pax_global_header00006660000000000000000000000064124353747120014522gustar00rootroot0000000000000052 comment=72ac00ec292192c9be5558cd8bb3a95b37cc296a moz-spdy-indicator-2.2/000077500000000000000000000000001243537471200151215ustar00rootroot00000000000000moz-spdy-indicator-2.2/README.md000066400000000000000000000014771243537471200164110ustar00rootroot00000000000000Firefox extension to add an SPDY support indicator in the address bar. Inspired by http://www.devthought.com/2012/03/10/chrome-spdy-indicator/ This extension is [now on AMO](https://addons.mozilla.org/en-US/firefox/addon/spdy-indicator/). Address bar icon by http://glyphicons.com/ - CC license. ## License DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Copyright (C) 2004 Sam Hocevar Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. moz-spdy-indicator-2.2/bootstrap.js000066400000000000000000000011141243537471200174710ustar00rootroot00000000000000const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/Services.jsm"); function startup(data, reason) { Cu.import("chrome://spdyindicator/content/indicator.jsm"); SPDYManager.startup(); } function shutdown(data, reason) { if (reason == APP_SHUTDOWN) return; Cu.import("chrome://spdyindicator/content/indicator.jsm"); SPDYManager.shutdown(); Cu.unload("chrome://spdyindicator/content/indicator.jsm"); } function install(data, reason) { // o hai there new friend! :D } function uninstall(data, reason) { // y u do this to me :( } moz-spdy-indicator-2.2/chrome.manifest000066400000000000000000000001761243537471200201320ustar00rootroot00000000000000content spdyindicator chrome/content/ locale spdyindicator en-US chrome/locale/en-US/ skin spdyindicator default chrome/skin/ moz-spdy-indicator-2.2/chrome/000077500000000000000000000000001243537471200163765ustar00rootroot00000000000000moz-spdy-indicator-2.2/chrome/content/000077500000000000000000000000001243537471200200505ustar00rootroot00000000000000moz-spdy-indicator-2.2/chrome/content/indicator.jsm000066400000000000000000000272241243537471200225460ustar00rootroot00000000000000var EXPORTED_SYMBOLS = ["SPDYManager"]; const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/Services.jsm"); // this is kludgy: in order to prevent unbounded memory growth, // we limit the number of SPDY-requested prePaths to this number const SPDYREQUESTS_MAXSIZE = 20; function getLoadContext(request) { let loadContext = null; try { loadContext = request.QueryInterface(Ci.nsIChannel) .notificationCallbacks .getInterface(Ci.nsILoadContext); } catch (e) { try { loadContext = request.loadGroup .notificationCallbacks .getInterface(Ci.nsILoadContext); } catch (e) {} } if (!loadContext) return null; return loadContext.associatedWindow; } // get the chrome window from a content window function getChromeWindow(domWindow) { return domWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); } const prefBranchName = "extensions.spdyindicator."; var SPDYManager = { // private indicators: [], branch: Services.prefs.getBranch(prefBranchName), createIndicator: function (window) { let indicator = new SPDYIndicator(window); indicator.start(); this.indicators.push(indicator); return indicator; }, newWindowListener: function (subject, topic, data) { let window = subject.QueryInterface(Ci.nsIDOMWindow); switch (topic) { case "domwindowopened": let self = this; window.addEventListener('load', function onLoad() { window.removeEventListener('load', onLoad, false); if (window.document.documentElement.getAttribute('windowtype') === "navigator:browser") { self.createIndicator(window); } }, false); break; case "domwindowclosed": for (let i in this.indicators) { if (this.indicators[i].window === window) { this.indicators[i].stop(); this.indicators.splice(i, 1); break; } } break; } }, setDefaultPrefs: function () { let defaultBranch = Services.prefs.getDefaultBranch(prefBranchName); defaultBranch.setIntPref("minShowState", 2); defaultBranch.setBoolPref("showDebug", false); }, observe: function (subject, topic, data) { switch (topic) { case "http-on-examine-response": case "http-on-examine-cached-response": case "http-on-examine-merged-response": subject.QueryInterface(Ci.nsIHttpChannel); // make sure we are requested via SPDY let spdyHeader = null; try { spdyHeader = subject.getResponseHeader("X-Firefox-Spdy"); } catch (e) {} if (!spdyHeader || !spdyHeader.length) return; // find the browser which this request originated from let domWindow = getLoadContext(subject); if (!domWindow) return; let window = getChromeWindow(domWindow); // notify the appropriate indicator let indicator = null; for (let i in this.indicators) { if (this.indicators[i].window === window) { indicator = this.indicators[i]; break; } } if (!indicator) { debug("Could not find indicator from chrome window for request"); } else { indicator.spdyRequested(domWindow, subject.URI, spdyHeader); } break; } }, // used by bootstrap.js startup: function (browser) { this.setDefaultPrefs(); // add response header observers Services.obs.addObserver(this, "http-on-examine-response", false); Services.obs.addObserver(this, "http-on-examine-merged-response", false); Services.obs.addObserver(this, "http-on-examine-cached-response", false); // add indicators for existing windows let browserEnum = Services.wm.getEnumerator("navigator:browser"); while (browserEnum.hasMoreElements()) { this.createIndicator(browserEnum.getNext()); } // listen for window open/close events Services.ww.registerNotification(this.newWindowListener.bind(this)); }, shutdown: function () { // remove response header observers Services.obs.removeObserver(this, "http-on-examine-response"); Services.obs.removeObserver(this, "http-on-examine-merged-response"); Services.obs.removeObserver(this, "http-on-examine-cached-response"); // stop and destroy indicators for existing windows for (let i in this.indicators) { this.indicators[i].stop(); } this.indicators = []; // stop listening for window open/close events Services.ww.unregisterNotification(this.newWindowListener); }, // used by SPDYIndicator indicatorStates: [ { name: "unknown", tooltip: "SPDY state unknown", }, { name: "inactive", tooltip: "SPDY is inactive", }, { name: "subactive", tooltip: "SPDY is active for some sub-documents included in the top-level document", }, { name: "active", tooltip: "SPDY is active for the top-level document", }, { name: "spdy2", tooltip: "SPDY 2 is active for the top-level document", }, { name: "spdy3", tooltip: "SPDY 3 is active for the top-level document", }, { name: "spdy31", tooltip: "SPDY 3.1 is active for the top-level document", }, { name: "http2", tooltip: "HTTP/2 is active for the top-level document", } ], getMinShowState: function () { return this.branch.getIntPref("minShowState"); }, getShowDebug: function () { return this.branch.getBoolPref("showDebug"); } }; function debug(s) { if (SPDYManager.getShowDebug()) { try { throw new Error("dummy"); } catch (e) { var stack = e.stack.split('\n'); stack.splice(0, 1); Services.console.logStringMessage("SPDYIndicator: " + s + "\n" + stack.join('\n')); } } } function SPDYIndicator(window) { this.window = window; this.browser = window.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow) .gBrowser; this._update_bound = this.update.bind(this); this.tabProgressListener.onLocationChange = this.tabProgressListener.onLocationChange.bind(this); debug("SPDYIndicator created"); } SPDYIndicator.prototype = { piStylesheet: null, start: function () { // insert our stylesheet this.piStylesheet = this.window.document.createProcessingInstruction('xml-stylesheet', 'href="chrome://spdyindicator/skin/overlay.css" type="text/css"'); this.window.document.insertBefore(this.piStylesheet, this.window.document.firstChild); // create icon let spdyIndicator = this.window.document.createElement('image'); spdyIndicator.id = 'spdyindicator-icon'; spdyIndicator.className = 'urlbar-icon'; // insert icon in urlbar let urlbarIcons = this.window.document.getElementById('urlbar-icons'); urlbarIcons.insertBefore(spdyIndicator, urlbarIcons.firstChild); // add browser event listeners this.browser.addEventListener("pageshow", this._update_bound, true); this.browser.addEventListener("select", this._update_bound, false); // add tab location listener this.browser.addTabsProgressListener(this.tabProgressListener); debug("SPDYIndicator started"); this.update(); }, stop: function () { // remove stylesheet if (this.piStylesheet.parentNode) { this.piStylesheet.parentNode.removeChild(this.piStylesheet); } else { debug("SPDYIndicator could not find stylesheet"); } // remove icon let spdyIndicator = this.window.document.getElementById('spdyindicator-icon'); if (spdyIndicator.parentNode) { spdyIndicator.parentNode.removeChild(spdyIndicator); } else { debug("SPDYIndicator could not find icon"); } // remove browser event listeners this.browser.removeEventListener("pageshow", this._update_bound, true); this.browser.removeEventListener("select", this._update_bound, false); // remove tab location listener this.browser.removeTabsProgressListener(this.tabProgressListener); debug("SPDYIndicator stopped"); }, getState: function (browser) { return browser.getUserData("__spdyindicator_state") || 0; }, setState: function (browser, newState) { browser.setUserData("__spdyindicator_state", newState, null); this.update(); }, updateState: function (browser, newState) { let oldState = this.getState(browser); if (newState > oldState) this.setState(browser, newState); }, isTopLevelSPDY: function (browser) { let spdyRequests = browser.getUserData("__spdyindicator_spdyrequests"); let currentPath = browser.getUserData("__spdyindicator_path") || browser.currentURI.prePath; return (spdyRequests && spdyRequests.indexOf(currentPath) !== -1); }, updateStateForSPDY: function (browser) { let spdyVersions = browser.getUserData("__spdyindicator_spdyversions"); let currentPath = browser.getUserData("__spdyindicator_path") || browser.currentURI.prePath; let state = 3; if (spdyVersions && spdyVersions.hasOwnProperty(currentPath)) { let version = spdyVersions[currentPath]; if (version.match(/^h2/)) { state = 7; } else if (version === "3.1") { state = 6; } else if (version === "3") { state = 5; } else if (version === "2") { state = 4; } } this.updateState(browser, state); }, update: function () { let state = this.getState(this.browser.selectedBrowser); // change indicator state let indicator = this.window.document.getElementById("spdyindicator-icon"); let indicatorState = SPDYManager.indicatorStates[state]; indicator.setAttribute("hidden", state < SPDYManager.getMinShowState()); indicator.setAttribute("state", indicatorState.name); indicator.setAttribute("tooltiptext", indicatorState.tooltip); }, _update_bound: null, spdyRequested: function (domWindow, uri, version) { debug("Requested " + uri.asciiSpec); debug("SPDY Version " + version); let browser = this.browser.getBrowserForDocument(domWindow.top.document); if (!browser) return; let spdyRequests = browser.getUserData("__spdyindicator_spdyrequests") || []; let spdyVersions = browser.getUserData("__spdyindicator_spdyversions") || {}; if (spdyRequests.indexOf(uri.prePath) === -1) { spdyRequests.push(uri.prePath); spdyVersions[uri.prePath] = version; } if (spdyRequests.length > SPDYREQUESTS_MAXSIZE) { let splices = spdyRequests.splice(0, spdyRequests.length - SPDYREQUESTS_MAXSIZE); splices.forEach(function (element) { if (spdyVersions.hasOwnProperty(element)) { delete spdyVersions[element]; } }); } browser.setUserData("__spdyindicator_spdyrequests", spdyRequests, null); browser.setUserData("__spdyindicator_spdyversions", spdyVersions, null); if (this.isTopLevelSPDY(browser)) { this.updateStateForSPDY(browser); } else { this.updateState(browser, 2); } }, tabProgressListener: { onLocationChange: function (browser, webProgress, request, URI, flags) { browser.setUserData("__spdyindicator_path", URI.prePath, null); this.setState(browser, 0); if (this.isTopLevelSPDY(browser)) { this.updateStateForSPDY(browser); } }, onProgressChange: function () {}, onSecurityChange: function () {}, onStateChange: function () {}, onStatusChange: function () {} }, }; // vim: filetype=javascript moz-spdy-indicator-2.2/chrome/locale/000077500000000000000000000000001243537471200176355ustar00rootroot00000000000000moz-spdy-indicator-2.2/chrome/locale/en-US/000077500000000000000000000000001243537471200205645ustar00rootroot00000000000000moz-spdy-indicator-2.2/chrome/locale/en-US/overlay.dtd000066400000000000000000000011541243537471200227430ustar00rootroot00000000000000 moz-spdy-indicator-2.2/chrome/skin/000077500000000000000000000000001243537471200173425ustar00rootroot00000000000000moz-spdy-indicator-2.2/chrome/skin/icon-http2-active.png000066400000000000000000000004151243537471200233100ustar00rootroot00000000000000PNG  IHDRaIDATxc=#w.x)vF~" Ż.h9 P&$rIu7e0Y.x1f@/C5BWf(A !{1Kb5`*D vZ ƞ z?#k גN 5G5!5Zl9 .T "75`JHIN 6ls ܅IENDB`moz-spdy-indicator-2.2/chrome/skin/icon-spdy-active.png000066400000000000000000000004451243537471200232310ustar00rootroot00000000000000PNG  IHDRaIDATxc8#%pN"D9ɥ``] $|_q\/d2Ig%g 8/pND 3 WEy. Ը^ Ho(^ð߁@Icb5 k%hc"йN@@>0>'L¢ZI^a+xU!`tyJ]```8/J⺠HAN 6)fd"*5IENDB`moz-spdy-indicator-2.2/chrome/skin/icon-spdy-subactive.png000066400000000000000000000004341243537471200237410ustar00rootroot00000000000000PNG  IHDRaIDATxc4iܔ)S2'OٳgmPS]SN&Z6!K4/;,@{i) m9s&!u45ҫf5===,6m^,@@ Ȯ@v&m۶1EZR0Ѐ@i֬YBDnݙ J!]3JHIN 6ġ.nIENDB`moz-spdy-indicator-2.2/chrome/skin/icon-spdy2-active.png000066400000000000000000000004551243537471200233140ustar00rootroot00000000000000PNG  IHDRaIDATxc8#%pN"D9ɥ``] $|_q\/d2Ig%g 8/pND 3 WEy. Ը^ Ho(^ð߁@Icb5 k%hc"йN@@>0>'L¢ZI^a+xU!dk`@L[ltޅM# "p^FDiLHj|okc*IENDB`moz-spdy-indicator-2.2/chrome/skin/icon-spdy3-active.png000066400000000000000000000004561243537471200233160ustar00rootroot00000000000000PNG  IHDRaIDATxc8#%pN"D9ɥ``] $|_q\/d2Ig%g 8/pND 3 WEy. Ը^ Ho(^ð߁@Icb5 k%hc"йN@@>0>'L¢ZI^a+xU!dk`@L[ltޅM# "p^F_M d@R "o~mIENDB`moz-spdy-indicator-2.2/chrome/skin/icon-spdy31-active.png000066400000000000000000000004541243537471200233750ustar00rootroot00000000000000PNG  IHDRaIDATxc8#%pN"D9ɥ``] $|_q\/d2Ig%g 8/pND 3 WEy. Ը^ Ho(^ð߁@Icb5 k%hc"йN@@>0>'L¢ZI^a+@0ubBd;p^.\pFJ3˨oZFt" 6%rw*IENDB`moz-spdy-indicator-2.2/chrome/skin/overlay.css000066400000000000000000000013631243537471200215400ustar00rootroot00000000000000#spdyindicator-icon[state=http2] { list-style-image: url("chrome://spdyindicator/skin/icon-http2-active.png"); } #spdyindicator-icon[state=spdy31] { list-style-image: url("chrome://spdyindicator/skin/icon-spdy31-active.png"); } #spdyindicator-icon[state=spdy3] { list-style-image: url("chrome://spdyindicator/skin/icon-spdy3-active.png"); } #spdyindicator-icon[state=spdy2] { list-style-image: url("chrome://spdyindicator/skin/icon-spdy2-active.png"); } #spdyindicator-icon[state=active] { list-style-image: url("chrome://spdyindicator/skin/icon-spdy-active.png"); } #spdyindicator-icon[state=subactive] { list-style-image: url("chrome://spdyindicator/skin/icon-spdy-subactive.png"); } #spdyindicator-icon { cursor: default; } moz-spdy-indicator-2.2/icon.png000066400000000000000000000063161243537471200165650ustar00rootroot00000000000000PNG  IHDR@@iq IDATx Ueǟ\]sbjVjheY}HJY*b~k)a"*,{ϽwQir4ќRƌ~޹sC!=ܻyߵo7z6}dm?4X߇6=P̖{||MGZZ_bG[F:B,0S5ǟ; 0@qml]o=١f0M'bO HvviBB ).G@p 3Z荶B=8ekܻ\(䃉x'rax+fN|櫖&Dড়.ӸwA w\ w4uExFk9s@!0{Ľ|OE@S/*VȞ p=Ħ"B4xKeBp;o_ O# q !pdi_eW_Ye+z0''wxhʒG $"q6r X1 <@ gǡ^<*b?/7@bB0"IR늏"3K@b>@I b9Gt'l#7^@3&5u{P3q{:\s@T"O܇Z(bDR_! a2$dp=D9_)*2b`!:\_µqF9T [֖hF LTKD JJT~.+ K`4S~xby~h'F 3a!x & :EU#dO5=RWQ%]uB CKfSe*᮵~JH}0XL]H0|MQ Yc$A~Fw2XnUs'c)nj>u /*tM5,S%i| л҆-׬wx5os(xwȣ%^ )xl5F~?}fNXwF{ַ{oėL͠_(D78Ht,|iMk{toT%Ph"tMu% t{{}q !sX_nzoeجė ,5+sަ ~Qf~TMo MT7Ϩ_w9mYh^{vE،hP$W@k/zPʎuΧVI2\]\_vJ+V[@{̒[T'3=AzJ30ko%>G1uŗU;V2*[q}̉\K2B3jQT0aJ%lFƙ Pu-?s7/ޅeTs*IieV ;暢g$Xg0=-{ׄ '&9oCAmAjW,{@{)=@ZAx"%wZ{Ĵ+VB@IKcb+xʳ1}j>6ǞLv!<]fND͋UeR7pF{mt_تJ&]iyԚX+ 3Ζs~-N=3WX{|D6a\8Ar 5LUNtt}L4KۇC 23?"ds7I!3mγ!=me{6i :RH>T>A7E -n5J7j;$ն1zmd ;%8{VQQ\*Skڢp:!"-xh4ߵV_ 5αLcuhxa56['q`BMy\0M"Aob%;F \vB:,W =H]2##WX8V=Q6 "Z!59Mɓ* C4h X]X!!M/߇*.Mrb_/P~0?MnJYxT\(u%se_$QDk\m_$W;yPrM#0Yݿd8_F~bQ>( P\AkNdEL 5Ux$K3Ǻ:`Α> GWԨ`B cM8:K0R .^ȳ",ՈTExܕ/t+I|k QUKZ2=Zb֪iUXI/pBdίP,#e4F_m3 O: j={NstPFQMȢ >. { Wh ej1 Mi*sQ{#Yb@5@K!U ޭ-V8YqOeUaM}% 0UK49ߞz!NV8]{|?%HGz 6JhHWzvj?]c,iDOU~ߣuPC'F* spdyindicator@chengsun.github.com 2.2 2 true {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 10.* 34.* SPDY indicator An indicator showing SPDY support in the address bar. Cheng Sun http://github.com/chengsun/moz-spdy-indicator