Bug 570745 - [f10s] Save As PDF menu does nothing [r=mfinkle]
authorVivien Nicolas <21@vingtetun.org>
Thu, 10 Jun 2010 04:12:05 +0200
changeset 66272 3f70fd00c9b0b8e431bc99ccc573cd418ad1f57b
parent 66271 70e03eb070a95a26b70216db412491a1f454575d
child 66273 32c722dc928b81d4259a5ca98953a85e7573df68
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs570745
Bug 570745 - [f10s] Save As PDF menu does nothing [r=mfinkle]
mobile/chrome/content/browser-ui.js
mobile/chrome/content/browser.js
mobile/chrome/content/content.js
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -398,16 +398,19 @@ var BrowserUI = {
     tabs.addEventListener("TabOpen", this, true);
 
     // listen content messages
     messageManager.addMessageListener("DOMLinkAdded", this);
     messageManager.addMessageListener("DOMTitleChanged", this);
     messageManager.addMessageListener("DOMWillOpenModalDialog", this);
     messageManager.addMessageListener("DOMWindowClose", this);
 
+    // listen returns messages from content
+    messageManager.addMessageListener("Browser:SaveAs:Return", this);
+
     // listening mousedown for automatically dismiss some popups (e.g. larry)
     window.addEventListener("mousedown", this, true);
 
     // listening escape to dismiss dialog on VK_ESCAPE
     window.addEventListener("keypress", this, true);
 
     // listening AppCommand to handle special keys
     window.addEventListener("AppCommand", this, true);
@@ -684,17 +687,17 @@ var BrowserUI = {
       this.hidePanel();
       return;
     }
 
     // Only if there are no dialogs, popups, or panels open
     Browser.selectedBrowser.goBack();
   },
 
-  handleEvent: function (aEvent) {
+  handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
       // Browser events
       case "DOMMetaAdded":
         this._metaAdded(aEvent);
         break;
       case "TabSelect":
         this._tabSelect(aEvent);
         break;
@@ -745,32 +748,59 @@ var BrowserUI = {
         break;
       // Favicon events
       case "error":
         this._favicon.src = "";
         break;
     }
   },
 
