{"action":"created","comment":{"url":"https://api.github.com/repos/facebook/stetho/pulls/comments/25309835","id":25309835,"diff_hunk":"@@ -2,30 +2,315 @@\n \n package com.facebook.stetho.inspector.protocol.module;\n \n+import android.util.SparseArray;\n+\n+import com.facebook.stetho.common.Util;\n+import com.facebook.stetho.inspector.helper.ChromePeerManager;\n import com.facebook.stetho.inspector.jsonrpc.JsonRpcPeer;\n import com.facebook.stetho.inspector.jsonrpc.JsonRpcResult;\n import com.facebook.stetho.inspector.protocol.ChromeDevtoolsDomain;\n import com.facebook.stetho.inspector.protocol.ChromeDevtoolsMethod;\n+import com.facebook.stetho.json.ObjectMapper;\n import com.facebook.stetho.json.annotation.JsonProperty;\n \n import org.json.JSONObject;\n \n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.HashMap;\n+import java.util.List;\n+import java.util.Map;\n+\n+import javax.annotation.Nullable;\n+import javax.annotation.concurrent.GuardedBy;\n+\n public class DOM implements ChromeDevtoolsDomain {\n-  public DOM() {\n+  private final Provider mDOMProvider;\n+  private final DOMPeerManager mPeerManager;\n+  private final ObjectMapper mObjectMapper;\n+\n+  private final Object mNodeMapSync = new Object();\n+\n+  @GuardedBy(\"mNodeMapSync\")\n+  private int mNextNodeId = 1;\n+\n+  @GuardedBy(\"mNodeMapSync\")\n+  private final Map<Object, Integer> mElementToNodeIdMap = new HashMap<>();\n+\n+  @GuardedBy(\"mNodeMapSync\")\n+  private final SparseArray<Object> mNodeIdToElementMap = new SparseArray<>();\n+\n+  public DOM(Provider provider) {\n+    mDOMProvider = Util.throwIfNull(provider);\n+    mDOMProvider.setListener(new ProviderListener());\n+\n+    mPeerManager = new DOMPeerManager();\n+    mObjectMapper = new ObjectMapper();\n+  }\n+\n+  private static final class DOMPeerManager extends ChromePeerManager {\n+    public DOMPeerManager() {\n+    }\n+  }\n+\n+  private final class ProviderListener implements Provider.Listener {\n+    @Override\n+    public void onAttributeModified(Object element, String name, String value) {\n+      AttributeModifiedEvent message = new AttributeModifiedEvent();\n+      message.nodeId = getOrCreateNodeIdForElement(element);\n+      message.name = name;\n+      message.value = value;\n+      mPeerManager.sendNotificationToPeers(\"DOM.attributeModified\", message);\n+    }\n+\n+    @Override\n+    public void onAttributeRemoved(Object element, String name) {\n+      AttributeRemovedEvent message = new AttributeRemovedEvent();\n+      message.nodeId = getOrCreateNodeIdForElement(element);\n+      message.name = name;\n+      mPeerManager.sendNotificationToPeers(\"DOM.attributeRemoved\", message);\n+    }\n+\n+    @Override\n+    public void onChildInserted(Object parentElement, Object previousElement, Object childElement) {\n+      ChildNodeInsertedEvent message = new ChildNodeInsertedEvent();\n+      message.parentNodeId = getOrCreateNodeIdForElement(parentElement);\n+\n+      message.previousNodeId = (previousElement == null)\n+          ? -1  // using -1 was just a guess, and it seemed to work. this is for the case where we\n+                // go from 0 to 1 children, or if we just happen to be inserting at index 0\n+          : getOrCreateNodeIdForElement(previousElement);\n+\n+      message.node = createNodeForElement(childElement);\n+      mPeerManager.sendNotificationToPeers(\"DOM.childNodeInserted\", message);\n+    }\n+\n+    @Override\n+    public void onChildRemoved(Object parentElement, Object childElement) {\n+      ChildNodeRemovedEvent message = new ChildNodeRemovedEvent();\n+      message.parentNodeId = getOrCreateNodeIdForElement(parentElement);\n+      message.nodeId = getOrCreateNodeIdForElement(childElement);\n+      mPeerManager.sendNotificationToPeers(\"DOM.childNodeRemoved\", message);\n+      unhookElement(childElement);\n+    }\n+  }\n+\n+  private static class AttributeModifiedEvent {\n+    @JsonProperty(required = true)\n+    public int nodeId;\n+\n+    @JsonProperty(required = true)\n+    public String name;\n+\n+    @JsonProperty(required = true)\n+    public String value;\n+  }\n+\n+  private static class AttributeRemovedEvent {\n+    @JsonProperty(required = true)\n+    public int nodeId;\n+\n+    @JsonProperty(required = true)\n+    public String name;\n+  }\n+\n+  private static class ChildNodeInsertedEvent {\n+    @JsonProperty(required = true)\n+    public int parentNodeId;\n+\n+    @JsonProperty(required = true)\n+    public int previousNodeId;\n+\n+    @JsonProperty(required = true)\n+    public Node node;\n+  }\n+\n+  private static class ChildNodeRemovedEvent {\n+    @JsonProperty(required = true)\n+    public int parentNodeId;\n+\n+    @JsonProperty(required = true)\n+    public int nodeId;\n+  }\n+\n+  @ChromeDevtoolsMethod\n+  public void enable(JsonRpcPeer peer, JSONObject params) {\n+    mPeerManager.addPeer(peer);\n+  }\n+\n+  @ChromeDevtoolsMethod\n+  public void disable(JsonRpcPeer peer, JSONObject params) {\n+    mPeerManager.removePeer(peer);\n   }\n \n   @ChromeDevtoolsMethod\n   public JsonRpcResult getDocument(JsonRpcPeer peer, JSONObject params) {\n-    Node node = new Node();\n-    node.nodeId = 1;\n-    node.nodeType = 1;\n-    node.nodeName = \"\";\n-    node.nodeValue = \"\";\n-    return node;\n+    Object rootElement = mDOMProvider.getRootElement();\n+    if (rootElement == null) {\n+      return null;\n+    }\n+\n+    Node rootNode = createNodeForElement(rootElement);\n+\n+    GetDocumentResponse result = new GetDocumentResponse();\n+    result.root = rootNode;\n+    return result;\n+  }\n+\n+  @ChromeDevtoolsMethod\n+  public void highlightNode(JsonRpcPeer peer, JSONObject params) {\n+    HighlightNodeRequest request = mObjectMapper.convertValue(params, HighlightNodeRequest.class);\n+    if (request.nodeId != null) {\n+      Object element = getElementForNodeId(request.nodeId);\n+      // TODO: pass in the HighlightConfig\n+      mDOMProvider.highlightElement(element);\n+    }\n   }\n \n   @ChromeDevtoolsMethod\n   public void hideHighlight(JsonRpcPeer peer, JSONObject params) {\n+    mDOMProvider.hideHighlight();\n+  }\n+\n+  public static class HighlightNodeRequest {\n+    @JsonProperty(required = true)\n+    public HighlightConfig highlightConfig;\n+\n+    @JsonProperty(required = false)\n+    public Integer nodeId;\n+\n+    @JsonProperty(required = false)\n+    public String objectId;\n+  }\n+\n+  public static class HighlightConfig {\n+    @JsonProperty(required = false)\n+    public Boolean showInfo;\n+\n+    @JsonProperty(required = false)\n+    public RGBAColor contentColor;\n+\n+    @JsonProperty(required = false)\n+    public RGBAColor paddingColor;\n+\n+    @JsonProperty(required = false)\n+    public RGBAColor borderColor;\n+\n+    @JsonProperty(required = false)\n+    public RGBAColor marginColor;\n+  }\n+\n+  public static class RGBAColor {\n+    @JsonProperty(required = true)\n+    public int r;\n+\n+    @JsonProperty(required = true)\n+    public int g;\n+\n+    @JsonProperty(required = true)\n+    public int b;\n+\n+    @JsonProperty(required = false)\n+    public Double a;\n+  }\n+\n+  private void unhookElement(Object element) {\n+    synchronized (mNodeMapSync) {\n+      int nodeId = mElementToNodeIdMap.get(element);\n+      mElementToNodeIdMap.remove(element);\n+      mNodeIdToElementMap.remove(nodeId);\n+    }\n+\n+    NodeDescriptor nodeDescriptor = mDOMProvider.getNodeDescriptor(element);\n+    nodeDescriptor.unhook(element);\n+    int childCount = nodeDescriptor.getChildCount(element);\n+    for (int i = 0; i < childCount; ++i) {\n+      Object childElement = nodeDescriptor.getChildAt(element, i);\n+      NodeDescriptor childNodeDescriptor = mDOMProvider.getNodeDescriptor(childElement);\n+      childNodeDescriptor.unhook(childElement);\n+    }\n+  }\n+\n+  private Object getElementForNodeId(int nodeId) {\n+    synchronized (mNodeMapSync) {\n+      return mNodeIdToElementMap.get(nodeId);\n+    }\n+  }\n+\n+  private int getOrCreateNodeIdForElement(Object element) {\n+    synchronized (mNodeMapSync) {\n+      if (mElementToNodeIdMap.containsKey(element)) {\n+        return mElementToNodeIdMap.get(element);\n+      }\n+\n+      Integer nodeId = mNextNodeId++;\n+      mElementToNodeIdMap.put(element, nodeId);\n+      mNodeIdToElementMap.put(nodeId, element);\n+\n+      NodeDescriptor nodeDescriptor = mDOMProvider.getNodeDescriptor(element);\n+      nodeDescriptor.hook(element);\n+\n+      return nodeId;\n+    }\n+  }\n+\n+  private Node createNodeForElement(Object element) {\n+    NodeDescriptor nodeDescriptor = mDOMProvider.getNodeDescriptor(element);\n+\n+    Node node = new Node();\n+    node.nodeId = getOrCreateNodeIdForElement(element);\n+    node.nodeType = nodeDescriptor.getNodeType(element).getValue();\n+    node.nodeName = nodeDescriptor.getNodeName(element);\n+    node.localName = nodeDescriptor.getLocalName(element);\n+    node.nodeValue = nodeDescriptor.getNodeValue(element);\n+\n+    node.children = getChildNodesForElement(element);\n+    node.childNodeCount = node.children.size();\n+\n+    int attributeCount = nodeDescriptor.getAttributeCount(element);\n+    if (attributeCount > 0) {\n+      node.attributes = new ArrayList<>(attributeCount * 2);","path":"stetho/src/main/java/com/facebook/stetho/inspector/protocol/module/DOM.java","position":278,"original_position":278,"commit_id":"f4189d0f7ea11e193c4745383bf706c50ed38b80","original_commit_id":"f4189d0f7ea11e193c4745383bf706c50ed38b80","user":{"login":"jasta","id":83791,"avatar_url":"https://avatars.githubusercontent.com/u/83791?v=3","gravatar_id":"","url":"https://api.github.com/users/jasta","html_url":"https://github.com/jasta","followers_url":"https://api.github.com/users/jasta/followers","following_url":"https://api.github.com/users/jasta/following{/other_user}","gists_url":"https://api.github.com/users/jasta/gists{/gist_id}","starred_url":"https://api.github.com/users/jasta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jasta/subscriptions","organizations_url":"https://api.github.com/users/jasta/orgs","repos_url":"https://api.github.com/users/jasta/repos","events_url":"https://api.github.com/users/jasta/events{/privacy}","received_events_url":"https://api.github.com/users/jasta/received_events","type":"User","site_admin":false},"body":"Danger.  We haven't yet resolved #44.  I can tackle this if you want, but it needs to be a precursor.","created_at":"2015-02-25T01:02:01Z","updated_at":"2015-02-25T01:02:01Z","html_url":"https://github.com/facebook/stetho/pull/73#discussion_r25309835","pull_request_url":"https://api.github.com/repos/facebook/stetho/pulls/73","_links":{"self":{"href":"https://api.github.com/repos/facebook/stetho/pulls/comments/25309835"},"html":{"href":"https://github.com/facebook/stetho/pull/73#discussion_r25309835"},"pull_request":{"href":"https://api.github.com/repos/facebook/stetho/pulls/73"}}},"pull_request":{"url":"https://api.github.com/repos/facebook/stetho/pulls/73","id":29939697,"html_url":"https://github.com/facebook/stetho/pull/73","diff_url":"https://github.com/facebook/stetho/pull/73.diff","patch_url":"https://github.com/facebook/stetho/pull/73.patch","issue_url":"https://api.github.com/repos/facebook/stetho/issues/73","number":73,"state":"open","locked":false,"title":"Initial check-in for Elements tab","user":{"login":"rickbrew","id":10873410,"avatar_url":"https://avatars.githubusercontent.com/u/10873410?v=3","gravatar_id":"","url":"https://api.github.com/users/rickbrew","html_url":"https://github.com/rickbrew","followers_url":"https://api.github.com/users/rickbrew/followers","following_url":"https://api.github.com/users/rickbrew/following{/other_user}","gists_url":"https://api.github.com/users/rickbrew/gists{/gist_id}","starred_url":"https://api.github.com/users/rickbrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rickbrew/subscriptions","organizations_url":"https://api.github.com/users/rickbrew/orgs","repos_url":"https://api.github.com/users/rickbrew/repos","events_url":"https://api.github.com/users/rickbrew/events{/privacy}","received_events_url":"https://api.github.com/users/rickbrew/received_events","type":"User","site_admin":false},"body":"This is a first stab at providing an Elements tab for Stetho.\r\n\r\nThe DOM class handles the JSON protocol and element <--> node ID mapping. An element is meant to be a real object in whatever DOM-type tree is being plugged in via a DOM.Provider implementation. We implement this in UIDOMProvider and our \"DOM-type tree\" is an Android application. We use the android.app.Application as the root of the DOM, its children are the android.app.Activity instances (initial list retrieved via a hack, then updated via Application.ActivityLifecycleCallbacks), then the android.view.Window and finally its android.view.View tree.\r\n\r\nWe use DOM.NodeDescriptor to describe an element in terms of a node (DOM.Node). In UIDOMProvider we use the element's class to figure out which descriptor(s) to use, but another DOM.Provider implementation could potentially choose another strategy.\r\n\r\nFor instance, an android.view.ViewGroup is an \"element.\" ViewGroupNodeDescriptor knows how to describe it in DOM.Node terms (name, children), and how to hook into it (with ViewGroup.OnHierarchyChangedListener) in order to report updates (via DOM.childNodeInserted / DOM.childNodeRemoved). Also participating in this are ViewNodeDescriptor (technically anyway, since it's currently empty) and ObjectNodeDescriptor (mostly just knows how to shorten class names to remove all the \"android.*.*\" package name noise).\r\n\r\nIn the Elements tab you can mouse-over a node and it will cause the Android device to draw a red highlight over the corresponding View. This is ultimately handled in the WindowNodeDescriptor class because that's where the highlighting View is installed (and uninstalled).\r\n\r\n![screen shot 2015-02-24 at 1 27 13 pm](https://cloud.githubusercontent.com/assets/10873410/6359566/06d20ef2-bc29-11e4-8f81-1857c90f0680.png)","created_at":"2015-02-24T21:53:30Z","updated_at":"2015-02-25T01:02:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e95a6cea66cc71cbe7ee85d55ac9bd37b5e899b5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/facebook/stetho/pulls/73/commits","review_comments_url":"https://api.github.com/repos/facebook/stetho/pulls/73/comments","review_comment_url":"https://api.github.com/repos/facebook/stetho/pulls/comments{/number}","comments_url":"https://api.github.com/repos/facebook/stetho/issues/73/comments","statuses_url":"https://api.github.com/repos/facebook/stetho/statuses/f4189d0f7ea11e193c4745383bf706c50ed38b80","head":{"label":"rickbrew:elements","ref":"elements","sha":"f4189d0f7ea11e193c4745383bf706c50ed38b80","user":{"login":"rickbrew","id":10873410,"avatar_url":"https://avatars.githubusercontent.com/u/10873410?v=3","gravatar_id":"","url":"https://api.github.com/users/rickbrew","html_url":"https://github.com/rickbrew","followers_url":"https://api.github.com/users/rickbrew/followers","following_url":"https://api.github.com/users/rickbrew/following{/other_user}","gists_url":"https://api.github.com/users/rickbrew/gists{/gist_id}","starred_url":"https://api.github.com/users/rickbrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rickbrew/subscriptions","organizations_url":"https://api.github.com/users/rickbrew/orgs","repos_url":"https://api.github.com/users/rickbrew/repos","events_url":"https://api.github.com/users/rickbrew/events{/privacy}","received_events_url":"https://api.github.com/users/rickbrew/received_events","type":"User","site_admin":false},"repo":{"id":30989042,"name":"stetho","full_name":"rickbrew/stetho","owner":{"login":"rickbrew","id":10873410,"avatar_url":"https://avatars.githubusercontent.com/u/10873410?v=3","gravatar_id":"","url":"https://api.github.com/users/rickbrew","html_url":"https://github.com/rickbrew","followers_url":"https://api.github.com/users/rickbrew/followers","following_url":"https://api.github.com/users/rickbrew/following{/other_user}","gists_url":"https://api.github.com/users/rickbrew/gists{/gist_id}","starred_url":"https://api.github.com/users/rickbrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rickbrew/subscriptions","organizations_url":"https://api.github.com/users/rickbrew/orgs","repos_url":"https://api.github.com/users/rickbrew/repos","events_url":"https://api.github.com/users/rickbrew/events{/privacy}","received_events_url":"https://api.github.com/users/rickbrew/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rickbrew/stetho","description":"Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.","fork":true,"url":"https://api.github.com/repos/rickbrew/stetho","forks_url":"https://api.github.com/repos/rickbrew/stetho/forks","keys_url":"https://api.github.com/repos/rickbrew/stetho/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rickbrew/stetho/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rickbrew/stetho/teams","hooks_url":"https://api.github.com/repos/rickbrew/stetho/hooks","issue_events_url":"https://api.github.com/repos/rickbrew/stetho/issues/events{/number}","events_url":"https://api.github.com/repos/rickbrew/stetho/events","assignees_url":"https://api.github.com/repos/rickbrew/stetho/assignees{/user}","branches_url":"https://api.github.com/repos/rickbrew/stetho/branches{/branch}","tags_url":"https://api.github.com/repos/rickbrew/stetho/tags","blobs_url":"https://api.github.com/repos/rickbrew/stetho/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rickbrew/stetho/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rickbrew/stetho/git/refs{/sha}","trees_url":"https://api.github.com/repos/rickbrew/stetho/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rickbrew/stetho/statuses/{sha}","languages_url":"https://api.github.com/repos/rickbrew/stetho/languages","stargazers_url":"https://api.github.com/repos/rickbrew/stetho/stargazers","contributors_url":"https://api.github.com/repos/rickbrew/stetho/contributors","subscribers_url":"https://api.github.com/repos/rickbrew/stetho/subscribers","subscription_url":"https://api.github.com/repos/rickbrew/stetho/subscription","commits_url":"https://api.github.com/repos/rickbrew/stetho/commits{/sha}","git_commits_url":"https://api.github.com/repos/rickbrew/stetho/git/commits{/sha}","comments_url":"https://api.github.com/repos/rickbrew/stetho/comments{/number}","issue_comment_url":"https://api.github.com/repos/rickbrew/stetho/issues/comments{/number}","contents_url":"https://api.github.com/repos/rickbrew/stetho/contents/{+path}","compare_url":"https://api.github.com/repos/rickbrew/stetho/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rickbrew/stetho/merges","archive_url":"https://api.github.com/repos/rickbrew/stetho/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rickbrew/stetho/downloads","issues_url":"https://api.github.com/repos/rickbrew/stetho/issues{/number}","pulls_url":"https://api.github.com/repos/rickbrew/stetho/pulls{/number}","milestones_url":"https://api.github.com/repos/rickbrew/stetho/milestones{/number}","notifications_url":"https://api.github.com/repos/rickbrew/stetho/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rickbrew/stetho/labels{/name}","releases_url":"https://api.github.com/repos/rickbrew/stetho/releases{/id}","created_at":"2015-02-18T21:52:05Z","updated_at":"2015-02-18T21:52:06Z","pushed_at":"2015-02-24T21:08:43Z","git_url":"git://github.com/rickbrew/stetho.git","ssh_url":"git@github.com:rickbrew/stetho.git","clone_url":"https://github.com/rickbrew/stetho.git","svn_url":"https://github.com/rickbrew/stetho","homepage":"http://facebook.github.io/stetho/","size":690,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"facebook:elements","ref":"elements","sha":"84efa0c17a81d165cb63b1d64a79315bc8d06a47","user":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"repo":{"id":29703871,"name":"stetho","full_name":"facebook/stetho","owner":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/facebook/stetho","description":"Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.","fork":false,"url":"https://api.github.com/repos/facebook/stetho","forks_url":"https://api.github.com/repos/facebook/stetho/forks","keys_url":"https://api.github.com/repos/facebook/stetho/keys{/key_id}","collaborators_url":"https://api.github.com/repos/facebook/stetho/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/facebook/stetho/teams","hooks_url":"https://api.github.com/repos/facebook/stetho/hooks","issue_events_url":"https://api.github.com/repos/facebook/stetho/issues/events{/number}","events_url":"https://api.github.com/repos/facebook/stetho/events","assignees_url":"https://api.github.com/repos/facebook/stetho/assignees{/user}","branches_url":"https://api.github.com/repos/facebook/stetho/branches{/branch}","tags_url":"https://api.github.com/repos/facebook/stetho/tags","blobs_url":"https://api.github.com/repos/facebook/stetho/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/facebook/stetho/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/facebook/stetho/git/refs{/sha}","trees_url":"https://api.github.com/repos/facebook/stetho/git/trees{/sha}","statuses_url":"https://api.github.com/repos/facebook/stetho/statuses/{sha}","languages_url":"https://api.github.com/repos/facebook/stetho/languages","stargazers_url":"https://api.github.com/repos/facebook/stetho/stargazers","contributors_url":"https://api.github.com/repos/facebook/stetho/contributors","subscribers_url":"https://api.github.com/repos/facebook/stetho/subscribers","subscription_url":"https://api.github.com/repos/facebook/stetho/subscription","commits_url":"https://api.github.com/repos/facebook/stetho/commits{/sha}","git_commits_url":"https://api.github.com/repos/facebook/stetho/git/commits{/sha}","comments_url":"https://api.github.com/repos/facebook/stetho/comments{/number}","issue_comment_url":"https://api.github.com/repos/facebook/stetho/issues/comments{/number}","contents_url":"https://api.github.com/repos/facebook/stetho/contents/{+path}","compare_url":"https://api.github.com/repos/facebook/stetho/compare/{base}...{head}","merges_url":"https://api.github.com/repos/facebook/stetho/merges","archive_url":"https://api.github.com/repos/facebook/stetho/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/facebook/stetho/downloads","issues_url":"https://api.github.com/repos/facebook/stetho/issues{/number}","pulls_url":"https://api.github.com/repos/facebook/stetho/pulls{/number}","milestones_url":"https://api.github.com/repos/facebook/stetho/milestones{/number}","notifications_url":"https://api.github.com/repos/facebook/stetho/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/facebook/stetho/labels{/name}","releases_url":"https://api.github.com/repos/facebook/stetho/releases{/id}","created_at":"2015-01-22T22:34:10Z","updated_at":"2015-02-25T01:00:05Z","pushed_at":"2015-02-24T21:22:09Z","git_url":"git://github.com/facebook/stetho.git","ssh_url":"git@github.com:facebook/stetho.git","clone_url":"https://github.com/facebook/stetho.git","svn_url":"https://github.com/facebook/stetho","homepage":"http://facebook.github.io/stetho/","size":1700,"stargazers_count":1454,"watchers_count":1454,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":72,"mirror_url":null,"open_issues_count":16,"forks":72,"open_issues":16,"watchers":1454,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/facebook/stetho/pulls/73"},"html":{"href":"https://github.com/facebook/stetho/pull/73"},"issue":{"href":"https://api.github.com/repos/facebook/stetho/issues/73"},"comments":{"href":"https://api.github.com/repos/facebook/stetho/issues/73/comments"},"review_comments":{"href":"https://api.github.com/repos/facebook/stetho/pulls/73/comments"},"review_comment":{"href":"https://api.github.com/repos/facebook/stetho/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/facebook/stetho/pulls/73/commits"},"statuses":{"href":"https://api.github.com/repos/facebook/stetho/statuses/f4189d0f7ea11e193c4745383bf706c50ed38b80"}}}}