You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
6.5 KiB

10 years ago
10 years ago
10 years ago
  1. /*******************************************************************************
  2. uMatrix - a browser extension to block requests.
  3. Copyright (C) 2014-2017 The uMatrix/uBlock Origin authors
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see {http://www.gnu.org/licenses/}.
  14. Home: https://github.com/gorhill/uMatrix
  15. */
  16. /* global ADDON_UNINSTALL, APP_SHUTDOWN */
  17. /* exported startup, shutdown, install, uninstall */
  18. 'use strict';
  19. /******************************************************************************/
  20. const {classes: Cc, interfaces: Ci} = Components;
  21. // Accessing the context of the background page:
  22. // var win = Services.appShell.hiddenDOMWindow.document.querySelector('iframe[src*=umatrix]').contentWindow;
  23. let windowlessBrowser = null;
  24. let windowlessBrowserPL = null;
  25. let bgProcess = null;
  26. let version;
  27. const hostName = 'umatrix';
  28. const restartListener = {
  29. get messageManager() {
  30. return Components.classes['@mozilla.org/parentprocessmessagemanager;1']
  31. .getService(Components.interfaces.nsIMessageListenerManager);
  32. },
  33. receiveMessage: function() {
  34. shutdown();
  35. startup();
  36. }
  37. };
  38. /******************************************************************************/
  39. // https://github.com/gorhill/uBlock/issues/2493
  40. // Fix by https://github.com/gijsk
  41. // imported from https://github.com/gorhill/uBlock/pull/2497
  42. function startup(data/*, reason*/) {
  43. if ( data !== undefined ) {
  44. version = data.version;
  45. }
  46. // Already started?
  47. if ( bgProcess !== null ) {
  48. return;
  49. }
  50. let appShell = Cc['@mozilla.org/appshell/appShellService;1']
  51. .getService(Ci.nsIAppShellService);
  52. if ( appShell.createWindowlessBrowser ) {
  53. getWindowlessBrowserFrame(appShell);
  54. } else {
  55. getHiddenWindowBrowserFrame(appShell);
  56. }
  57. }
  58. function createBgProcess(parentDocument) {
  59. bgProcess = parentDocument.documentElement.appendChild(
  60. parentDocument.createElementNS('http://www.w3.org/1999/xhtml', 'iframe')
  61. );
  62. bgProcess.setAttribute(
  63. 'src',
  64. 'chrome://' + hostName + '/content/background.html#' + version
  65. );
  66. // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager#addMessageListener%28%29
  67. // "If the same listener registers twice for the same message, the
  68. // "second registration is ignored."
  69. restartListener.messageManager.addMessageListener(
  70. hostName + '-restart',
  71. restartListener
  72. );
  73. }
  74. function getWindowlessBrowserFrame(appShell) {
  75. windowlessBrowser = appShell.createWindowlessBrowser(true);
  76. windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor);
  77. let webProgress = windowlessBrowser.getInterface(Ci.nsIWebProgress);
  78. let XPCOMUtils = Components.utils.import('resource://gre/modules/XPCOMUtils.jsm', null).XPCOMUtils;
  79. windowlessBrowserPL = {
  80. QueryInterface: XPCOMUtils.generateQI([
  81. Ci.nsIWebProgressListener, Ci.nsIWebProgressListener2,
  82. Ci.nsISupportsWeakReference]),
  83. onStateChange(wbp, request, stateFlags, status) {
  84. if ( !request ) {
  85. return;
  86. }
  87. if ( stateFlags & Ci.nsIWebProgressListener.STATE_STOP ) {
  88. webProgress.removeProgressListener(windowlessBrowserPL);
  89. windowlessBrowserPL = null;
  90. createBgProcess(windowlessBrowser.document);
  91. }
  92. }
  93. };
  94. webProgress.addProgressListener(windowlessBrowserPL, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
  95. windowlessBrowser.document.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='" + hostName + "-win'/>";
  96. }
  97. function getHiddenWindowBrowserFrame(appShell) {
  98. let onReady = function(e) {
  99. if ( e ) {
  100. this.removeEventListener(e.type, onReady);
  101. }
  102. let hiddenDoc = appShell.hiddenDOMWindow.document;
  103. // https://github.com/gorhill/uBlock/issues/10
  104. // Fixed by github.com/AlexVallat:
  105. // https://github.com/chrisaljoudi/uBlock/issues/1149
  106. // https://github.com/AlexVallat/uBlock/commit/e762a29d308caa46578cdc34a9be92c4ad5ecdd0
  107. if ( hiddenDoc.readyState === 'loading' ) {
  108. hiddenDoc.addEventListener('DOMContentLoaded', onReady);
  109. return;
  110. }
  111. createBgProcess(hiddenDoc);
  112. };
  113. }
  114. /******************************************************************************/
  115. function shutdown(data, reason) {
  116. if ( reason === APP_SHUTDOWN ) {
  117. return;
  118. }
  119. if ( bgProcess !== null ) {
  120. bgProcess.parentNode.removeChild(bgProcess);
  121. bgProcess = null;
  122. }
  123. if ( windowlessBrowser !== null ) {
  124. // close() does not exist for older versions of Firefox.
  125. if ( typeof windowlessBrowser.close === 'function' ) {
  126. windowlessBrowser.close();
  127. }
  128. windowlessBrowser = null;
  129. windowlessBrowserPL = null;
  130. }
  131. if ( data === undefined ) {
  132. return;
  133. }
  134. // Remove the restartObserver only when the extension is being disabled
  135. restartListener.messageManager.removeMessageListener(
  136. hostName + '-restart',
  137. restartListener
  138. );
  139. }
  140. /******************************************************************************/
  141. function install() {
  142. // https://bugzil.la/719376
  143. Components.classes['@mozilla.org/intl/stringbundle;1']
  144. .getService(Components.interfaces.nsIStringBundleService)
  145. .flushBundles();
  146. }
  147. /******************************************************************************/
  148. function uninstall(data, aReason) {
  149. if ( aReason !== ADDON_UNINSTALL ) {
  150. return;
  151. }
  152. // To cleanup vAPI.localStorage in vapi-common.js, aka
  153. // "extensions.umatrix.*" in `about:config`.
  154. Components.utils.import('resource://gre/modules/Services.jsm', null)
  155. .Services.prefs
  156. .getBranch('extensions.' + hostName + '.')
  157. .deleteBranch('');
  158. }
  159. /******************************************************************************/