{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/bedrock/pulls/comments/27643010","id":27643010,"diff_hunk":"@@ -0,0 +1,277 @@\n+/*globals Utils */\n+\n+(function(exports) {\n+\n+    var clientOS = Utils.getOS(navigator.userAgent);\n+\n+    /**\n+     * Java plugin version numbers are exposed with a leading 1. which obscures\n+     * the actual version number we will find in the plugincheck database. This\n+     * removes the leading bits and returns the 'real' version number.\n+     * @returns The Java version number excluding the leading 1.\n+     */\n+    function setJavaVersion() {\n+        var mimes = navigator.mimeTypes[\"application/x-java-applet\"].enabledPlugin;\n+\n+        for (var mime in mimes) {\n+            if(mimes.hasOwnProperty(mime) && mime.indexOf('jpi-version') > -1) {\n+                var type = mime;\n+                // + 3 to strip of the leading 1. in java versions\n+                installedVersion = type.substring(type.indexOf('=') + 3)\n+                    .replace('_', '.');\n+            }\n+        }\n+        return installedVersion;\n+    }\n+\n+    /**\n+    * Creates and populates a plugin object for an unknown plugin.\n+    * @param {object} pluginInfo - Information about the plugin from the plugins DB\n+    * @param {object} currentPlugin - The current installed plugin with info from the browser.\n+    * @returns The unknown plugin as an object\n+    */\n+    function populateUnknownPlugin (currentPlugin) {\n+        return {\n+            name: currentPlugin.name,\n+            version: currentPlugin.version,\n+            description: currentPlugin.description,\n+            status: 'unknown'\n+        };\n+    }\n+\n+    /**\n+     * Sets the status of the current plugin.\n+     *\n+     * @param {object} plugin - The plugin object to update\n+     * @param {string} installedVersion - Version of the current installed plugin\n+     * @param {array} knownVersions - Array of all known versions\n+     *\n+     * @returns the updated plugin object with the status set. For vulnerable\n+     * plugins, the vulnerability_description and vulnerability_url fields are\n+     * also set.\n+     */\n+     function setPluginStatus (plugin, installedVersion, knownVersions) {\n+        // sort versions from low to high\n+        knownVersions.latest.sort(function(v1, v2) {\n+            // TODO: the server currently returns some versions with a leading\n+            // space, therefore the trim workaround is currently required.\n+            // Remove the trims once the backend rewrite is done.\n+            return versionCompare($.trim(v1.version), $.trim(v2.version));\n+        });\n+\n+        // store the absolutly latest known version.\n+        var knownAbsLatest = knownVersions.latest[knownVersions.latest.length - 1].version;\n+\n+        if (Utils.isMatch(installedVersion, knownVersions.latest)) {\n+\n+            plugin['status'] = 'latest';\n+            return plugin;\n+\n+        } else if (Utils.isMatch(installedVersion, knownVersions.vulnerable)) {\n+\n+            var vulnerableInfo = Utils.isMatch(installedVersion, knownVersions.vulnerable);\n+            plugin['status'] = 'vulnerable';\n+            plugin['vulnerability_description'] = vulnerableInfo.vulnerability_description;\n+            plugin['vulnerability_url'] = vulnerableInfo.vulnerability_url;\n+\n+            return plugin;\n+\n+        } else if (!(installedVersion > knownAbsLatest)) {\n+\n+            // it is not the latest but also not vulnerable so, just outdated\n+            plugin['status'] = 'outdated';\n+            return plugin;\n+\n+        } else if (installedVersion > knownAbsLatest) {\n+\n+            // if newer than our known absolutely latest version, set status as newer but currently,\n+            // it will still show up as up to date (latest) in the UI\n+            plugin['status'] = 'newer';\n+            return plugin;\n+        }\n+    }\n+\n+    var PluginCheck = {\n+        /**\n+        * Returns the latest and vulnrable known versions for the current plugin.\n+        * @params {object} knownPluginReleases\n+        * @returns The latest and vulnerable versions for this plugin.\n+        */\n+        getKnownVersionInfo:function (knownPluginReleases) {\n+            var latest;\n+            var vulnerable;\n+\n+            // See whether we have data for the current OS\n+            if (knownPluginReleases.hasOwnProperty(clientOS)) {\n+\n+                // Combine all release for the current OS and\n+                // versions marked for all operating systems.\n+                latest = knownPluginReleases[clientOS].latest.concat(\n+                    knownPluginReleases['all'].latest\n+                );\n+                vulnerable = knownPluginReleases[clientOS].vulnerable.concat(\n+                    knownPluginReleases['all'].vulnerable\n+                );\n+            } else if (knownPluginReleases.hasOwnProperty('all')) {\n+                latest = knownPluginReleases['all'].latest;\n+                vulnerable = knownPluginReleases['all'].vulnerable;\n+            }\n+\n+            return { latest: latest, vulnerable: vulnerable };\n+        },\n+        /**\n+        * Populate the plugin object with the required data for the UI.\n+        * @param {object} pluginInfo - Information about the plugin from the plugins DB\n+        * @param {object} currentPlugin - The current installed plugin with info from the browser.\n+        * @returns The populated plugin object\n+        */\n+        populatePluginObject: function(pluginInfo, currentPlugin) {\n+            var installedVersion = currentPlugin.version;\n+\n+            if (currentPlugin.name.indexOf('Java') > -1 &&\n+                'undefined' !== navigator.mimeTypes[\"application/x-java-applet\"]) {\n+                    // we need todo some extra work to get a decent version number\n+                    installedVersion = setJavaVersion();\n+            }\n+\n+            var plugin = {};\n+            var knownVersions = PluginCheck.getKnownVersionInfo(pluginInfo.versions);\n+            var description = pluginInfo.description || currentPlugin.description;\n+\n+            plugin = {\n+                name: pluginInfo.display_name,\n+                version: installedVersion,\n+                description: description,\n+                url: pluginInfo.url\n+            };\n+\n+            return setPluginStatus(plugin, installedVersion, knownVersions);\n+        },\n+        /**\n+        * Determines whether we are dealing with one of the known plugins and returns it,\n+        * or false if this is not a known plugin.\n+        * @param {array} knownPlugins - Array of known plugins\n+        * @param {object} currentPlugin - The current installed plugin to test.\n+        * @returns The knownPlugin object or false\n+        */\n+        isKnownPlugin: function (knownPlugins, currentPlugin) {\n+\n+            for (var plugin in knownPlugins) {\n+                if(knownPlugins.hasOwnProperty(plugin)) {\n+                    var knownPluginName = knownPlugins[plugin].display_name;\n+                    var patterns = [];\n+\n+                    // For some plugins a regex is needed to match the name,\n+                    // see if it is the case for the current plugin.\n+                    if (knownPlugins[plugin].regex.length) {\n+                        patterns = knownPlugins[plugin].regex;\n+                    }\n+\n+                    var patternsLength = patterns.length;\n+                    if (patternsLength) {\n+                        for (var i = 0; i < patternsLength; i++) {\n+                            var re = new RegExp(patterns[i], 'g');\n+\n+                            if (re.test(currentPlugin.name)) {\n+                                return knownPlugins[plugin];\n+                            }\n+                        }\n+                    } else if (knownPluginName.indexOf(currentPlugin.name) > -1) {\n+                        return knownPlugins[plugin];\n+                    }\n+                }\n+            }\n+            return false;\n+        },\n+        /**\n+         * On Linux the Totem plugin handles Quicktime video but, it masquerade's\n+         * as the either the Quicktime player or the Windows Media player by\n+         * setting it's name accordingly. This causes problems when checking the\n+         * list of known plugins, hence we need this check to determine it's real\n+         * identity by looking at the filename for the enabledPlugin.\n+         *\n+         * @params {string} filename - The filename to check for libtotem\n+         * @returns {boolean} True if it is Totem else false\n+         */\n+        isTotem: function(filename) {\n+\n+            var totemQuicktime = filename.indexOf('libtotem-narrowspace');\n+            var totemWindowsMedia = filename.indexOf('libtotem-gmp');\n+\n+            if (totemQuicktime > -1 || totemWindowsMedia > -1) {\n+                return true;\n+            }\n+\n+            return false;\n+        },\n+        /**\n+        * Get's a list of plugins and versions as a JSON object from the database. Iterates over\n+        * navigator.mimeTypes to gather the installed plugins. For each known plugin, it\n+        * determines whether the version is the latest, is outdated or vulnerable.\n+        * @param {string} endpoint - The JSON endpoint exposed by the plugins database service.\n+        * @returns pluginList - List of known and unknown plugins\n+        */\n+        getPluginsStatus: function(endpoint, callback) {\n+\n+            // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1131137\n+            navigator.plugins.refresh();\n+\n+            $.getJSON(endpoint, function(data) {\n+\n+                var pluginNames = [];\n+                var installedPlugins = [];\n+                var pluginList = [];\n+\n+                var mimes = navigator.mimeTypes;\n+                var knownPlugins = data.plugins;\n+\n+                for (var i = 0, l = mimes.length; i < l; i++) {\n+                    var currentMime = mimes[i];\n+                    var pluginData = {};\n+\n+                    if(typeof currentMime !== 'undefined' && currentMime.enabledPlugin) {\n+                        var enabledPlugin = currentMime.enabledPlugin;\n+                        var pluginName = enabledPlugin.name;\n+\n+                        // on Linux we need to check whether this in fact the totem plugin?\n+                        if (clientOS === 'lin' && PluginCheck.isTotem(enabledPlugin.filename)) {\n+                            pluginName = 'Totem';\n+                        }\n+\n+                        if($.inArray(enabledPlugin.name, pluginNames) === -1) {\n+                            pluginData = {\n+                                name: pluginName,\n+                                version: enabledPlugin.version,\n+                                description: enabledPlugin.description\n+                            };\n+\n+                            installedPlugins.push(pluginData);\n+                            pluginNames.push(enabledPlugin.name);\n+                        }\n+                    }\n+                }\n+\n+                for (i = 0, l = installedPlugins.length; i < l; i++) {\n+                    var currentInstalledPlugin = installedPlugins[i];\n+                    var pluginInfo = PluginCheck.isKnownPlugin(knownPlugins, currentInstalledPlugin);\n+\n+                    if (pluginInfo) {\n+                        pluginList.push(PluginCheck.populatePluginObject(pluginInfo, currentInstalledPlugin));\n+                    } else {\n+                        pluginList.push(populateUnknownPlugin(currentInstalledPlugin));\n+                    }\n+                }\n+\n+                callback(pluginList);\n+\n+            }).fail(function(xhr, status, error) {\n+                console.log('xhr', xhr);","path":"media/js/plugincheck/lib/plugincheck.js","position":268,"original_position":268,"commit_id":"08b71e6a28f0bf9e5bffdd5b9813aa9bade2ef85","original_commit_id":"08b71e6a28f0bf9e5bffdd5b9813aa9bade2ef85","user":{"login":"alexgibson","id":400117,"avatar_url":"https://avatars.githubusercontent.com/u/400117?v=3","gravatar_id":"","url":"https://api.github.com/users/alexgibson","html_url":"https://github.com/alexgibson","followers_url":"https://api.github.com/users/alexgibson/followers","following_url":"https://api.github.com/users/alexgibson/following{/other_user}","gists_url":"https://api.github.com/users/alexgibson/gists{/gist_id}","starred_url":"https://api.github.com/users/alexgibson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexgibson/subscriptions","organizations_url":"https://api.github.com/users/alexgibson/orgs","repos_url":"https://api.github.com/users/alexgibson/repos","events_url":"https://api.github.com/users/alexgibson/events{/privacy}","received_events_url":"https://api.github.com/users/alexgibson/received_events","type":"User","site_admin":false},"body":"We don't usually leave calls to `console` in production code, but seeing as page will be available to just Firefox users and it's limited to error logging, I guess we could leave this in.","created_at":"2015-04-02T09:28:15Z","updated_at":"2015-04-02T09:28:15Z","html_url":"https://github.com/mozilla/bedrock/pull/2828#discussion_r27643010","pull_request_url":"https://api.github.com/repos/mozilla/bedrock/pulls/2828","_links":{"self":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/comments/27643010"},"html":{"href":"https://github.com/mozilla/bedrock/pull/2828#discussion_r27643010"},"pull_request":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/2828"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/bedrock/pulls/2828","id":30940680,"html_url":"https://github.com/mozilla/bedrock/pull/2828","diff_url":"https://github.com/mozilla/bedrock/pull/2828.diff","patch_url":"https://github.com/mozilla/bedrock/pull/2828.patch","issue_url":"https://api.github.com/repos/mozilla/bedrock/issues/2828","number":2828,"state":"open","locked":false,"title":"WIP Bug 1121460, move all plugincheck client side code into bedrock","user":{"login":"schalkneethling","id":10350960,"avatar_url":"https://avatars.githubusercontent.com/u/10350960?v=3","gravatar_id":"","url":"https://api.github.com/users/schalkneethling","html_url":"https://github.com/schalkneethling","followers_url":"https://api.github.com/users/schalkneethling/followers","following_url":"https://api.github.com/users/schalkneethling/following{/other_user}","gists_url":"https://api.github.com/users/schalkneethling/gists{/gist_id}","starred_url":"https://api.github.com/users/schalkneethling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schalkneethling/subscriptions","organizations_url":"https://api.github.com/users/schalkneethling/orgs","repos_url":"https://api.github.com/users/schalkneethling/repos","events_url":"https://api.github.com/users/schalkneethling/events{/privacy}","received_events_url":"https://api.github.com/users/schalkneethling/received_events","type":"User","site_admin":false},"body":"This is a WIP, do not merge. This will move all of the client side code for plugincheck into bedrock and also adds actual real life tests \\o/ More to come.","created_at":"2015-03-11T13:03:42Z","updated_at":"2015-04-02T09:28:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d06fe01a7ae7b56a1c055f74c3214a8e46a3b8ef","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/bedrock/pulls/2828/commits","review_comments_url":"https://api.github.com/repos/mozilla/bedrock/pulls/2828/comments","review_comment_url":"https://api.github.com/repos/mozilla/bedrock/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/bedrock/issues/2828/comments","statuses_url":"https://api.github.com/repos/mozilla/bedrock/statuses/08b71e6a28f0bf9e5bffdd5b9813aa9bade2ef85","head":{"label":"schalkneethling:bug1121460-move-plugincheck-clientside-into-bedrock","ref":"bug1121460-move-plugincheck-clientside-into-bedrock","sha":"08b71e6a28f0bf9e5bffdd5b9813aa9bade2ef85","user":{"login":"schalkneethling","id":10350960,"avatar_url":"https://avatars.githubusercontent.com/u/10350960?v=3","gravatar_id":"","url":"https://api.github.com/users/schalkneethling","html_url":"https://github.com/schalkneethling","followers_url":"https://api.github.com/users/schalkneethling/followers","following_url":"https://api.github.com/users/schalkneethling/following{/other_user}","gists_url":"https://api.github.com/users/schalkneethling/gists{/gist_id}","starred_url":"https://api.github.com/users/schalkneethling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schalkneethling/subscriptions","organizations_url":"https://api.github.com/users/schalkneethling/orgs","repos_url":"https://api.github.com/users/schalkneethling/repos","events_url":"https://api.github.com/users/schalkneethling/events{/privacy}","received_events_url":"https://api.github.com/users/schalkneethling/received_events","type":"User","site_admin":false},"repo":{"id":4284689,"name":"bedrock","full_name":"schalkneethling/bedrock","owner":{"login":"schalkneethling","id":10350960,"avatar_url":"https://avatars.githubusercontent.com/u/10350960?v=3","gravatar_id":"","url":"https://api.github.com/users/schalkneethling","html_url":"https://github.com/schalkneethling","followers_url":"https://api.github.com/users/schalkneethling/followers","following_url":"https://api.github.com/users/schalkneethling/following{/other_user}","gists_url":"https://api.github.com/users/schalkneethling/gists{/gist_id}","starred_url":"https://api.github.com/users/schalkneethling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schalkneethling/subscriptions","organizations_url":"https://api.github.com/users/schalkneethling/orgs","repos_url":"https://api.github.com/users/schalkneethling/repos","events_url":"https://api.github.com/users/schalkneethling/events{/privacy}","received_events_url":"https://api.github.com/users/schalkneethling/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/schalkneethling/bedrock","description":"Making mozilla.org awesome, one pebble at a time","fork":true,"url":"https://api.github.com/repos/schalkneethling/bedrock","forks_url":"https://api.github.com/repos/schalkneethling/bedrock/forks","keys_url":"https://api.github.com/repos/schalkneethling/bedrock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/schalkneethling/bedrock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/schalkneethling/bedrock/teams","hooks_url":"https://api.github.com/repos/schalkneethling/bedrock/hooks","issue_events_url":"https://api.github.com/repos/schalkneethling/bedrock/issues/events{/number}","events_url":"https://api.github.com/repos/schalkneethling/bedrock/events","assignees_url":"https://api.github.com/repos/schalkneethling/bedrock/assignees{/user}","branches_url":"https://api.github.com/repos/schalkneethling/bedrock/branches{/branch}","tags_url":"https://api.github.com/repos/schalkneethling/bedrock/tags","blobs_url":"https://api.github.com/repos/schalkneethling/bedrock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/schalkneethling/bedrock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/schalkneethling/bedrock/git/refs{/sha}","trees_url":"https://api.github.com/repos/schalkneethling/bedrock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/schalkneethling/bedrock/statuses/{sha}","languages_url":"https://api.github.com/repos/schalkneethling/bedrock/languages","stargazers_url":"https://api.github.com/repos/schalkneethling/bedrock/stargazers","contributors_url":"https://api.github.com/repos/schalkneethling/bedrock/contributors","subscribers_url":"https://api.github.com/repos/schalkneethling/bedrock/subscribers","subscription_url":"https://api.github.com/repos/schalkneethling/bedrock/subscription","commits_url":"https://api.github.com/repos/schalkneethling/bedrock/commits{/sha}","git_commits_url":"https://api.github.com/repos/schalkneethling/bedrock/git/commits{/sha}","comments_url":"https://api.github.com/repos/schalkneethling/bedrock/comments{/number}","issue_comment_url":"https://api.github.com/repos/schalkneethling/bedrock/issues/comments{/number}","contents_url":"https://api.github.com/repos/schalkneethling/bedrock/contents/{+path}","compare_url":"https://api.github.com/repos/schalkneethling/bedrock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/schalkneethling/bedrock/merges","archive_url":"https://api.github.com/repos/schalkneethling/bedrock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/schalkneethling/bedrock/downloads","issues_url":"https://api.github.com/repos/schalkneethling/bedrock/issues{/number}","pulls_url":"https://api.github.com/repos/schalkneethling/bedrock/pulls{/number}","milestones_url":"https://api.github.com/repos/schalkneethling/bedrock/milestones{/number}","notifications_url":"https://api.github.com/repos/schalkneethling/bedrock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/schalkneethling/bedrock/labels{/name}","releases_url":"https://api.github.com/repos/schalkneethling/bedrock/releases{/id}","created_at":"2012-05-10T13:21:55Z","updated_at":"2015-03-23T13:38:03Z","pushed_at":"2015-03-31T14:10:48Z","git_url":"git://github.com/schalkneethling/bedrock.git","ssh_url":"git@github.com:schalkneethling/bedrock.git","clone_url":"https://github.com/schalkneethling/bedrock.git","svn_url":"https://github.com/schalkneethling/bedrock","homepage":"http://mozilla.org","size":299979,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"e916f902ad708a31cff33092a29c40c9ada25ee2","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":1616665,"name":"bedrock","full_name":"mozilla/bedrock","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/bedrock","description":"Making mozilla.org awesome, one pebble at a time","fork":false,"url":"https://api.github.com/repos/mozilla/bedrock","forks_url":"https://api.github.com/repos/mozilla/bedrock/forks","keys_url":"https://api.github.com/repos/mozilla/bedrock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/bedrock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/bedrock/teams","hooks_url":"https://api.github.com/repos/mozilla/bedrock/hooks","issue_events_url":"https://api.github.com/repos/mozilla/bedrock/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/bedrock/events","assignees_url":"https://api.github.com/repos/mozilla/bedrock/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/bedrock/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/bedrock/tags","blobs_url":"https://api.github.com/repos/mozilla/bedrock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/bedrock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/bedrock/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/bedrock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/bedrock/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/bedrock/languages","stargazers_url":"https://api.github.com/repos/mozilla/bedrock/stargazers","contributors_url":"https://api.github.com/repos/mozilla/bedrock/contributors","subscribers_url":"https://api.github.com/repos/mozilla/bedrock/subscribers","subscription_url":"https://api.github.com/repos/mozilla/bedrock/subscription","commits_url":"https://api.github.com/repos/mozilla/bedrock/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/bedrock/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/bedrock/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/bedrock/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/bedrock/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/bedrock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/bedrock/merges","archive_url":"https://api.github.com/repos/mozilla/bedrock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/bedrock/downloads","issues_url":"https://api.github.com/repos/mozilla/bedrock/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/bedrock/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/bedrock/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/bedrock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/bedrock/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/bedrock/releases{/id}","created_at":"2011-04-14T22:57:57Z","updated_at":"2015-04-02T00:26:41Z","pushed_at":"2015-04-02T00:26:40Z","git_url":"git://github.com/mozilla/bedrock.git","ssh_url":"git@github.com:mozilla/bedrock.git","clone_url":"https://github.com/mozilla/bedrock.git","svn_url":"https://github.com/mozilla/bedrock","homepage":"http://mozilla.org","size":347266,"stargazers_count":222,"watchers_count":222,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":316,"mirror_url":null,"open_issues_count":15,"forks":316,"open_issues":15,"watchers":222,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/2828"},"html":{"href":"https://github.com/mozilla/bedrock/pull/2828"},"issue":{"href":"https://api.github.com/repos/mozilla/bedrock/issues/2828"},"comments":{"href":"https://api.github.com/repos/mozilla/bedrock/issues/2828/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/2828/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/bedrock/pulls/2828/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/bedrock/statuses/08b71e6a28f0bf9e5bffdd5b9813aa9bade2ef85"}}}}