[Pkg-javascript-commits] [pdf.js] 04/119: Bug 1072350 - Removing CPOWs used by Find events.

David Prévot taffit at moszumanska.debian.org
Wed May 13 21:27:35 UTC 2015


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

taffit pushed a commit to branch master
in repository pdf.js.

commit 595be5cb4f482f2a4740763b01df7672ccaa215b
Author: Gabor Krizsanits <gkrizsanits at mozilla.com>
Date:   Fri Feb 20 17:47:29 2015 +0100

    Bug 1072350 - Removing CPOWs used by Find events.
---
 extensions/firefox/content/PdfStreamConverter.jsm |  84 +++++------
 extensions/firefox/content/PdfjsChromeUtils.jsm   | 169 +++++++++++-----------
 2 files changed, 127 insertions(+), 126 deletions(-)

diff --git a/extensions/firefox/content/PdfStreamConverter.jsm b/extensions/firefox/content/PdfStreamConverter.jsm
index 8ca76c9..07eb7a0 100644
--- a/extensions/firefox/content/PdfStreamConverter.jsm
+++ b/extensions/firefox/content/PdfStreamConverter.jsm
@@ -72,7 +72,7 @@ function getChromeWindow(domWindow) {
 
 function getFindBar(domWindow) {
   if (PdfjsContentUtils.isRemote) {
-    return PdfjsContentUtils.getFindBar(domWindow);
+    throw new Error('FindBar is not accessible from the content process.');
   }
   var browser = getContainingBrowser(domWindow);
   try {
@@ -371,7 +371,13 @@ ChromeActions.prototype = {
     if (this.domWindow.frameElement !== null) {
       return false;
     }
-    // ... and when the new find events code exists.
+
+    // ... and we are in a child process
+    if (PdfjsContentUtils.isRemote) {
+      return true;
+    }
+
+    // ... or when the new find events code exists.
     var findBar = getFindBar(this.domWindow);
     return findBar && ('updateControlState' in findBar);
   },
@@ -473,7 +479,15 @@ ChromeActions.prototype = {
         (findPreviousType !== 'undefined' && findPreviousType !== 'boolean')) {
       return;
     }
-    getFindBar(this.domWindow).updateControlState(result, findPrevious);
+
+    var winmm = this.domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIDocShell)
+                              .sameTypeRootTreeItem
+                              .QueryInterface(Ci.nsIDocShell)
+                              .QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIContentFrameMessageManager);
+
+    winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data);
   },
   setPreferences: function(prefs, sendResponse) {
     var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
@@ -778,14 +792,14 @@ RequestListener.prototype.receive = function(event) {
 
 // Forwards events from the eventElement to the contentWindow only if the
 // content window matches the currently selected browser window.
-function FindEventManager(eventElement, contentWindow, chromeWindow) {
-  this.types = ['find',
-                'findagain',
-                'findhighlightallchange',
-                'findcasesensitivitychange'];
-  this.chromeWindow = chromeWindow;
+function FindEventManager(contentWindow) {
   this.contentWindow = contentWindow;
-  this.eventElement = eventElement;
+  this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIDocShell)
+                            .sameTypeRootTreeItem
+                            .QueryInterface(Ci.nsIDocShell)
+                            .QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIContentFrameMessageManager);
 }
 
 FindEventManager.prototype.bind = function() {
@@ -795,41 +809,27 @@ FindEventManager.prototype.bind = function() {
   }.bind(this);
   this.contentWindow.addEventListener('unload', unload);
 
-  for (var i = 0; i < this.types.length; i++) {
-    var type = this.types[i];
-    this.eventElement.addEventListener(type, this, true);
-  }
+  // We cannot directly attach listeners to for the find events
+  // since the FindBar is in the parent process. Instead we're
+  // asking the PdfjsChromeUtils to do it for us and forward
+  // all the find events to us.
+  this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
+  this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
 };
 
-FindEventManager.prototype.handleEvent = function(e) {
-  var chromeWindow = this.chromeWindow;
+FindEventManager.prototype.receiveMessage = function(msg) {
+  var detail = msg.data.detail;
+  var type = msg.data.type;
   var contentWindow = this.contentWindow;
-  // Only forward the events if they are for our dom window.
-  if (chromeWindow.gBrowser.selectedBrowser.contentWindow === contentWindow) {
-    var detail = {
-      query: e.detail.query,
-      caseSensitive: e.detail.caseSensitive,
-      highlightAll: e.detail.highlightAll,
-      findPrevious: e.detail.findPrevious
-    };
-    detail = makeContentReadable(detail, contentWindow);
-    var forward = contentWindow.document.createEvent('CustomEvent');
-    forward.initCustomEvent(e.type, true, true, detail);
-    // Due to restrictions with cpow use, we can't dispatch
-    // dom events with an urgent message on the stack. So bounce
-    // this off the main thread to make it async.
-    Services.tm.mainThread.dispatch(function () {
-      contentWindow.dispatchEvent(forward);
-    }, Ci.nsIThread.DISPATCH_NORMAL);
-    e.preventDefault();
-  }
+
+  detail = makeContentReadable(detail, contentWindow);
+  var forward = contentWindow.document.createEvent('CustomEvent');
+  forward.initCustomEvent(type, true, true, detail);
+  contentWindow.dispatchEvent(forward);
 };
 
 FindEventManager.prototype.unbind = function() {
-  for (var i = 0; i < this.types.length; i++) {
-    var type = this.types[i];
-    this.eventElement.removeEventListener(type, this, true);
-  }
+  this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
 };
 
 function PdfStreamConverter() {
@@ -994,11 +994,7 @@ PdfStreamConverter.prototype = {
           requestListener.receive(event);
         }, false, true);
         if (actions.supportsIntegratedFind()) {
-          var chromeWindow = getChromeWindow(domWindow);
-          var findBar = getFindBar(domWindow);
-          var findEventManager = new FindEventManager(findBar,
-                                                      domWindow,
-                                                      chromeWindow);
+          var findEventManager = new FindEventManager(domWindow);
           findEventManager.bind();
         }
         listener.onStopRequest(aRequest, context, statusCode);
diff --git a/extensions/firefox/content/PdfjsChromeUtils.jsm b/extensions/firefox/content/PdfjsChromeUtils.jsm
index 598502d..ed49732 100644
--- a/extensions/firefox/content/PdfjsChromeUtils.jsm
+++ b/extensions/firefox/content/PdfjsChromeUtils.jsm
@@ -51,6 +51,7 @@ let PdfjsChromeUtils = {
    */
 
   init: function () {
+    this._browsers = new Set();
     if (!this._ppmm) {
       // global parent process message manager (PPMM)
       this._ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'].
@@ -65,10 +66,12 @@ let PdfjsChromeUtils = {
       // global dom message manager (MMg)
       this._mmg = Cc['@mozilla.org/globalmessagemanager;1'].
         getService(Ci.nsIMessageListenerManager);
-      this._mmg.addMessageListener('PDFJS:Parent:getChromeWindow', this);
-      this._mmg.addMessageListener('PDFJS:Parent:getFindBar', this);
       this._mmg.addMessageListener('PDFJS:Parent:displayWarning', this);
 
+      this._mmg.addMessageListener('PDFJS:Parent:addEventListener', this);
+      this._mmg.addMessageListener('PDFJS:Parent:removeEventListener', this);
+      this._mmg.addMessageListener('PDFJS:Parent:updateControlState', this);
+
       // observer to handle shutdown
       Services.obs.addObserver(this, 'quit-application', false);
     }
@@ -84,10 +87,12 @@ let PdfjsChromeUtils = {
       this._ppmm.removeMessageListener('PDFJS:Parent:isDefaultHandlerApp',
                                        this);
 
-      this._mmg.removeMessageListener('PDFJS:Parent:getChromeWindow', this);
-      this._mmg.removeMessageListener('PDFJS:Parent:getFindBar', this);
       this._mmg.removeMessageListener('PDFJS:Parent:displayWarning', this);
 
+      this._mmg.removeMessageListener('PDFJS:Parent:addEventListener', this);
+      this._mmg.removeMessageListener('PDFJS:Parent:removeEventListener', this);
+      this._mmg.removeMessageListener('PDFJS:Parent:updateControlState', this);
+
       Services.obs.removeObserver(this, 'quit-application', false);
 
       this._mmg = null;
@@ -146,11 +151,13 @@ let PdfjsChromeUtils = {
         this._displayWarning(aMsg);
         break;
 
-      // CPOW getters
-      case 'PDFJS:Parent:getChromeWindow':
-        return this._getChromeWindow(aMsg);
-      case 'PDFJS:Parent:getFindBar':
-        return this._getFindBar(aMsg);
+
+      case 'PDFJS:Parent:updateControlState':
+        return this._updateControlState(aMsg);
+      case 'PDFJS:Parent:addEventListener':
+        return this._addEventListener(aMsg);
+      case 'PDFJS:Parent:removeEventListener':
+        return this._removeEventListener(aMsg);
     }
   },
 
@@ -158,24 +165,81 @@ let PdfjsChromeUtils = {
    * Internal
    */
 
-  _getChromeWindow: function (aMsg) {
-    // See the child module, our return result here can't be the element
-    // since return results don't get auto CPOW'd.
+  _findbarFromMessage: function(aMsg) {
     let browser = aMsg.target;
-    let wrapper = new PdfjsWindowWrapper(browser);
-    let suitcase = aMsg.objects.suitcase;
-    suitcase.setChromeWindow(wrapper);
-    return true;
+    let tabbrowser = browser.getTabBrowser();
+    let tab = tabbrowser.getTabForBrowser(browser);
+    return tabbrowser.getFindBar(tab);
+  },
+
+  _updateControlState: function (aMsg) {
+    let data = aMsg.data;
+    this._findbarFromMessage(aMsg)
+        .updateControlState(data.result, data.findPrevious);
   },
 
-  _getFindBar: function (aMsg) {
-    // We send this over via the window's message manager, so target should
-    // be the dom window.
+  handleEvent: function(aEvent) {
+    // We cannot just forward the message as a CPOW without setting up
+    // __exposedProps__ on it. Instead, let's just create a structured
+    // cloneable version of the event for performance and for the ease of usage.
+    let type = aEvent.type;
+    let detail = {
+      query: aEvent.detail.query,
+      caseSensitive: aEvent.detail.caseSensitive,
+      highlightAll: aEvent.detail.highlightAll,
+      findPrevious: aEvent.detail.findPrevious
+    };
+
+    let chromeWindow = aEvent.target.ownerDocument.defaultView;
+    let browser = chromeWindow.gBrowser.selectedBrowser;
+    if (this._browsers.has(browser)) {
+      // Only forward the events if the selected browser is a registered
+      // browser.
+      let mm = browser.messageManager;
+      mm.sendAsyncMessage('PDFJS:Child:handleEvent',
+                          { type: type, detail: detail });
+      aEvent.preventDefault();
+    }
+  },
+
+  _types: ['find',
+           'findagain',
+           'findhighlightallchange',
+           'findcasesensitivitychange'],
+
+  _addEventListener: function (aMsg) {
     let browser = aMsg.target;
-    let wrapper = new PdfjsFindbarWrapper(browser);
-    let suitcase = aMsg.objects.suitcase;
-    suitcase.setFindBar(wrapper);
-    return true;
+    if (this._browsers.has(browser)) {
+      throw new Error('FindEventManager was bound 2nd time ' +
+                      'without unbinding it first.');
+    }
+
+    // Since this jsm is global, we need to store all the browsers
+    // we have to forward the messages for.
+    this._browsers.add(browser);
+
+    // And we need to start listening to find events.
+    for (var i = 0; i < this._types.length; i++) {
+      var type = this._types[i];
+      this._findbarFromMessage(aMsg)
+          .addEventListener(type, this, true);
+    }
+  },
+
+  _removeEventListener: function (aMsg) {
+    let browser = aMsg.target;
+    if (!this._browsers.has(browser)) {
+      throw new Error('FindEventManager was unbound without binding it first.');
+    }
+
+    this._browsers.delete(browser);
+
+    // No reason to listen to find events any longer.
+    for (var i = 0; i < this._types.length; i++) {
+      var type = this._types[i];
+      this._findbarFromMessage(aMsg)
+          .removeEventListener(type, this, true);
+    }
   },
 
   _ensurePreferenceAllowed: function (aPrefName) {
@@ -268,62 +332,3 @@ let PdfjsChromeUtils = {
   }
 };
 
-/*
- * CPOW security features require chrome objects declare exposed
- * properties via __exposedProps__. We don't want to expose things
- * directly on the findbar, so we wrap the findbar in a smaller
- * object here that supports the features pdf.js needs.
- */
-function PdfjsFindbarWrapper(aBrowser) {
-  let tabbrowser = aBrowser.getTabBrowser();
-  let tab;
-//#if MOZCENTRAL
-  tab = tabbrowser.getTabForBrowser(aBrowser);
-//#else
-  if (tabbrowser.getTabForBrowser) {
-    tab = tabbrowser.getTabForBrowser(aBrowser);
-  } else {
-    // _getTabForBrowser is depreciated in Firefox 35, see
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=1039500.
-    tab = tabbrowser._getTabForBrowser(aBrowser);
-  }
-//#endif
-  this._findbar = tabbrowser.getFindBar(tab);
-}
-
-PdfjsFindbarWrapper.prototype = {
-  __exposedProps__: {
-    addEventListener: 'r',
-    removeEventListener: 'r',
-    updateControlState: 'r',
-  },
-  _findbar: null,
-
-  updateControlState: function (aResult, aFindPrevious) {
-    this._findbar.updateControlState(aResult, aFindPrevious);
-  },
-
-  addEventListener: function (aType, aListener, aUseCapture, aWantsUntrusted) {
-    this._findbar.addEventListener(aType, aListener, aUseCapture,
-                                   aWantsUntrusted);
-  },
-
-  removeEventListener: function (aType, aListener, aUseCapture) {
-    this._findbar.removeEventListener(aType, aListener, aUseCapture);
-  }
-};
-
-function PdfjsWindowWrapper(aBrowser) {
-  this._window = aBrowser.ownerDocument.defaultView;
-}
-
-PdfjsWindowWrapper.prototype = {
-  __exposedProps__: {
-    valueOf: 'r',
-  },
-  _window: null,
-
-  valueOf: function () {
-    return this._window.valueOf();
-  }
-};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git



More information about the Pkg-javascript-commits mailing list