-  receiveMessage: function(aMessage) {
+  receiveMessage: function receiveMessage(aMessage) {
     let browser = aMessage.target;
     switch (aMessage.name) {
       case "DOMTitleChanged":
         this._titleChanged(browser);
         break;
       case "DOMWillOpenModalDialog":
         return this._domWillOpenModalDialog(browser);
         break;
       case "DOMWindowClose":
         return this._domWindowClose(browser);
         break;
       case "DOMLinkAdded":
         if (Browser.selectedBrowser == browser)
           this._updateIcon(Browser.selectedBrowser.mIconURL);
         break;
+      case "Browser:SaveAs:Return":
+        let json = aMessage.json;
+        if (json.type != Ci.nsIPrintSettings.kOutputFormatPDF)
+          return;
+
+        let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
+        let db = dm.DBConnection;
+        let stmt = db.createStatement("UPDATE moz_downloads SET endTime = :endTime, state = :state WHERE id = :id");
+        stmt.params.endTime = Date.now() * 1000;
+        stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_FINISHED;
+        stmt.params.id = json.id;
+        stmt.execute();
+        stmt.finalize();
+
+        let download = dm.getDownload(json.id);
+        try {
+          DownloadsView.downloadCompleted(download);
+          let element = DownloadsView.getElementForDownload(json.id);
+          element.setAttribute("state", Ci.nsIDownloadManager.DOWNLOAD_FINISHED);
+          element.setAttribute("endTime", Date.now());
+          element.setAttribute("referrer", json.referrer);
+          DownloadsView._updateTime(element);
+          DownloadsView._updateStatus(element);
+        }
+        catch(e) {}
+        gObserverService.notifyObservers(download, "dl-done", null);
+        break;
     }
   },
 
   supportsCommand : function(cmd) {
     var isSupported = false;
     switch (cmd) {
       case "cmd_back":
       case "cmd_forward":
@@ -1017,56 +1047,35 @@ var PageActions = {
     });
 
     let lm = this._loginManager;
     if (!lm.getLoginSavingEnabled(host.prePath))
       lm.setLoginSavingEnabled(host.prePath, true);
   },
 
   _savePageAsPDF: function saveAsPDF() {
-    let contentWindow = Browser.selectedBrowser.contentWindow;
     let strings = Elements.browserBundle;
     let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     picker.init(window, strings.getString("pageactions.saveas.pdf"), Ci.nsIFilePicker.modeSave);
     picker.appendFilter("PDF", "*.pdf");
     picker.defaultExtension = "pdf";
 
-    let fileName = getDefaultFileName(null, null, contentWindow.document, null);
+    let browser = Browser.selectedBrowser;
+    let fileName = getDefaultFileName(null, browser.documentURI, browser.contentDocument, null);
 #ifdef MOZ_PLATFORM_MAEMO
     fileName = fileName.replace(/[\*\:\?]+/g, " ");
 #endif
     picker.defaultString = fileName + ".pdf";
 
     let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
     picker.displayDirectory = dm.defaultDownloadsDirectory;
-
     let rv = picker.show();
     if (rv == Ci.nsIFilePicker.returnCancel)
       return;
 
-    let printSettings = Cc["@mozilla.org/gfx/printsettings-service;1"]
-                          .getService(Ci.nsIPrintSettingsService)
-                          .newPrintSettings;
-    printSettings.printSilent = true;
-    printSettings.showPrintProgress = false;
-    printSettings.printBGImages = true;
-    printSettings.printBGColors = true;
-    printSettings.printToFile = true;
-    printSettings.toFileName = picker.file.path;
-    printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs;
-    printSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF;
-
-    //XXX we probably need a preference here, the header can be useful
-    printSettings.footerStrCenter = '';
-    printSettings.footerStrLeft   = '';
-    printSettings.footerStrRight  = '';
-    printSettings.headerStrCenter = '';
-    printSettings.headerStrLeft   = '';
-    printSettings.headerStrRight  = '';
-
     // We must manually add this to the download system
     let db = dm.DBConnection;
 
     let stmt = db.createStatement(
       "INSERT INTO moz_downloads (name, source, target, startTime, endTime, state, referrer) " +
       "VALUES (:name, :source, :target, :startTime, :endTime, :state, :referrer)"
     );
 
@@ -1076,58 +1085,32 @@ var PageActions = {
     stmt.params.target = gIOService.newFileURI(picker.file).spec;
     stmt.params.startTime = Date.now() * 1000;
     stmt.params.endTime = Date.now() * 1000;
     stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
     stmt.params.referrer = current;
     stmt.execute();
     stmt.finalize();
 
-    let newId = db.lastInsertRowID;
-    let listener = {
-      onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
-        if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
-          let stmt = db.createStatement("UPDATE moz_downloads SET endTime = :endTime, state = :state WHERE id = :id");
-          stmt.params.endTime = Date.now() * 1000;
-          stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_FINISHED;
-          stmt.params.id = newId;
-          stmt.execute();
-          stmt.finalize();
-
-          let download = dm.getDownload(newId);
-          try {
-            DownloadsView.downloadCompleted(download);
-            let element = DownloadsView.getElementForDownload(newId);
-            element.setAttribute("state", Ci.nsIDownloadManager.DOWNLOAD_FINISHED);
-            element.setAttribute("endTime", Date.now());
-            element.setAttribute("referrer", current);
-            DownloadsView._updateTime(element);
-            DownloadsView._updateStatus(element);
-          }
-          catch(e) {}
-          gObserverService.notifyObservers(download, "dl-done", null);
-        }
-      },
-      onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
-
-      // stubs for the nsIWebProgressListener interfaces which nsIWebBrowserPrint doesn't use.
-      onLocationChange : function() { throw "Unexpected onLocationChange"; },
-      onStatusChange   : function() { throw "Unexpected onStatusChange";   },
-      onSecurityChange : function() { throw "Unexpected onSecurityChange"; }
-    };
-
-    let download = dm.getDownload(newId);
+    let newItemId = db.lastInsertRowID;
+    let download = dm.getDownload(newItemId);
     try {
       DownloadsView.downloadStarted(download);
     }
     catch(e) {}
     gObserverService.notifyObservers(download, "dl-start", null);
 
-    let webBrowserPrint = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebBrowserPrint);
-    webBrowserPrint.print(printSettings, listener);
+    let data = {
+      type: Ci.nsIPrintSettings.kOutputFormatPDF,
+      id: newItemId,
+      referrer: current,
+      filePath: picker.file.path
+    };
+
+    Browser.selectedBrowser.messageManager.sendAsyncMessage("Browser:SaveAs", data);
   },
 
   updatePageSaveAs: function updatePageSaveAs() {
     this.removeItems("saveas");
     if (Browser.selectedBrowser.contentDocument instanceof XULDocument)
       return;
 
     let strings = Elements.browserBundle;
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -2955,17 +2955,17 @@ var OfflineApps = {
   _startFetching: function(aRequest) {
     let currentURI = gIOService.newURI(aRequest.location, aRequest.charset, null);
     let manifestURI = gIOService.newURI(aRequest.manifest, aRequest.charset, currentURI);
 
     let updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].getService(Ci.nsIOfflineCacheUpdateService);
     updateService.scheduleUpdate(manifestURI, currentURI);
   },
 
-  receiveMessage: function(aMessage) {
+  receiveMessage: function receiveMessage(aMessage) {
     if (aMessage.name == "MozApplicationManifest") {
       this.offlineAppRequested(aMessage.json);
     }
   }
 };
 
 function Tab() {
   this._id = null;
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -443,18 +443,16 @@ ContentFormManager.prototype = {
 
   closedFormAssistant: function() {
     if (this._navigator) {
       removeEventListener("keyup", this, false);
       this._navigator = null;
     }
   },
 
-  receiveMessage: Util.receiveMessage,
-
   receiveFennecClosedFormAssist: function() {
     this.closedFormAssistant();
   },
 
   receiveFennecFormPrevious: function() {
     if (this._navigator) {
       this._navigator.goToPrevious();
       sendMessage("FennecFormAssist", this._navigator.getJSON());
@@ -668,48 +666,120 @@ FormNavigator.prototype = {
   }
 };
 
 
 /** Can't think of a good description of this class.  It probably does too much? */
 function Content() {
   this._iconURI = null;
 
-  addMessageListener("FennecBlur", this);
-  addMessageListener("FennecFocus", this);
-  addMessageListener("FennecMousedown", this);
-  addMessageListener("FennecMouseup", this);
-  addMessageListener("FennecCancelMouse", this);
+  addMessageListener("Browser:Blur", this);
+  addMessageListener("Browser:Focus", this);
+  addMessageListener("Browser:Mousedown", this);
+  addMessageListener("Browser:Mouseup", this);
+  addMessageListener("Browser:CancelMouse", this);
+  addMessageListener("Browser:SaveAs", this);
 
   this._coalescer = new Coalescer();
   addEventListener("MozAfterPaint", this._coalescer, false);
   addEventListener("MozScrolledAreaChanged", this._coalescer, false);
   addEventListener("MozApplicationManifest", this._coalescer, false);
 
   this._progressController = new ProgressController(this);
   this._progressController.start();
 
   this._contentFormManager = new ContentFormManager();
 
   this._mousedownTimeout = new Util.Timeout();
 }
 
 Content.prototype = {
-  handleEvent: Util.handleEvent,
+  receiveMessage: function receiveMessage(aMessage) {
+    let json = aMessage.json;
+
+    switch (aMessage.name) {
+      case "Browser:Blur": 
+        docShell.isOffScreenBrowser = false;
+        this._selected = false;
+        break;
+
+      case "Browser:Focus":
+        docShell.isOffScreenBrowser = true;
+        this._selected = true;
+        break;
 
-  receiveMessage: Util.receiveMessage,
+      case "Browser:Mousedown":
+        this._mousedownTimeout.once(kTapOverlayTimeout, function() {
+          let element = elementFromPoint(x, y);
+          gFocusManager.setFocus(element, Ci.nsIFocusManager.FLAG_NOSCROLL);
+        });
+        break;
+
+      case "Browser:Mouseup":
+        this._mousedownTimeout.flush();
+
+        let element = elementFromPoint(x, y);
+        if (!this._contentFormManager.formAssist(element)) {
+          this._sendMouseEvent("mousedown", element, x, y);
+          this._sendMouseEvent("mouseup", element, x, y);
+        }
+        break;
+
+      case "Browser:CancelMouse":
+        this._mousedownTimeout.clear();
+        // XXX there must be a better way than this to cancel the mouseover/focus?
+        this._sendMouseEvent("mouseup", null, -1000, -1000);
+        try {
+          content.document.activeElement.blur();
+        }
+        catch(e) {}
+        break;
 
-  receiveFennecFocus: function receiveFennecFocus() {
-    docShell.isOffScreenBrowser = true;
-    this._selected = true;
-  },
+      case "Browser:SaveAs":
+        if (json.type != Ci.nsIPrintSettings.kOutputFormatPDF)
+          return;
+
+        let printSettings = Cc["@mozilla.org/gfx/printsettings-service;1"]
+                              .getService(Ci.nsIPrintSettingsService)
+                              .newPrintSettings;
+        printSettings.printSilent = true;
+        printSettings.showPrintProgress = false;
+        printSettings.printBGImages = true;
+        printSettings.printBGColors = true;
+        printSettings.printToFile = true;
+        printSettings.toFileName = json.filePath;
+        printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs;
+        printSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF;
 
-  receiveFennecBlur: function receiveFennecBlur() {
-    docShell.isOffScreenBrowser = false;
-    this._selected = false;
+        //XXX we probably need a preference here, the header can be useful
+        printSettings.footerStrCenter = "";
+        printSettings.footerStrLeft   = "";
+        printSettings.footerStrRight  = "";
+        printSettings.headerStrCenter = "";
+        printSettings.headerStrLeft   = "";
+        printSettings.headerStrRight  = "";
+
+        let listener = {
+          onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
+            if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
+              sendAsyncMessage("Browser:SaveAs:Return", { type: json.type, id: json.id, referrer: json.referrer });
+            }
+          },
+          onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
+
+          // stubs for the nsIWebProgressListener interfaces which nsIWebBrowserPrint doesn't use.
+          onLocationChange : function() { throw "Unexpected onLocationChange"; },
+          onStatusChange   : function() { throw "Unexpected onStatusChange";   },
+          onSecurityChange : function() { throw "Unexpected onSecurityChange"; }
+        };
+
+        let webBrowserPrint = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebBrowserPrint);
+        webBrowserPrint.print(printSettings, listener);
+        break;
+    }
   },
 
   _sendMouseEvent: function _sendMouseEvent(name, element, x, y) {
     let windowUtils = Util.getWindowUtils(content);
     let scrollOffset = Util.getScrollOffset(content);
 
     // the element can be out of the cX/cY point because of the touch radius
     let rect = getBoundingContentRect(element);
@@ -719,42 +789,16 @@ Content.prototype = {
       let point = rect.center();
       x = point.x;
       y = point.y;
     }
 
     windowUtils.sendMouseEvent(name, x - scrollOffset.x, y - scrollOffset.y, 0, 1, 0, true);
   },
 
-  receiveFennecMousedown: function receiveFennecMousedown(message, x, y) {
-    this._mousedownTimeout.once(kTapOverlayTimeout, function() {
-      let element = elementFromPoint(x, y);
-      gFocusManager.setFocus(element, Ci.nsIFocusManager.FLAG_NOSCROLL);
-    });
-  },
-
-  receiveFennecMouseup: function receiveFennecMouseup(message, x, y) {
-    this._mousedownTimeout.flush();
-
-    let element = elementFromPoint(x, y);
-    if (!this._contentFormManager.formAssist(element)) {
-      this._sendMouseEvent("mousedown", element, x, y);
-      this._sendMouseEvent("mouseup", element, x, y);
-    }
-  },
-
-  receiveFennecCancelMouse: function receiveFennecCancelMouse() {
-    this._mousedownTimeout.clear();
-    // XXX there must be a better way than this to cancel the mouseover/focus?
-    this._sendMouseEvent("mouseup", null, -1000, -1000);
-    let element = content.document.activeElement;
-    if (element)
-      element.blur();
-  },
-
   startLoading: function startLoading() {
     this._loading = true;
     this._iconURI = null;
     this._coalescer.emptyPage();
     this._coalescer.startCoalescing();
   },
 
   stopLoading: function stopLoading() {