Bug 570745 - [f10s] Save As PDF menu does nothing [r=mfinkle]
--- 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() {