browser/components/nsBrowserContentHandler.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4
michael@0 5 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 6 Components.utils.import("resource://gre/modules/Services.jsm");
michael@0 7
michael@0 8 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
michael@0 9 "resource://gre/modules/PrivateBrowsingUtils.jsm");
michael@0 10 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
michael@0 11 "resource:///modules/RecentWindow.jsm");
michael@0 12
michael@0 13 const nsISupports = Components.interfaces.nsISupports;
michael@0 14
michael@0 15 const nsIBrowserDOMWindow = Components.interfaces.nsIBrowserDOMWindow;
michael@0 16 const nsIBrowserHandler = Components.interfaces.nsIBrowserHandler;
michael@0 17 const nsIBrowserHistory = Components.interfaces.nsIBrowserHistory;
michael@0 18 const nsIChannel = Components.interfaces.nsIChannel;
michael@0 19 const nsICommandLine = Components.interfaces.nsICommandLine;
michael@0 20 const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
michael@0 21 const nsIContentHandler = Components.interfaces.nsIContentHandler;
michael@0 22 const nsIDocShellTreeItem = Components.interfaces.nsIDocShellTreeItem;
michael@0 23 const nsIDOMChromeWindow = Components.interfaces.nsIDOMChromeWindow;
michael@0 24 const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
michael@0 25 const nsIFileURL = Components.interfaces.nsIFileURL;
michael@0 26 const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor;
michael@0 27 const nsINetUtil = Components.interfaces.nsINetUtil;
michael@0 28 const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
michael@0 29 const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
michael@0 30 const nsISupportsString = Components.interfaces.nsISupportsString;
michael@0 31 const nsIURIFixup = Components.interfaces.nsIURIFixup;
michael@0 32 const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
michael@0 33 const nsIWindowMediator = Components.interfaces.nsIWindowMediator;
michael@0 34 const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
michael@0 35 const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo;
michael@0 36 const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
michael@0 37 const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
michael@0 38
michael@0 39 const NS_BINDING_ABORTED = Components.results.NS_BINDING_ABORTED;
michael@0 40 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
michael@0 41 const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
michael@0 42
michael@0 43 const URI_INHERITS_SECURITY_CONTEXT = Components.interfaces.nsIHttpProtocolHandler
michael@0 44 .URI_INHERITS_SECURITY_CONTEXT;
michael@0 45
michael@0 46 function shouldLoadURI(aURI) {
michael@0 47 if (aURI && !aURI.schemeIs("chrome"))
michael@0 48 return true;
michael@0 49
michael@0 50 dump("*** Preventing external load of chrome: URI into browser window\n");
michael@0 51 dump(" Use -chrome <uri> instead\n");
michael@0 52 return false;
michael@0 53 }
michael@0 54
michael@0 55 function resolveURIInternal(aCmdLine, aArgument) {
michael@0 56 var uri = aCmdLine.resolveURI(aArgument);
michael@0 57 var urifixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
michael@0 58 .getService(nsIURIFixup);
michael@0 59
michael@0 60 if (!(uri instanceof nsIFileURL)) {
michael@0 61 return urifixup.createFixupURI(aArgument,
michael@0 62 urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS);
michael@0 63 }
michael@0 64
michael@0 65 try {
michael@0 66 if (uri.file.exists())
michael@0 67 return uri;
michael@0 68 }
michael@0 69 catch (e) {
michael@0 70 Components.utils.reportError(e);
michael@0 71 }
michael@0 72
michael@0 73 // We have interpreted the argument as a relative file URI, but the file
michael@0 74 // doesn't exist. Try URI fixup heuristics: see bug 290782.
michael@0 75
michael@0 76 try {
michael@0 77 uri = urifixup.createFixupURI(aArgument, 0);
michael@0 78 }
michael@0 79 catch (e) {
michael@0 80 Components.utils.reportError(e);
michael@0 81 }
michael@0 82
michael@0 83 return uri;
michael@0 84 }
michael@0 85
michael@0 86 var gFirstWindow = false;
michael@0 87
michael@0 88 const OVERRIDE_NONE = 0;
michael@0 89 const OVERRIDE_NEW_PROFILE = 1;
michael@0 90 const OVERRIDE_NEW_MSTONE = 2;
michael@0 91 const OVERRIDE_NEW_BUILD_ID = 3;
michael@0 92 /**
michael@0 93 * Determines whether a home page override is needed.
michael@0 94 * Returns:
michael@0 95 * OVERRIDE_NEW_PROFILE if this is the first run with a new profile.
michael@0 96 * OVERRIDE_NEW_MSTONE if this is the first run with a build with a different
michael@0 97 * Gecko milestone (i.e. right after an upgrade).
michael@0 98 * OVERRIDE_NEW_BUILD_ID if this is the first run with a new build ID of the
michael@0 99 * same Gecko milestone (i.e. after a nightly upgrade).
michael@0 100 * OVERRIDE_NONE otherwise.
michael@0 101 */
michael@0 102 function needHomepageOverride(prefb) {
michael@0 103 var savedmstone = null;
michael@0 104 try {
michael@0 105 savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone");
michael@0 106 } catch (e) {}
michael@0 107
michael@0 108 if (savedmstone == "ignore")
michael@0 109 return OVERRIDE_NONE;
michael@0 110
michael@0 111 var mstone = Services.appinfo.platformVersion;
michael@0 112
michael@0 113 var savedBuildID = null;
michael@0 114 try {
michael@0 115 savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID");
michael@0 116 } catch (e) {}
michael@0 117
michael@0 118 var buildID = Services.appinfo.platformBuildID;
michael@0 119
michael@0 120 if (mstone != savedmstone) {
michael@0 121 // Bug 462254. Previous releases had a default pref to suppress the EULA
michael@0 122 // agreement if the platform's installer had already shown one. Now with
michael@0 123 // about:rights we've removed the EULA stuff and default pref, but we need
michael@0 124 // a way to make existing profiles retain the default that we removed.
michael@0 125 if (savedmstone)
michael@0 126 prefb.setBoolPref("browser.rights.3.shown", true);
michael@0 127
michael@0 128 prefb.setCharPref("browser.startup.homepage_override.mstone", mstone);
michael@0 129 prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
michael@0 130 return (savedmstone ? OVERRIDE_NEW_MSTONE : OVERRIDE_NEW_PROFILE);
michael@0 131 }
michael@0 132
michael@0 133 if (buildID != savedBuildID) {
michael@0 134 prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
michael@0 135 return OVERRIDE_NEW_BUILD_ID;
michael@0 136 }
michael@0 137
michael@0 138 return OVERRIDE_NONE;
michael@0 139 }
michael@0 140
michael@0 141 /**
michael@0 142 * Gets the override page for the first run after the application has been
michael@0 143 * updated.
michael@0 144 * @param defaultOverridePage
michael@0 145 * The default override page.
michael@0 146 * @return The override page.
michael@0 147 */
michael@0 148 function getPostUpdateOverridePage(defaultOverridePage) {
michael@0 149 var um = Components.classes["@mozilla.org/updates/update-manager;1"]
michael@0 150 .getService(Components.interfaces.nsIUpdateManager);
michael@0 151 try {
michael@0 152 // If the updates.xml file is deleted then getUpdateAt will throw.
michael@0 153 var update = um.getUpdateAt(0)
michael@0 154 .QueryInterface(Components.interfaces.nsIPropertyBag);
michael@0 155 } catch (e) {
michael@0 156 // This should never happen.
michael@0 157 Components.utils.reportError("Unable to find update: " + e);
michael@0 158 return defaultOverridePage;
michael@0 159 }
michael@0 160
michael@0 161 let actions = update.getProperty("actions");
michael@0 162 // When the update doesn't specify actions fallback to the original behavior
michael@0 163 // of displaying the default override page.
michael@0 164 if (!actions)
michael@0 165 return defaultOverridePage;
michael@0 166
michael@0 167 // The existence of silent or the non-existence of showURL in the actions both
michael@0 168 // mean that an override page should not be displayed.
michael@0 169 if (actions.indexOf("silent") != -1 || actions.indexOf("showURL") == -1)
michael@0 170 return "";
michael@0 171
michael@0 172 return update.getProperty("openURL") || defaultOverridePage;
michael@0 173 }
michael@0 174
michael@0 175 // Flag used to indicate that the arguments to openWindow can be passed directly.
michael@0 176 const NO_EXTERNAL_URIS = 1;
michael@0 177
michael@0 178 function openWindow(parent, url, target, features, args, noExternalArgs) {
michael@0 179 var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
michael@0 180 .getService(nsIWindowWatcher);
michael@0 181
michael@0 182 if (noExternalArgs == NO_EXTERNAL_URIS) {
michael@0 183 // Just pass in the defaultArgs directly
michael@0 184 var argstring;
michael@0 185 if (args) {
michael@0 186 argstring = Components.classes["@mozilla.org/supports-string;1"]
michael@0 187 .createInstance(nsISupportsString);
michael@0 188 argstring.data = args;
michael@0 189 }
michael@0 190
michael@0 191 return wwatch.openWindow(parent, url, target, features, argstring);
michael@0 192 }
michael@0 193
michael@0 194 // Pass an array to avoid the browser "|"-splitting behavior.
michael@0 195 var argArray = Components.classes["@mozilla.org/supports-array;1"]
michael@0 196 .createInstance(Components.interfaces.nsISupportsArray);
michael@0 197
michael@0 198 // add args to the arguments array
michael@0 199 var stringArgs = null;
michael@0 200 if (args instanceof Array) // array
michael@0 201 stringArgs = args;
michael@0 202 else if (args) // string
michael@0 203 stringArgs = [args];
michael@0 204
michael@0 205 if (stringArgs) {
michael@0 206 // put the URIs into argArray
michael@0 207 var uriArray = Components.classes["@mozilla.org/supports-array;1"]
michael@0 208 .createInstance(Components.interfaces.nsISupportsArray);
michael@0 209 stringArgs.forEach(function (uri) {
michael@0 210 var sstring = Components.classes["@mozilla.org/supports-string;1"]
michael@0 211 .createInstance(nsISupportsString);
michael@0 212 sstring.data = uri;
michael@0 213 uriArray.AppendElement(sstring);
michael@0 214 });
michael@0 215 argArray.AppendElement(uriArray);
michael@0 216 } else {
michael@0 217 argArray.AppendElement(null);
michael@0 218 }
michael@0 219
michael@0 220 // Pass these as null to ensure that we always trigger the "single URL"
michael@0 221 // behavior in browser.js's gBrowserInit.onLoad (which handles the window
michael@0 222 // arguments)
michael@0 223 argArray.AppendElement(null); // charset
michael@0 224 argArray.AppendElement(null); // referer
michael@0 225 argArray.AppendElement(null); // postData
michael@0 226 argArray.AppendElement(null); // allowThirdPartyFixup
michael@0 227
michael@0 228 return wwatch.openWindow(parent, url, target, features, argArray);
michael@0 229 }
michael@0 230
michael@0 231 function openPreferences() {
michael@0 232 if (Services.prefs.getBoolPref("browser.preferences.inContent")) {
michael@0 233 var sa = Components.classes["@mozilla.org/supports-array;1"]
michael@0 234 .createInstance(Components.interfaces.nsISupportsArray);
michael@0 235
michael@0 236 var wuri = Components.classes["@mozilla.org/supports-string;1"]
michael@0 237 .createInstance(Components.interfaces.nsISupportsString);
michael@0 238 wuri.data = "about:preferences";
michael@0 239
michael@0 240 sa.AppendElement(wuri);
michael@0 241
michael@0 242 var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
michael@0 243 .getService(nsIWindowWatcher);
michael@0 244
michael@0 245 wwatch.openWindow(null, gBrowserContentHandler.chromeURL,
michael@0 246 "_blank",
michael@0 247 "chrome,dialog=no,all",
michael@0 248 sa);
michael@0 249 } else {
michael@0 250 var features = "chrome,titlebar,toolbar,centerscreen,dialog=no";
michael@0 251 var url = "chrome://browser/content/preferences/preferences.xul";
michael@0 252
michael@0 253 var win = getMostRecentWindow("Browser:Preferences");
michael@0 254 if (win) {
michael@0 255 win.focus();
michael@0 256 } else {
michael@0 257 openWindow(null, url, "_blank", features);
michael@0 258 }
michael@0 259 }
michael@0 260 }
michael@0 261
michael@0 262 function getMostRecentWindow(aType) {
michael@0 263 var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
michael@0 264 .getService(nsIWindowMediator);
michael@0 265 return wm.getMostRecentWindow(aType);
michael@0 266 }
michael@0 267
michael@0 268 function doSearch(searchTerm, cmdLine) {
michael@0 269 var ss = Components.classes["@mozilla.org/browser/search-service;1"]
michael@0 270 .getService(nsIBrowserSearchService);
michael@0 271
michael@0 272 var submission = ss.defaultEngine.getSubmission(searchTerm);
michael@0 273
michael@0 274 // fill our nsISupportsArray with uri-as-wstring, null, null, postData
michael@0 275 var sa = Components.classes["@mozilla.org/supports-array;1"]
michael@0 276 .createInstance(Components.interfaces.nsISupportsArray);
michael@0 277
michael@0 278 var wuri = Components.classes["@mozilla.org/supports-string;1"]
michael@0 279 .createInstance(Components.interfaces.nsISupportsString);
michael@0 280 wuri.data = submission.uri.spec;
michael@0 281
michael@0 282 sa.AppendElement(wuri);
michael@0 283 sa.AppendElement(null);
michael@0 284 sa.AppendElement(null);
michael@0 285 sa.AppendElement(submission.postData);
michael@0 286
michael@0 287 // XXXbsmedberg: use handURIToExistingBrowser to obey tabbed-browsing
michael@0 288 // preferences, but need nsIBrowserDOMWindow extensions
michael@0 289
michael@0 290 var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
michael@0 291 .getService(nsIWindowWatcher);
michael@0 292
michael@0 293 return wwatch.openWindow(null, gBrowserContentHandler.chromeURL,
michael@0 294 "_blank",
michael@0 295 "chrome,dialog=no,all" +
michael@0 296 gBrowserContentHandler.getFeatures(cmdLine),
michael@0 297 sa);
michael@0 298 }
michael@0 299
michael@0 300 function nsBrowserContentHandler() {
michael@0 301 }
michael@0 302 nsBrowserContentHandler.prototype = {
michael@0 303 classID: Components.ID("{5d0ce354-df01-421a-83fb-7ead0990c24e}"),
michael@0 304
michael@0 305 _xpcom_factory: {
michael@0 306 createInstance: function bch_factory_ci(outer, iid) {
michael@0 307 if (outer)
michael@0 308 throw Components.results.NS_ERROR_NO_AGGREGATION;
michael@0 309 return gBrowserContentHandler.QueryInterface(iid);
michael@0 310 }
michael@0 311 },
michael@0 312
michael@0 313 /* helper functions */
michael@0 314
michael@0 315 mChromeURL : null,
michael@0 316
michael@0 317 get chromeURL() {
michael@0 318 if (this.mChromeURL) {
michael@0 319 return this.mChromeURL;
michael@0 320 }
michael@0 321
michael@0 322 var prefb = Components.classes["@mozilla.org/preferences-service;1"]
michael@0 323 .getService(nsIPrefBranch);
michael@0 324 this.mChromeURL = prefb.getCharPref("browser.chromeURL");
michael@0 325
michael@0 326 return this.mChromeURL;
michael@0 327 },
michael@0 328
michael@0 329 /* nsISupports */
michael@0 330 QueryInterface : XPCOMUtils.generateQI([nsICommandLineHandler,
michael@0 331 nsIBrowserHandler,
michael@0 332 nsIContentHandler,
michael@0 333 nsICommandLineValidator]),
michael@0 334
michael@0 335 /* nsICommandLineHandler */
michael@0 336 handle : function bch_handle(cmdLine) {
michael@0 337 if (cmdLine.handleFlag("browser", false)) {
michael@0 338 // Passing defaultArgs, so use NO_EXTERNAL_URIS
michael@0 339 openWindow(null, this.chromeURL, "_blank",
michael@0 340 "chrome,dialog=no,all" + this.getFeatures(cmdLine),
michael@0 341 this.defaultArgs, NO_EXTERNAL_URIS);
michael@0 342 cmdLine.preventDefault = true;
michael@0 343 }
michael@0 344
michael@0 345 try {
michael@0 346 var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
michael@0 347 }
michael@0 348 catch (e) {
michael@0 349 throw NS_ERROR_ABORT;
michael@0 350 }
michael@0 351
michael@0 352 if (remoteCommand != null) {
michael@0 353 try {
michael@0 354 var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
michael@0 355 var remoteVerb;
michael@0 356 if (a) {
michael@0 357 remoteVerb = a[1].toLowerCase();
michael@0 358 var remoteParams = [];
michael@0 359 var sepIndex = a[2].lastIndexOf(",");
michael@0 360 if (sepIndex == -1)
michael@0 361 remoteParams[0] = a[2];
michael@0 362 else {
michael@0 363 remoteParams[0] = a[2].substring(0, sepIndex);
michael@0 364 remoteParams[1] = a[2].substring(sepIndex + 1);
michael@0 365 }
michael@0 366 }
michael@0 367
michael@0 368 switch (remoteVerb) {
michael@0 369 case "openurl":
michael@0 370 case "openfile":
michael@0 371 // openURL(<url>)
michael@0 372 // openURL(<url>,new-window)
michael@0 373 // openURL(<url>,new-tab)
michael@0 374
michael@0 375 // First param is the URL, second param (if present) is the "target"
michael@0 376 // (tab, window)
michael@0 377 var url = remoteParams[0];
michael@0 378 var target = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
michael@0 379 if (remoteParams[1]) {
michael@0 380 var targetParam = remoteParams[1].toLowerCase()
michael@0 381 .replace(/^\s*|\s*$/g, "");
michael@0 382 if (targetParam == "new-tab")
michael@0 383 target = nsIBrowserDOMWindow.OPEN_NEWTAB;
michael@0 384 else if (targetParam == "new-window")
michael@0 385 target = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
michael@0 386 else {
michael@0 387 // The "target" param isn't one of our supported values, so
michael@0 388 // assume it's part of a URL that contains commas.
michael@0 389 url += "," + remoteParams[1];
michael@0 390 }
michael@0 391 }
michael@0 392
michael@0 393 var uri = resolveURIInternal(cmdLine, url);
michael@0 394 handURIToExistingBrowser(uri, target, cmdLine);
michael@0 395 break;
michael@0 396
michael@0 397 case "xfedocommand":
michael@0 398 // xfeDoCommand(openBrowser)
michael@0 399 if (remoteParams[0].toLowerCase() != "openbrowser")
michael@0 400 throw NS_ERROR_ABORT;
michael@0 401
michael@0 402 // Passing defaultArgs, so use NO_EXTERNAL_URIS
michael@0 403 openWindow(null, this.chromeURL, "_blank",
michael@0 404 "chrome,dialog=no,all" + this.getFeatures(cmdLine),
michael@0 405 this.defaultArgs, NO_EXTERNAL_URIS);
michael@0 406 break;
michael@0 407
michael@0 408 default:
michael@0 409 // Somebody sent us a remote command we don't know how to process:
michael@0 410 // just abort.
michael@0 411 throw "Unknown remote command.";
michael@0 412 }
michael@0 413
michael@0 414 cmdLine.preventDefault = true;
michael@0 415 }
michael@0 416 catch (e) {
michael@0 417 Components.utils.reportError(e);
michael@0 418 // If we had a -remote flag but failed to process it, throw
michael@0 419 // NS_ERROR_ABORT so that the xremote code knows to return a failure
michael@0 420 // back to the handling code.
michael@0 421 throw NS_ERROR_ABORT;
michael@0 422 }
michael@0 423 }
michael@0 424
michael@0 425 var uriparam;
michael@0 426 try {
michael@0 427 while ((uriparam = cmdLine.handleFlagWithParam("new-window", false))) {
michael@0 428 var uri = resolveURIInternal(cmdLine, uriparam);
michael@0 429 if (!shouldLoadURI(uri))
michael@0 430 continue;
michael@0 431 openWindow(null, this.chromeURL, "_blank",
michael@0 432 "chrome,dialog=no,all" + this.getFeatures(cmdLine),
michael@0 433 uri.spec);
michael@0 434 cmdLine.preventDefault = true;
michael@0 435 }
michael@0 436 }
michael@0 437 catch (e) {
michael@0 438 Components.utils.reportError(e);
michael@0 439 }
michael@0 440
michael@0 441 try {
michael@0 442 while ((uriparam = cmdLine.handleFlagWithParam("new-tab", false))) {
michael@0 443 var uri = resolveURIInternal(cmdLine, uriparam);
michael@0 444 handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine);
michael@0 445 cmdLine.preventDefault = true;
michael@0 446 }
michael@0 447 }
michael@0 448 catch (e) {
michael@0 449 Components.utils.reportError(e);
michael@0 450 }
michael@0 451
michael@0 452 var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
michael@0 453 if (chromeParam) {
michael@0 454
michael@0 455 // Handle old preference dialog URLs.
michael@0 456 if (chromeParam == "chrome://browser/content/pref/pref.xul" ||
michael@0 457 (Services.prefs.getBoolPref("browser.preferences.inContent") &&
michael@0 458 chromeParam == "chrome://browser/content/preferences/preferences.xul")) {
michael@0 459 openPreferences();
michael@0 460 cmdLine.preventDefault = true;
michael@0 461 } else try {
michael@0 462 // only load URIs which do not inherit chrome privs
michael@0 463 var features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
michael@0 464 var uri = resolveURIInternal(cmdLine, chromeParam);
michael@0 465 var netutil = Components.classes["@mozilla.org/network/util;1"]
michael@0 466 .getService(nsINetUtil);
michael@0 467 if (!netutil.URIChainHasFlags(uri, URI_INHERITS_SECURITY_CONTEXT)) {
michael@0 468 openWindow(null, uri.spec, "_blank", features);
michael@0 469 cmdLine.preventDefault = true;
michael@0 470 }
michael@0 471 }
michael@0 472 catch (e) {
michael@0 473 Components.utils.reportError(e);
michael@0 474 }
michael@0 475 }
michael@0 476 if (cmdLine.handleFlag("preferences", false)) {
michael@0 477 openPreferences();
michael@0 478 cmdLine.preventDefault = true;
michael@0 479 }
michael@0 480 if (cmdLine.handleFlag("silent", false))
michael@0 481 cmdLine.preventDefault = true;
michael@0 482
michael@0 483 try {
michael@0 484 var privateWindowParam = cmdLine.handleFlagWithParam("private-window", false);
michael@0 485 if (privateWindowParam) {
michael@0 486 var uri = resolveURIInternal(cmdLine, privateWindowParam);
michael@0 487 handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true);
michael@0 488 cmdLine.preventDefault = true;
michael@0 489 }
michael@0 490 } catch (e if e.result == Components.results.NS_ERROR_INVALID_ARG) {
michael@0 491 // NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param.
michael@0 492 if (cmdLine.handleFlag("private-window", false)) {
michael@0 493 openWindow(null, this.chromeURL, "_blank",
michael@0 494 "chrome,dialog=no,private,all" + this.getFeatures(cmdLine),
michael@0 495 "about:privatebrowsing");
michael@0 496 cmdLine.preventDefault = true;
michael@0 497 }
michael@0 498 }
michael@0 499
michael@0 500 var searchParam = cmdLine.handleFlagWithParam("search", false);
michael@0 501 if (searchParam) {
michael@0 502 doSearch(searchParam, cmdLine);
michael@0 503 cmdLine.preventDefault = true;
michael@0 504 }
michael@0 505
michael@0 506 // The global PB Service consumes this flag, so only eat it in per-window
michael@0 507 // PB builds.
michael@0 508 if (cmdLine.handleFlag("private", false)) {
michael@0 509 PrivateBrowsingUtils.enterTemporaryAutoStartMode();
michael@0 510 }
michael@0 511
michael@0 512 var fileParam = cmdLine.handleFlagWithParam("file", false);
michael@0 513 if (fileParam) {
michael@0 514 var file = cmdLine.resolveFile(fileParam);
michael@0 515 var ios = Components.classes["@mozilla.org/network/io-service;1"]
michael@0 516 .getService(Components.interfaces.nsIIOService);
michael@0 517 var uri = ios.newFileURI(file);
michael@0 518 openWindow(null, this.chromeURL, "_blank",
michael@0 519 "chrome,dialog=no,all" + this.getFeatures(cmdLine),
michael@0 520 uri.spec);
michael@0 521 cmdLine.preventDefault = true;
michael@0 522 }
michael@0 523
michael@0 524 #ifdef XP_WIN
michael@0 525 // Handle "? searchterm" for Windows Vista start menu integration
michael@0 526 for (var i = cmdLine.length - 1; i >= 0; --i) {
michael@0 527 var param = cmdLine.getArgument(i);
michael@0 528 if (param.match(/^\? /)) {
michael@0 529 cmdLine.removeArguments(i, i);
michael@0 530 cmdLine.preventDefault = true;
michael@0 531
michael@0 532 searchParam = param.substr(2);
michael@0 533 doSearch(searchParam, cmdLine);
michael@0 534 }
michael@0 535 }
michael@0 536 #endif
michael@0 537 },
michael@0 538
michael@0 539 helpInfo : " -browser Open a browser window.\n" +
michael@0 540 " -new-window <url> Open <url> in a new window.\n" +
michael@0 541 " -new-tab <url> Open <url> in a new tab.\n" +
michael@0 542 #ifdef XP_WIN
michael@0 543 " -preferences Open Options dialog.\n" +
michael@0 544 #else
michael@0 545 " -preferences Open Preferences dialog.\n" +
michael@0 546 #endif
michael@0 547 " -search <term> Search <term> with your default search engine.\n",
michael@0 548
michael@0 549 /* nsIBrowserHandler */
michael@0 550
michael@0 551 get defaultArgs() {
michael@0 552 var prefb = Components.classes["@mozilla.org/preferences-service;1"]
michael@0 553 .getService(nsIPrefBranch);
michael@0 554
michael@0 555 if (!gFirstWindow) {
michael@0 556 gFirstWindow = true;
michael@0 557 if (PrivateBrowsingUtils.isInTemporaryAutoStartMode) {
michael@0 558 return "about:privatebrowsing";
michael@0 559 }
michael@0 560 }
michael@0 561
michael@0 562 var overridePage = "";
michael@0 563 var willRestoreSession = false;
michael@0 564 try {
michael@0 565 // Read the old value of homepage_override.mstone before
michael@0 566 // needHomepageOverride updates it, so that we can later add it to the
michael@0 567 // URL if we do end up showing an overridePage. This makes it possible
michael@0 568 // to have the overridePage's content vary depending on the version we're
michael@0 569 // upgrading from.
michael@0 570 let old_mstone = "unknown";
michael@0 571 try {
michael@0 572 old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
michael@0 573 } catch (ex) {}
michael@0 574 let override = needHomepageOverride(prefb);
michael@0 575 if (override != OVERRIDE_NONE) {
michael@0 576 switch (override) {
michael@0 577 case OVERRIDE_NEW_PROFILE:
michael@0 578 // New profile.
michael@0 579 overridePage = Services.urlFormatter.formatURLPref("startup.homepage_welcome_url");
michael@0 580 break;
michael@0 581 case OVERRIDE_NEW_MSTONE:
michael@0 582 // Check whether we will restore a session. If we will, we assume
michael@0 583 // that this is an "update" session. This does not take crashes
michael@0 584 // into account because that requires waiting for the session file
michael@0 585 // to be read. If a crash occurs after updating, before restarting,
michael@0 586 // we may open the startPage in addition to restoring the session.
michael@0 587 var ss = Components.classes["@mozilla.org/browser/sessionstartup;1"]
michael@0 588 .getService(Components.interfaces.nsISessionStartup);
michael@0 589 willRestoreSession = ss.isAutomaticRestoreEnabled();
michael@0 590
michael@0 591 overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
michael@0 592 if (prefb.prefHasUserValue("app.update.postupdate"))
michael@0 593 overridePage = getPostUpdateOverridePage(overridePage);
michael@0 594
michael@0 595 overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
michael@0 596 break;
michael@0 597 }
michael@0 598 }
michael@0 599 } catch (ex) {}
michael@0 600
michael@0 601 // formatURLPref might return "about:blank" if getting the pref fails
michael@0 602 if (overridePage == "about:blank")
michael@0 603 overridePage = "";
michael@0 604
michael@0 605 var startPage = "";
michael@0 606 try {
michael@0 607 var choice = prefb.getIntPref("browser.startup.page");
michael@0 608 if (choice == 1 || choice == 3)
michael@0 609 startPage = this.startPage;
michael@0 610 } catch (e) {
michael@0 611 Components.utils.reportError(e);
michael@0 612 }
michael@0 613
michael@0 614 if (startPage == "about:blank")
michael@0 615 startPage = "";
michael@0 616
michael@0 617 // Only show the startPage if we're not restoring an update session.
michael@0 618 if (overridePage && startPage && !willRestoreSession)
michael@0 619 return overridePage + "|" + startPage;
michael@0 620
michael@0 621 return overridePage || startPage || "about:blank";
michael@0 622 },
michael@0 623
michael@0 624 get startPage() {
michael@0 625 var uri = Services.prefs.getComplexValue("browser.startup.homepage",
michael@0 626 nsIPrefLocalizedString).data;
michael@0 627 if (!uri) {
michael@0 628 Services.prefs.clearUserPref("browser.startup.homepage");
michael@0 629 uri = Services.prefs.getComplexValue("browser.startup.homepage",
michael@0 630 nsIPrefLocalizedString).data;
michael@0 631 }
michael@0 632 return uri;
michael@0 633 },
michael@0 634
michael@0 635 mFeatures : null,
michael@0 636
michael@0 637 getFeatures : function bch_features(cmdLine) {
michael@0 638 if (this.mFeatures === null) {
michael@0 639 this.mFeatures = "";
michael@0 640
michael@0 641 try {
michael@0 642 var width = cmdLine.handleFlagWithParam("width", false);
michael@0 643 var height = cmdLine.handleFlagWithParam("height", false);
michael@0 644
michael@0 645 if (width)
michael@0 646 this.mFeatures += ",width=" + width;
michael@0 647 if (height)
michael@0 648 this.mFeatures += ",height=" + height;
michael@0 649 }
michael@0 650 catch (e) {
michael@0 651 }
michael@0 652
michael@0 653 // The global PB Service consumes this flag, so only eat it in per-window
michael@0 654 // PB builds.
michael@0 655 if (PrivateBrowsingUtils.isInTemporaryAutoStartMode) {
michael@0 656 this.mFeatures = ",private";
michael@0 657 }
michael@0 658 }
michael@0 659
michael@0 660 return this.mFeatures;
michael@0 661 },
michael@0 662
michael@0 663 /* nsIContentHandler */
michael@0 664
michael@0 665 handleContent : function bch_handleContent(contentType, context, request) {
michael@0 666 try {
michael@0 667 var webNavInfo = Components.classes["@mozilla.org/webnavigation-info;1"]
michael@0 668 .getService(nsIWebNavigationInfo);
michael@0 669 if (!webNavInfo.isTypeSupported(contentType, null)) {
michael@0 670 throw NS_ERROR_WONT_HANDLE_CONTENT;
michael@0 671 }
michael@0 672 } catch (e) {
michael@0 673 throw NS_ERROR_WONT_HANDLE_CONTENT;
michael@0 674 }
michael@0 675
michael@0 676 request.QueryInterface(nsIChannel);
michael@0 677 handURIToExistingBrowser(request.URI,
michael@0 678 nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null);
michael@0 679 request.cancel(NS_BINDING_ABORTED);
michael@0 680 },
michael@0 681
michael@0 682 /* nsICommandLineValidator */
michael@0 683 validate : function bch_validate(cmdLine) {
michael@0 684 // Other handlers may use osint so only handle the osint flag if the url
michael@0 685 // flag is also present and the command line is valid.
michael@0 686 var osintFlagIdx = cmdLine.findFlag("osint", false);
michael@0 687 var urlFlagIdx = cmdLine.findFlag("url", false);
michael@0 688 if (urlFlagIdx > -1 && (osintFlagIdx > -1 ||
michael@0 689 cmdLine.state == nsICommandLine.STATE_REMOTE_EXPLICIT)) {
michael@0 690 var urlParam = cmdLine.getArgument(urlFlagIdx + 1);
michael@0 691 if (cmdLine.length != urlFlagIdx + 2 || /firefoxurl:/.test(urlParam))
michael@0 692 throw NS_ERROR_ABORT;
michael@0 693 cmdLine.handleFlag("osint", false)
michael@0 694 }
michael@0 695 },
michael@0 696 };
michael@0 697 var gBrowserContentHandler = new nsBrowserContentHandler();
michael@0 698
michael@0 699 function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate)
michael@0 700 {
michael@0 701 if (!shouldLoadURI(uri))
michael@0 702 return;
michael@0 703
michael@0 704 // Unless using a private window is forced, open external links in private
michael@0 705 // windows only if we're in perma-private mode.
michael@0 706 var allowPrivate = forcePrivate || PrivateBrowsingUtils.permanentPrivateBrowsing;
michael@0 707 var navWin = RecentWindow.getMostRecentBrowserWindow({private: allowPrivate});
michael@0 708 if (!navWin) {
michael@0 709 // if we couldn't load it in an existing window, open a new one
michael@0 710 var features = "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine);
michael@0 711 if (forcePrivate) {
michael@0 712 features += ",private";
michael@0 713 }
michael@0 714 openWindow(null, gBrowserContentHandler.chromeURL, "_blank", features, uri.spec);
michael@0 715 return;
michael@0 716 }
michael@0 717
michael@0 718 var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
michael@0 719 .getInterface(nsIWebNavigation);
michael@0 720 var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
michael@0 721 var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
michael@0 722 .getInterface(nsIDOMWindow);
michael@0 723 var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
michael@0 724 bwin.openURI(uri, null, location,
michael@0 725 nsIBrowserDOMWindow.OPEN_EXTERNAL);
michael@0 726 }
michael@0 727
michael@0 728 function nsDefaultCommandLineHandler() {
michael@0 729 }
michael@0 730
michael@0 731 nsDefaultCommandLineHandler.prototype = {
michael@0 732 classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"),
michael@0 733
michael@0 734 /* nsISupports */
michael@0 735 QueryInterface : function dch_QI(iid) {
michael@0 736 if (!iid.equals(nsISupports) &&
michael@0 737 !iid.equals(nsICommandLineHandler))
michael@0 738 throw Components.results.NS_ERROR_NO_INTERFACE;
michael@0 739
michael@0 740 return this;
michael@0 741 },
michael@0 742
michael@0 743 #ifdef XP_WIN
michael@0 744 _haveProfile: false,
michael@0 745 #endif
michael@0 746
michael@0 747 /* nsICommandLineHandler */
michael@0 748 handle : function dch_handle(cmdLine) {
michael@0 749 var urilist = [];
michael@0 750
michael@0 751 #ifdef XP_WIN
michael@0 752 // If we don't have a profile selected yet (e.g. the Profile Manager is
michael@0 753 // displayed) we will crash if we open an url and then select a profile. To
michael@0 754 // prevent this handle all url command line flags and set the command line's
michael@0 755 // preventDefault to true to prevent the display of the ui. The initial
michael@0 756 // command line will be retained when nsAppRunner calls LaunchChild though
michael@0 757 // urls launched after the initial launch will be lost.
michael@0 758 if (!this._haveProfile) {
michael@0 759 try {
michael@0 760 // This will throw when a profile has not been selected.
michael@0 761 var fl = Components.classes["@mozilla.org/file/directory_service;1"]
michael@0 762 .getService(Components.interfaces.nsIProperties);
michael@0 763 var dir = fl.get("ProfD", Components.interfaces.nsILocalFile);
michael@0 764 this._haveProfile = true;
michael@0 765 }
michael@0 766 catch (e) {
michael@0 767 while ((ar = cmdLine.handleFlagWithParam("url", false))) { }
michael@0 768 cmdLine.preventDefault = true;
michael@0 769 }
michael@0 770 }
michael@0 771 #endif
michael@0 772
michael@0 773 try {
michael@0 774 var ar;
michael@0 775 while ((ar = cmdLine.handleFlagWithParam("url", false))) {
michael@0 776 var uri = resolveURIInternal(cmdLine, ar);
michael@0 777 urilist.push(uri);
michael@0 778 }
michael@0 779 }
michael@0 780 catch (e) {
michael@0 781 Components.utils.reportError(e);
michael@0 782 }
michael@0 783
michael@0 784 count = cmdLine.length;
michael@0 785
michael@0 786 for (i = 0; i < count; ++i) {
michael@0 787 var curarg = cmdLine.getArgument(i);
michael@0 788 if (curarg.match(/^-/)) {
michael@0 789 Components.utils.reportError("Warning: unrecognized command line flag " + curarg + "\n");
michael@0 790 // To emulate the pre-nsICommandLine behavior, we ignore
michael@0 791 // the argument after an unrecognized flag.
michael@0 792 ++i;
michael@0 793 } else {
michael@0 794 try {
michael@0 795 urilist.push(resolveURIInternal(cmdLine, curarg));
michael@0 796 }
michael@0 797 catch (e) {
michael@0 798 Components.utils.reportError("Error opening URI '" + curarg + "' from the command line: " + e + "\n");
michael@0 799 }
michael@0 800 }
michael@0 801 }
michael@0 802
michael@0 803 if (urilist.length) {
michael@0 804 if (cmdLine.state != nsICommandLine.STATE_INITIAL_LAUNCH &&
michael@0 805 urilist.length == 1) {
michael@0 806 // Try to find an existing window and load our URI into the
michael@0 807 // current tab, new tab, or new window as prefs determine.
michael@0 808 try {
michael@0 809 handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine);
michael@0 810 return;
michael@0 811 }
michael@0 812 catch (e) {
michael@0 813 }
michael@0 814 }
michael@0 815
michael@0 816 var URLlist = urilist.filter(shouldLoadURI).map(function (u) u.spec);
michael@0 817 if (URLlist.length) {
michael@0 818 openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
michael@0 819 "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine),
michael@0 820 URLlist);
michael@0 821 }
michael@0 822
michael@0 823 }
michael@0 824 else if (!cmdLine.preventDefault) {
michael@0 825 // Passing defaultArgs, so use NO_EXTERNAL_URIS
michael@0 826 openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
michael@0 827 "chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine),
michael@0 828 gBrowserContentHandler.defaultArgs, NO_EXTERNAL_URIS);
michael@0 829 }
michael@0 830 },
michael@0 831
michael@0 832 helpInfo : "",
michael@0 833 };
michael@0 834
michael@0 835 var components = [nsBrowserContentHandler, nsDefaultCommandLineHandler];
michael@0 836 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

mercurial