[Pkg-mozext-commits] [greasemonkey] 03/43: [WIP] GM_rmc

David Prévot taffit at moszumanska.debian.org
Sun Feb 22 21:56:09 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository greasemonkey.

commit f93513725b51bb84b1d6f16f4085b2e1ceeb3c1c
Author: Ventero <ventero at ventero.de>
Date:   Sat Sep 27 05:20:30 2014 +0200

    [WIP] GM_rmc
---
 content/browser.js       |  3 ++
 content/framescript.js   | 66 +++++++++++++++++++++++++++++++++-
 content/menucommander.js | 93 +++++++++++++++++++++++++++++++++++++++---------
 modules/menucommand.js   | 41 ++++++---------------
 modules/sandbox.js       | 22 ++++++------
 5 files changed, 167 insertions(+), 58 deletions(-)

diff --git a/content/browser.js b/content/browser.js
index f34a564..4e2328d 100644
--- a/content/browser.js
+++ b/content/browser.js
@@ -73,6 +73,9 @@ GM_BrowserUI.chromeLoad = function(e) {
   // initialization routines will run, no matter what.
   GM_BrowserUI.gmSvc.config;
 
+  // Initialize the chrome side handling of menu commands.
+  GM_MenuCommander.initialize();
+
   GM_BrowserUI.showToolbarButton();
 
   // Make sure this is imported at least once, so its internal timer starts.
diff --git a/content/framescript.js b/content/framescript.js
index 6033172..e6df7e9 100644
--- a/content/framescript.js
+++ b/content/framescript.js
@@ -13,7 +13,9 @@ var gStripUserPassRegexp = new RegExp('(://)([^:/]+)(:[^@/]+)?@');
 var gScriptRunners = {};
 
 function ScriptRunner(aWindow, aUrl) {
+  this.menuCommands = [];
   this.window = aWindow;
+  this.windowId = GM_util.windowId(this.window);
   this.url = aUrl;
 }
 
@@ -27,11 +29,23 @@ ScriptRunner.prototype.injectScripts = function(aScripts) {
   }
 
   for (var i = 0, script = null; script = aScripts[i]; i++) {
-    var sandbox = createSandbox(script, this.window, this.url);
+    var sandbox = createSandbox(script, this);
     runScriptInSandbox(script, sandbox);
   }
 }
 
