summaryrefslogtreecommitdiffstats
path: root/comm/suite/browser/nsBrowserContentHandler.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/suite/browser/nsBrowserContentHandler.js')
-rw-r--r--comm/suite/browser/nsBrowserContentHandler.js634
1 files changed, 634 insertions, 0 deletions
diff --git a/comm/suite/browser/nsBrowserContentHandler.js b/comm/suite/browser/nsBrowserContentHandler.js
new file mode 100644
index 0000000000..5e6c37380f
--- /dev/null
+++ b/comm/suite/browser/nsBrowserContentHandler.js
@@ -0,0 +1,634 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const nsISupports = Ci.nsISupports;
+const nsIBrowserDOMWindow = Ci.nsIBrowserDOMWindow;
+const nsIBrowserHistory = Ci.nsIBrowserHistory;
+const nsIBrowserSearchService = Ci.nsIBrowserSearchService;
+const nsIChannel = Ci.nsIChannel;
+const nsICommandLine = Ci.nsICommandLine;
+const nsICommandLineHandler = Ci.nsICommandLineHandler;
+const nsICommandLineValidator = Ci.nsICommandLineValidator;
+const nsIComponentRegistrar = Ci.nsIComponentRegistrar;
+const nsIContentHandler = Ci.nsIContentHandler;
+const nsIDOMWindow = Ci.nsIDOMWindow;
+const nsIFactory = Ci.nsIFactory;
+const nsIFileURL = Ci.nsIFileURL;
+const nsIHttpProtocolHandler = Ci.nsIHttpProtocolHandler;
+const nsINetUtil = Ci.nsINetUtil;
+const nsIPrefService = Ci.nsIPrefService;
+const nsIPrefBranch = Ci.nsIPrefBranch;
+const nsIPrefLocalizedString = Ci.nsIPrefLocalizedString;
+const nsISupportsString = Ci.nsISupportsString;
+const nsIWindowMediator = Ci.nsIWindowMediator;
+const nsIWebNavigationInfo = Ci.nsIWebNavigationInfo;
+
+const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
+
+const URI_INHERITS_SECURITY_CONTEXT = nsIHttpProtocolHandler
+ .URI_INHERITS_SECURITY_CONTEXT;
+
+const NS_GENERAL_STARTUP_PREFIX = "@mozilla.org/commandlinehandler/general-startup;1?type=";
+
+function shouldLoadURI(aURI)
+{
+ if (aURI && !aURI.schemeIs("chrome"))
+ return true;
+
+ dump("*** Preventing external load of chrome: URI into browser window\n");
+ dump(" Use -chrome <uri> instead\n");
+ return false;
+}
+
+function resolveURIInternal(aCmdLine, aArgument)
+{
+ try {
+ var file = aCmdLine.resolveFile(aArgument);
+ if (file.exists()) {
+ return Services.io.newFileURI(file);
+ }
+ } catch (e) {
+ }
+
+ // We have interpreted the argument as a relative file URI, but the file
+ // doesn't exist. Try URI fixup heuristics: see bug 290782.
+
+ try {
+ return Services.uriFixup
+ .createFixupURI(aArgument,
+ Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP);
+ } catch (e) {
+ Cu.reportError(e);
+ }
+
+ return null;
+}
+
+function getHomePageGroup()
+{
+ var homePage = Services.prefs.getComplexValue("browser.startup.homepage",
+ nsIPrefLocalizedString).data;
+
+ var count = 0;
+ try {
+ count = Services.prefs.getIntPref("browser.startup.homepage.count");
+ } catch (e) {
+ }
+
+ for (var i = 1; i < count; ++i) {
+ try {
+ homePage += '\n' + Services.prefs.getStringPref("browser.startup.homepage." + i);
+ } catch (e) {
+ }
+ }
+ return homePage;
+}
+
+function needHomePageOverride()
+{
+ var savedmstone = null;
+ try {
+ savedmstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
+ if (savedmstone == "ignore")
+ return false;
+ } catch (e) {
+ }
+
+ var mstone = Cc["@mozilla.org/network/protocol;1?name=http"]
+ .getService(nsIHttpProtocolHandler).misc;
+
+ if (mstone == savedmstone)
+ return false;
+
+ Services.prefs.setCharPref("browser.startup.homepage_override.mstone", mstone);
+
+ return true;
+}
+
+function getURLToLoad()
+{
+ if (needHomePageOverride()) {
+ try {
+ return Services.urlFormatter.formatURLPref("startup.homepage_override_url");
+ } catch (e) {
+ }
+ }
+
+ try {
+ var ss = Cc["@mozilla.org/suite/sessionstartup;1"]
+ .getService(Ci.nsISessionStartup);
+ // return about:blank if we are restoring previous session
+ if (ss.doRestore())
+ return "about:blank";
+ } catch (e) {
+ }
+
+ try {
+ var st = Cc["@mozilla.org/suite/sessionstore;1"]
+ .getService(Ci.nsISessionStore);
+ // return about:blank if the last window was closed and should be restored
+ if (st.doRestoreLastWindow())
+ return "about:blank";
+ } catch (e) {
+ }
+
+ try {
+ switch (Services.prefs.getIntPref("browser.startup.page")) {
+ case 1:
+ return getHomePageGroup();
+
+ case 2:
+ return Services.prefs.getStringPref("browser.history.last_page_visited");
+ }
+ } catch (e) {
+ }
+
+ return "about:blank";
+}
+
+function openWindow(parent, url, features, arg)
+{
+ var argstring = Cc["@mozilla.org/supports-string;1"]
+ .createInstance(nsISupportsString);
+ argstring.data = arg;
+ return Services.ww.openWindow(parent, url, "", features, argstring);
+}
+
+function openPreferences()
+{
+ var win = Services.wm.getMostRecentWindow("mozilla:preferences");
+ if (win)
+ win.focus();
+ else
+ openWindow(null, "chrome://communicator/content/pref/preferences.xul",
+ "chrome,titlebar,dialog=no,resizable", "");
+}
+
+function getBrowserURL()
+{
+ try {
+ return Services.prefs.getCharPref("browser.chromeURL");
+ } catch (e) {
+ }
+ return "chrome://navigator/content/navigator.xul";
+}
+
+function handURIToExistingBrowser(aUri, aLocation, aFeatures, aTriggeringPrincipal)
+{
+ if (!shouldLoadURI(aUri))
+ return;
+
+ var navWin = Services.wm.getMostRecentWindow("navigator:browser");
+ if (!navWin) {
+ // if we couldn't load it in an existing window, open a new one
+ openWindow(null, getBrowserURL(), aFeatures, aUri.spec);
+ return;
+ }
+
+ navWin.browserDOMWindow.openURI(aUri, null, aLocation,
+ nsIBrowserDOMWindow.OPEN_EXTERNAL,
+ aTriggeringPrincipal);
+}
+
+function doSearch(aSearchTerm, aFeatures) {
+ var submission = Services.search.defaultEngine.getSubmission(aSearchTerm);
+
+ // fill our nsIMutableArray with uri-as-wstring, null, null, postData
+ var sa = Cc["@mozilla.org/array;1"]
+ .createInstance(Ci.nsIMutableArray);
+
+ var uristring = Cc["@mozilla.org/supports-string;1"]
+ .createInstance(nsISupportsString);
+ uristring.data = submission.uri.spec;
+
+ sa.appendElement(uristring);
+ sa.appendElement(null);
+ sa.appendElement(null);
+ sa.appendElement(submission.postData);
+
+ // XXXbsmedberg: use handURIToExistingBrowser to obey tabbed-browsing
+ // preferences, but need nsIBrowserDOMWindow extensions
+ return Services.ww.openWindow(null, getBrowserURL(), "_blank", aFeatures,
+ sa);
+}
+
+var nsBrowserContentHandler = {
+ get wrappedJSObject() {
+ return this;
+ },
+
+ /* nsISupports */
+ QueryInterface: function QueryInterface(iid) {
+ if (iid.equals(nsISupports) ||
+ iid.equals(nsICommandLineHandler) ||
+ iid.equals(nsICommandLine) ||
+ iid.equals(nsICommandLineValidator) ||
+ iid.equals(nsIContentHandler) ||
+ iid.equals(nsIFactory))
+ return this;
+
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ },
+
+ _handledURI: null,
+
+ /* nsICommandLineHandler */
+ handle: function handle(cmdLine) {
+ var features = "chrome,all,dialog=no";
+ try {
+ var width = cmdLine.handleFlagWithParam("width", false);
+ if (width != null)
+ features += ",width=" + width;
+ } catch (e) {
+ }
+ try {
+ var height = cmdLine.handleFlagWithParam("height", false);
+ if (height != null)
+ features += ",height=" + height;
+ } catch (e) {
+ }
+
+ try {
+ var remote = cmdLine.handleFlagWithParam("remote", true);
+ if (/^\s*(\w+)\s*\(\s*([^\s,]+)\s*,?\s*([^\s]*)\s*\)\s*$/.test(remote)) {
+ switch (RegExp.$1.toLowerCase()) {
+ case "openurl":
+ case "openfile":
+ // openURL(<url>)
+ // openURL(<url>,new-window)
+ // openURL(<url>,new-tab)
+
+ var uri = resolveURIInternal(cmdLine, RegExp.$2);
+
+ var location = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
+ if (RegExp.$3 == "new-window")
+ location = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
+ else if (RegExp.$3 == "new-tab")
+ location = nsIBrowserDOMWindow.OPEN_NEWTAB;
+
+ handURIToExistingBrowser(uri, location, features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ break;
+
+ case "mailto":
+ openWindow(null, "chrome://messenger/content/messengercompose/messengercompose.xul", features, RegExp.$2);
+ break;
+
+ case "xfedocommand":
+ switch (RegExp.$2.toLowerCase()) {
+ case "openbrowser":
+ openWindow(null, getBrowserURL(), features, RegExp.$3 || getURLToLoad());
+ break;
+
+ case "openinbox":
+ openWindow(null, "chrome://messenger/content", features);
+ break;
+
+ case "composemessage":
+ openWindow(null, "chrome://messenger/content/messengercompose/messengercompose.xul", features, RegExp.$3);
+ break;
+
+ default:
+ throw Cr.NS_ERROR_ABORT;
+ }
+ break;
+
+ default:
+ // Somebody sent us a remote command we don't know how to process:
+ // just abort.
+ throw Cr.NS_ERROR_ABORT;
+ }
+
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ // If we had a -remote flag but failed to process it, throw
+ // NS_ERROR_ABORT so that the xremote code knows to return a failure
+ // back to the handling code.
+ throw Cr.NS_ERROR_ABORT;
+ }
+
+ try {
+ var browserParam = cmdLine.handleFlagWithParam("browser", false);
+ if (browserParam) {
+ openWindow(null, getBrowserURL(), features, browserParam);
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ if (cmdLine.handleFlag("browser", false)) {
+ openWindow(null, getBrowserURL(), features, getURLToLoad());
+ cmdLine.preventDefault = true;
+ }
+ }
+
+ try {
+ var privateParam = cmdLine.handleFlagWithParam("private", false);
+ if (privateParam) {
+ openWindow(null, getBrowserURL(), "private," + features, privateParam);
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ if (cmdLine.handleFlag("private", false)) {
+ openWindow(null, getBrowserURL(), "private," + features, "about:privatebrowsing");
+ cmdLine.preventDefault = true;
+ }
+ }
+
+ // If we don't have a profile selected yet (e.g. the Profile Manager is
+ // displayed) we will crash if we open an url and then select a profile. To
+ // prevent this handle all url command line flag and set the command line's
+ // preventDefault to true to prevent the display of the ui. The initial
+ // command line will be retained when nsAppRunner calls LaunchChild though
+ // urls launched after the initial launch will be lost.
+ try {
+ // This will throw when a profile has not been selected.
+ Services.dirsvc.get("ProfD", Ci.nsIFile);
+ } catch (e) {
+ cmdLine.preventDefault = true;
+ throw Cr.NS_ERROR_ABORT;
+ }
+
+ try {
+ var urlParam = cmdLine.handleFlagWithParam("url", false);
+ if (urlParam) {
+ if (this._handledURI == urlParam) {
+ this._handledURI = null;
+ } else {
+ if (cmdLine.handleFlag("requestpending", false) &&
+ cmdLine.state == nsICommandLine.STATE_INITIAL_LAUNCH) {
+ // A DDE request with the URL will follow and the DDE handling code
+ // will send it to the commandline handler via
+ // "mozilla -url http://www.foo.com". Store the URL so we can
+ // ignore this request later
+ this._handledURI = urlParam;
+ }
+
+ urlParam = resolveURIInternal(cmdLine, urlParam);
+ handURIToExistingBrowser(urlParam,
+ nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
+ features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ }
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ }
+
+ var param;
+ try {
+ while ((param = cmdLine.handleFlagWithParam("new-window", false)) != null) {
+ var uri = resolveURIInternal(cmdLine, param);
+ handURIToExistingBrowser(uri,
+ nsIBrowserDOMWindow.OPEN_NEWWINDOW,
+ features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ }
+
+ try {
+ while ((param = cmdLine.handleFlagWithParam("new-tab", false)) != null) {
+ var uri = resolveURIInternal(cmdLine, param);
+ handURIToExistingBrowser(uri,
+ nsIBrowserDOMWindow.OPEN_NEWTAB,
+ features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ }
+
+ try {
+ var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
+ if (chromeParam) {
+ // only load URIs which do not inherit chrome privs
+ var uri = resolveURIInternal(cmdLine, chromeParam);
+ if (!Services.netUtils.URIChainHasFlags(uri, URI_INHERITS_SECURITY_CONTEXT)) {
+ openWindow(null, uri.spec, features);
+ cmdLine.preventDefault = true;
+ }
+ }
+ } catch (e) {
+ }
+
+ try {
+ var fileParam = cmdLine.handleFlagWithParam("file", false);
+ if (fileParam) {
+ fileParam = resolveURIInternal(cmdLine, fileParam);
+ handURIToExistingBrowser(fileParam,
+ nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
+ features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ cmdLine.preventDefault = true;
+ }
+ } catch (e) {
+ }
+
+ var searchParam = cmdLine.handleFlagWithParam("search", false);
+ if (searchParam) {
+ doSearch(searchParam, features);
+ cmdLine.preventDefault = true;
+ }
+
+ if (cmdLine.handleFlag("preferences", false)) {
+ openPreferences();
+ cmdLine.preventDefault = true;
+ }
+
+ if (cmdLine.handleFlag("silent", false))
+ cmdLine.preventDefault = true;
+
+ if (!cmdLine.preventDefault && cmdLine.length) {
+ var arg = cmdLine.getArgument(0);
+ if (!/^-/.test(arg)) {
+ try {
+ arg = resolveURIInternal(cmdLine, arg);
+ handURIToExistingBrowser(arg,
+ nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
+ features,
+ Services.scriptSecurityManager.getSystemPrincipal());
+ cmdLine.preventDefault = true;
+ } catch (e) {
+ }
+ }
+ }
+
+ if (!cmdLine.preventDefault) {
+ this.realCmdLine = cmdLine;
+
+ var prefBranch = Services.prefs.getBranch("general.startup.");
+
+ var startupArray = prefBranch.getChildList("");
+
+ for (var i = 0; i < startupArray.length; ++i) {
+ this.currentArgument = startupArray[i];
+ var contract = NS_GENERAL_STARTUP_PREFIX + this.currentArgument;
+ if (contract in Cc) {
+ // Ignore any exceptions - we can't do anything about them here.
+ try {
+ if (prefBranch.getBoolPref(this.currentArgument)) {
+ var handler = Cc[contract].getService(nsICommandLineHandler);
+ if (handler.wrappedJSObject)
+ handler.wrappedJSObject.handle(this);
+ else
+ handler.handle(this);
+ }
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ }
+
+ this.realCmdLine = null;
+ }
+
+ if (!cmdLine.preventDefault) {
+ var homePage = getURLToLoad();
+ if (!/\n/.test(homePage)) {
+ try {
+ let uri = Services.uriFixup.createFixupURI(homePage, 0);
+ handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, features);
+ cmdLine.preventDefault = true;
+ } catch (e) {
+ }
+ }
+
+ if (!cmdLine.preventDefault) {
+ openWindow(null, getBrowserURL(), features, homePage);
+ cmdLine.preventDefault = true;
+ }
+ }
+
+ },
+
+ /* nsICommandLineValidator */
+ validate: function validate(cmdLine) {
+ var osintFlagIdx = cmdLine.findFlag("osint", false);
+
+ // If the osint flag is not present and we are not called by DDE then we're safe
+ if (cmdLine.state != nsICommandLine.STATE_REMOTE_EXPLICIT &&
+ cmdLine.findFlag("osint", false) == -1)
+ return;
+
+ // Other handlers may use osint so only handle the osint flag if a
+ // flag is also present and the command line is valid.
+ ["url", "news", "compose"].forEach(function(value) {
+ var flagIdx = cmdLine.findFlag(value, false);
+
+ if (flagIdx > -1) {
+ var testExpr = new RegExp("seamonkey" + value + ":");
+ if (cmdLine.length != flagIdx + 2 ||
+ testExpr.test(cmdLine.getArgument(flagIdx + 1)))
+ throw Cr.NS_ERROR_ABORT;
+ cmdLine.handleFlag("osint", false);
+ }
+ });
+ },
+
+ helpInfo: " -browser <url> Open a browser window.\n" +
+ " -private <url> Open a private window.\n" +
+ " -new-window <url> Open <url> in a new browser window.\n" +
+ " -new-tab <url> Open <url> in a new browser tab.\n" +
+ " -url <url> Open the specified url.\n" +
+ " -chrome <url> Open the specified chrome.\n" +
+ " -search <term> Search <term> with your default search engine.\n" +
+ " -preferences Open Preferences dialog.\n",
+
+ /* nsICommandLine */
+ length: 1,
+
+ getArgument: function getArgument(index) {
+ if (index == 0)
+ return this.currentArgument;
+
+ throw Cr.NS_ERROR_INVALID_ARG;
+ },
+
+ findFlag: function findFlag(flag, caseSensitive) {
+ if (caseSensitive)
+ return flag == this.currentArgument ? 0 : -1;
+ return flag.toLowerCase() == this.currentArgument.toLowerCase() ? 0 : -1;
+ },
+
+ removeArguments: function removeArguments(start, end) {
+ // do nothing
+ },
+
+ handleFlag: function handleFlag(flag, caseSensitive) {
+ if (caseSensitive)
+ return flag == this.currentArgument;
+ return flag.toLowerCase() == this.currentArgument.toLowerCase();
+ },
+
+ handleFlagWithParam : function handleFlagWithParam(flag, caseSensitive) {
+ if (this.handleFlag(flag, caseSensitive))
+ throw Cr.NS_ERROR_INVALID_ARG;
+ },
+
+ get state() {
+ return this.realCmdLine.state;
+ },
+
+ get preventDefault() {
+ return this.realCmdLine.preventDefault;
+ },
+
+ set preventDefault(preventDefault) {
+ return this.realCmdLine.preventDefault = preventDefault;
+ },
+
+ get workingDirectory() {
+ return this.realCmdLine.workingDirectory;
+ },
+
+ get windowContext() {
+ return this.realCmdLine.windowContext;
+ },
+
+ resolveFile: function resolveFile(arg) {
+ return this.realCmdLine.resolveFile(arg);
+ },
+
+ resolveURI: function resolveURI(arg) {
+ return this.realCmdLine.resolveURI(arg);
+ },
+
+ /* nsIContentHandler */
+ handleContent: function handleContent(contentType, context, request) {
+ var webNavInfo = Cc["@mozilla.org/webnavigation-info;1"]
+ .getService(nsIWebNavigationInfo);
+ if (!webNavInfo.isTypeSupported(contentType, null))
+ throw NS_ERROR_WONT_HANDLE_CONTENT;
+
+ request.QueryInterface(nsIChannel);
+ handURIToExistingBrowser(request.URI,
+ nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
+ "chrome,all,dialog=no",
+ request.loadInfo.triggeringPrincipal);
+ request.cancel(Cr.NS_BINDING_ABORTED);
+ },
+
+ /* nsIFactory */
+ createInstance: function createInstance(outer, iid) {
+ if (outer != null)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+
+ return this.QueryInterface(iid);
+ },
+
+ lockFactory: function lockFactory(lock) {
+ /* no-op */
+ }
+};
+
+const BROWSER_CID = Components.ID("{c2343730-dc2c-11d3-98b3-001083010e9b}");
+
+function NSGetFactory(cid) {
+ if (cid.number == BROWSER_CID)
+ return nsBrowserContentHandler;
+ throw Cr.NS_ERROR_FACTORY_NOT_REGISTERED;
+}