+ScriptRunner.prototype.registeredMenuCommand = function(aCommand) {
+  var length = this.menuCommands.push(aCommand);
+
+  sendAsyncMessage("greasemonkey:menu-command-registered", {
+    accessKey: aCommand.accessKey,
+    frozen: aCommand.frozen,
+    index: length - 1,
+    name: aCommand.name,
+    windowId: aCommand.contentWindowId
+  });
+}
+
 var observer = {
   observe: function(aSubject, aTopic, aData) {
     if (!GM_util.getEnabled()) return;
@@ -68,6 +82,40 @@ var observer = {
     this.runScripts('document-end', contentWin);
   },
 
+  pagehide: function(aEvent) {
+    var contentWin = aEvent.target.defaultView;
+    var windowId = GM_util.windowId(contentWin);
+    if (!windowId || !gScriptRunners[windowId]) return;
+
+    // Small optimization: only send a notification if there's a menu command
+    // for this window.
+    if (!gScriptRunners[windowId].menuCommands.length) return;
+
+    if (aEvent.persisted) {
+      sendAsyncMessage("greasemonkey:toggle-menu-commands", {
+        frozen: true,
+        windowId: windowId
+      });
+    } else {
+      sendAsyncMessage("greasemonkey:clear-menu-commands", {
+        windowId: windowId
+      });
+    }
+  },
+
+  pageshow: function(aEvent) {
+    var contentWin = aEvent.target.defaultView;
+    var windowId = GM_util.windowId(contentWin);
+    if (!windowId || !gScriptRunners[windowId]) return;
+
+    if (!gScriptRunners[windowId].menuCommands.length) return;
+
+    sendAsyncMessage("greasemonkey:toggle-menu-commands", {
+      frozen: false,
+      windowId: windowId
+    });
+  },
+
   runScripts: function(aRunWhen, aWrappedContentWin) {
     // See #1970
     // When content does (e.g.) history.replacestate() in an inline script,
@@ -109,6 +157,18 @@ var observer = {
     gScriptRunners[windowId].injectScripts([script]);
   },
 
+  runMenuCommand: function(aMessage) {
+    var windowId = aMessage.data.windowId;
+    if (!gScriptRunners[windowId]) return;
+
+    var index = aMessage.data.index;
+    var command = gScriptRunners[windowId].menuCommands[index];
+    if (!command || !command.commandFunc) return;
+
+    // Ensure |this| is set to the sandbox object inside the command function.
+    command.commandFunc.call(null);
+  },
+
   createScriptFromObject: function(aObject) {
     var script = Object.create(IPCScript.prototype);
     // TODO: better way for this? Object.create needs property descriptors.
@@ -126,6 +186,10 @@ observerService.addObserver(observer, 'inner-window-destroyed', false);
 
 addEventListener("DOMContentLoaded", observer.contentLoad.bind(observer));
 addEventListener("load", observer.contentLoad.bind(observer));
+addEventListener("pagehide", observer.pagehide.bind(observer));
+addEventListener("pageshow", observer.pageshow.bind(observer));
 
 addMessageListener("greasemonkey:inject-script",
     observer.runDelayedScript.bind(observer));
+addMessageListener("greasemonkey:menu-command-clicked",
+    observer.runMenuCommand.bind(observer));
diff --git a/content/menucommander.js b/content/menucommander.js
index b66fa03..dfd1d9d 100644
--- a/content/menucommander.js
+++ b/content/menucommander.js
@@ -1,17 +1,62 @@
 Components.utils.import('resource://greasemonkey/util.js');
 
-var GM_MenuCommander = {};
+var GM_MenuCommander = {
+  menuCommands: {}
+};
+
+GM_MenuCommander.initialize = function() {
+  var messageManager = Components.classes["@mozilla.org/globalmessagemanager;1"]
+      .getService(Components.interfaces.nsIMessageListenerManager);
+
+  messageManager.addMessageListener('greasemonkey:menu-command-registered',
+      GM_MenuCommander.menuCommandRegistered);
+  messageManager.addMessageListener('greasemonkey:clear-menu-commands',
+      GM_MenuCommander.clearMenuCommands);
+  messageManager.addMessageListener('greasemonkey:toggle-menu-commands',
+      GM_MenuCommander.toggleMenuCommands);
+}
 
-// Mix in menucommand.js so we don't pollute the global scope
-Components.utils.import('resource://greasemonkey/menucommand.js',
-    GM_MenuCommander);
+GM_MenuCommander.menuCommandRegistered = function(aMessage) {
+  var windowId = aMessage.data.windowId;
+
+  if (!GM_MenuCommander.menuCommands[windowId]) {
+    GM_MenuCommander.menuCommands[windowId] = [];
+  }
+
+  var command = aMessage.data;
+  command.browser = aMessage.target;
+  GM_MenuCommander.menuCommands[windowId].push(command);
+}
+
+GM_MenuCommander.clearMenuCommands = function(aMessage) {
+  var windowId = aMessage.data.windowId;
+  if (!windowId) return;
+
+  delete GM_MenuCommander.menuCommands[windowId];
+}
+
+GM_MenuCommander.toggleMenuCommands = function(aMessage) {
+  var frozen = aMessage.data.frozen;
+  var windowId = aMessage.data.windowId;
+
+  GM_MenuCommander.withAllMenuCommandsForWindowId(windowId, function(command) {
+    command.frozen = frozen;
+  });
+}
+
+GM_MenuCommander.commandClicked = function(aCommand) {
+  aCommand.browser.messageManager.sendAsyncMessage("greasemonkey:menu-command-clicked", {
+    index: aCommand.index,
+    windowId: aCommand.windowId
+  });
+}
 
 GM_MenuCommander.createMenuItem = function(command) {
   var menuItem = document.createElement("menuitem");
   menuItem.setAttribute("label", command.name);
-  if ('function' == typeof command.commandFunc) {
-    menuItem.addEventListener("command", command.commandFunc, true);
-  }
+  menuItem.addEventListener("command", function() {
+    GM_MenuCommander.commandClicked(command);
+  }, false);
 
   if (command.accessKey) {
       menuItem.setAttribute("accesskey", command.accessKey);
@@ -25,16 +70,7 @@ GM_MenuCommander.onPageHide = function(aWindowId, aPersisted) {
     GM_MenuCommander.withAllMenuCommandsForWindowId(aWindowId,
         function(index, command) { command.frozen = true; });
   } else {
-    GM_MenuCommander.removeMatchingMenuCommands(
-      null,
-      function(index, command) {
-        return (
-            // Remove the reference if either the window is closed, ...
-            GM_util.windowIsClosed(command.contentWindow)
-            // ... or the window id of the destroyed page matches.
-            || (aWindowId && command.contentWindowId == aWindowId));
-      },
-      true);  // Don't forget the aForced=true passed here!
+    delete GM_MenuCommander.menuCommands[aWindowId];
   }
 }
 
@@ -67,3 +103,26 @@ GM_MenuCommander.onPopupShowing = function(aMenuPopup) {
 
   aMenuPopup.parentNode.disabled = !haveCommands;
 };
+
+GM_MenuCommander.withAllMenuCommandsForWindowId = function(
+    aContentWindowId, aCallback, aForce) {
+
+  var targetWindowIds = null;
+  if (aForce) {
+    targetWindowIds = Object.keys(GM_MenuCommander.menuCommands);
+  } else if (aContentWindowId) {
+    targetWindowIds = [aContentWindowId];
+  } else {
+    return;
+  }
+
+  for each (var windowId in targetWindowIds) {
+   var commands = GM_MenuCommander.menuCommands[windowId];
+   if (!commands) return;
+
+    var l = commands.length - 1;
+    for (var i = l, command = null; command = commands[i]; i--) {
+      aCallback(i, command);
+    }
+  }
+};
diff --git a/modules/menucommand.js b/modules/menucommand.js
index aea292d..606436d 100644
--- a/modules/menucommand.js
+++ b/modules/menucommand.js
@@ -1,5 +1,4 @@
-var EXPORTED_SYMBOLS = ['registerMenuCommand', 'removeMatchingMenuCommands',
-    'withAllMenuCommandsForWindowId'];
+var EXPORTED_SYMBOLS = ['registerMenuCommand'];
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import('resource://greasemonkey/util.js');
@@ -9,10 +8,10 @@ var gStringBundle = Services.strings.createBundle(
     "chrome://greasemonkey/locale/greasemonkey.properties");
 
 function registerMenuCommand(
-    wrappedContentWin, script,
+    scriptRunner,
     commandName, commandFunc, accessKey, unused, accessKey2
 ) {
-  if (wrappedContentWin.top != wrappedContentWin) {
+  if (scriptRunner.window.top != scriptRunner.window) {
     // Only register menu commands for the top level window.
     return;
   }
@@ -33,30 +32,12 @@ function registerMenuCommand(
   }
 
   var command = {
-      name: commandName,
-      accessKey: accessKey,
-      commandFunc: commandFunc,
-      contentWindow: wrappedContentWin,
-      contentWindowId: GM_util.windowId(wrappedContentWin),
-      frozen: false};
-  gMenuCommands.push(command);
+    name: commandName,
+    accessKey: accessKey,
+    commandFunc: commandFunc,
+    contentWindowId: scriptRunner.windowId,
+    frozen: false
+  };
+
+  scriptRunner.registeredMenuCommand(command);
 };
-
-function withAllMenuCommandsForWindowId(aContentWindowId, aCallback, aForce) {
-  if(!aContentWindowId && !aForce) return;
-
-  var l = gMenuCommands.length - 1;
-  for (var i = l, command = null; command = gMenuCommands[i]; i--) {
-    if (aForce || command.contentWindowId == aContentWindowId) {
-      aCallback(i, command);
-    }
-  }
-};
-
-function removeMatchingMenuCommands(aContentWindowId, aCallback, aForce) {
-  withAllMenuCommandsForWindowId(aContentWindowId, function(index, command) {
-    if (aCallback(index, command)) {
-      gMenuCommands.splice(index, 1);
-    }
-  }, aForce)
-}
diff --git a/modules/sandbox.js b/modules/sandbox.js
index d19dbe2..b81f4ef 100644
--- a/modules/sandbox.js
+++ b/modules/sandbox.js
@@ -22,15 +22,18 @@ function alert(msg) {
       .alert(null, "Greasemonkey alert", msg);
 }
 
-function createSandbox(aScript, aContentWin, aUrl) {
+function createSandbox(aScript, aScriptRunner) {
+  var contentWin = aScriptRunner.window;
+  var url = aScriptRunner.url;
+
   if (GM_util.inArray(aScript.grants, 'none')) {
     // If there is an explicit none grant, use a plain unwrapped sandbox
     // with no other content.
     var contentSandbox = new Components.utils.Sandbox(
-        aContentWin,
+        contentWin,
         {
           'sandboxName': aScript.id,
-          'sandboxPrototype': aContentWin,
+          'sandboxPrototype': contentWin,
           'wantXrays': false,
         });
     // GM_info is always provided.
@@ -51,10 +54,10 @@ function createSandbox(aScript, aContentWin, aUrl) {
   }
 
   var sandbox = new Components.utils.Sandbox(
-      [aContentWin],
+      [contentWin],
       {
         'sandboxName': aScript.id,
-        'sandboxPrototype': aContentWin,
+        'sandboxPrototype': contentWin,
         'wantXrays': true,
       });
 
@@ -70,14 +73,13 @@ function createSandbox(aScript, aContentWin, aUrl) {
   sandbox.exportFunction = Cu.exportFunction;
 
   if (GM_util.inArray(aScript.grants, 'GM_addStyle')) {
-    sandbox.GM_addStyle = GM_util.hitch(null, GM_addStyle, aContentWin.document);
+    sandbox.GM_addStyle = GM_util.hitch(null, GM_addStyle, contentWin.document);
   }
   if (GM_util.inArray(aScript.grants, 'GM_log')) {
     sandbox.GM_log = GM_util.hitch(new GM_ScriptLogger(aScript), 'log');
   }
   if (GM_util.inArray(aScript.grants, 'GM_registerMenuCommand')) {
-    var gmrmc = GM_util.hitch(
-        null, registerMenuCommand, aContentWin, aScript);
+    var gmrmc = GM_util.hitch(null, registerMenuCommand, aScriptRunner);
     sandbox.GM_registerMenuCommand = gmrmc;
   }
 
@@ -109,11 +111,11 @@ function createSandbox(aScript, aContentWin, aUrl) {
   }
   if (GM_util.inArray(aScript.grants, 'GM_openInTab')) {
     sandbox.GM_openInTab = GM_util.hitch(
-        null, GM_openInTab, aContentWin);
+        null, GM_openInTab, contentWin);
   }
   if (GM_util.inArray(aScript.grants, 'GM_xmlhttpRequest')) {
     sandbox.GM_xmlhttpRequest = GM_util.hitch(
-        new GM_xmlhttpRequester(aContentWin, aUrl, sandbox),
+        new GM_xmlhttpRequester(contentWin, aScriptRunner.url, sandbox),
         'contentStartRequest');
   }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/greasemonkey.git



More information about the Pkg-mozext-commits mailing list