browser.js
Go to the documentation of this file.
1 # -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 # ***** BEGIN LICENSE BLOCK *****
3 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 #
5 # The contents of this file are subject to the Mozilla Public License Version
6 # 1.1 (the "License"); you may not use this file except in compliance with
7 # the License. You may obtain a copy of the License at
8 # http://www.mozilla.org/MPL/
9 #
10 # Software distributed under the License is distributed on an "AS IS" basis,
11 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 # for the specific language governing rights and limitations under the
13 # License.
14 #
15 # The Original Code is mozilla.org code.
16 #
17 # The Initial Developer of the Original Code is
18 # Netscape Communications Corporation.
19 # Portions created by the Initial Developer are Copyright (C) 1998
20 # the Initial Developer. All Rights Reserved.
21 #
22 # Contributor(s):
23 # Blake Ross <blake@cs.stanford.edu>
24 # David Hyatt <hyatt@mozilla.org>
25 # Peter Annema <disttsc@bart.nl>
26 # Dean Tessman <dean_tessman@hotmail.com>
27 # Kevin Puetz <puetzk@iastate.edu>
28 # Ben Goodger <ben@netscape.com>
29 # Pierre Chanial <chanial@noos.fr>
30 # Jason Eager <jce2@po.cwru.edu>
31 # Joe Hewitt <hewitt@netscape.com>
32 # Alec Flett <alecf@netscape.com>
33 # Asaf Romano <mozilla.mano@sent.com>
34 # Jason Barnabe <jason_barnabe@fastmail.fm>
35 # Peter Parente <parente@cs.unc.edu>
36 # Giorgio Maone <g.maone@informaction.com>
37 # Tom Germeau <tom.germeau@epigoon.com>
38 # Jesse Ruderman <jruderman@gmail.com>
39 # Joe Hughes <joe@retrovirus.com>
40 # Pamela Greene <pamg.bugs@gmail.com>
41 # Michael Ventnor <m.ventnor@gmail.com>
42 # Simon Bünzli <zeniko@gmail.com>
43 # Johnathan Nightingale <johnath@mozilla.com>
44 # Ehsan Akhgari <ehsan.akhgari@gmail.com>
45 # Dão Gottwald <dao@mozilla.com>
46 # Thomas K. Dyas <tdyas@zecador.org>
47 # Edward Lee <edward.lee@engineering.uiuc.edu>
48 # Paul O’Shannessy <paul@oshannessy.com>
49 # Nils Maier <maierman@web.de>
50 # Rob Arnold <robarnold@cmu.edu>
51 # Dietrich Ayala <dietrich@mozilla.com>
52 #
53 # Alternatively, the contents of this file may be used under the terms of
54 # either the GNU General Public License Version 2 or later (the "GPL"), or
55 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
56 # in which case the provisions of the GPL or the LGPL are applicable instead
57 # of those above. If you wish to allow use of your version of this file only
58 # under the terms of either the GPL or the LGPL, and not to allow others to
59 # use your version of this file under the terms of the MPL, indicate your
60 # decision by deleting the provisions above and replace them with the notice
61 # and other provisions required by the GPL or the LGPL. If you do not delete
62 # the provisions above, a recipient may use your version of this file under
63 # the terms of any one of the MPL, the GPL or the LGPL.
64 #
65 # ***** END LICENSE BLOCK *****
66 
67 let Ci = Components.interfaces;
68 let Cu = Components.utils;
69 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
70 
71 const nsIWebNavigation = Ci.nsIWebNavigation;
72 
79 var gSidebarCommand = "";
80 var gInPrintPreviewMode = false;
82 
83 // Global variable that holds the nsContextMenu instance.
85 
86 var gChromeState = null; // chrome state before we went into print preview
87 
90 
91 #ifndef XP_MACOSX
92 var gEditUIVisible = true;
93 #endif
94 
95 [
96  ["gBrowser", "content"],
97  ["gNavToolbox", "navigator-toolbox"],
98  ["gURLBar", "urlbar"],
99  ["gNavigatorBundle", "bundle_browser"],
100  ["gProgressMeterPanel", "statusbar-progresspanel"],
101  ["gFindBar", "FindToolbar"]
102 ].forEach(function (elementGlobal) {
103  var [name, id] = elementGlobal;
104  window.__defineGetter__(name, function () {
105  var element = document.getElementById(id);
106  if (!element)
107  return null;
108  delete window[name];
109  return window[name] = element;
110  });
111  window.__defineSetter__(name, function (val) {
112  delete window[name];
113  return window[name] = val;
114  });
115 });
116 
117 __defineGetter__("gPrefService", function() {
118  delete this.gPrefService;
119  return this.gPrefService = Cc["@mozilla.org/preferences-service;1"]
120  .getService(Ci.nsIPrefBranch2)
121  .QueryInterface(Ci.nsIPrefService);
122 });
123 
124 __defineGetter__("PluralForm", function() {
125  Cu.import("resource://gre/modules/PluralForm.jsm");
126  return this.PluralForm;
127 });
128 __defineSetter__("PluralForm", function (val) {
129  delete this.PluralForm;
130  return this.PluralForm = val;
131 });
132 
133 #ifdef MOZ_CRASHREPORTER
134 __defineGetter__("gCrashReporter", function() {
135  delete this.gCrashReporter;
136  return this.gCrashReporter = Cc["@mozilla.org/xre/app-info;1"].
137  getService(Ci.nsICrashReporter);
138 });
139 #endif
140 
142  "about:blank",
143  "about:privatebrowsing",
144  "about:sessionrestore"
145 ];
146 
152  // Filter out events that are not about the document load we are interested in
153  if (event.originalTarget == content.document) {
155  XULBrowserWindow.asyncUpdateUI();
156  }
157 }
158 
164 {
165  var saveFrameItem = document.getElementById("menu_saveFrame");
166  if (!content || !content.frames.length || !isContentFrame(document.commandDispatcher.focusedWindow))
167  saveFrameItem.setAttribute("hidden", "true");
168  else
169  saveFrameItem.removeAttribute("hidden");
170 }
171 
172 function UpdateBackForwardCommands(aWebNavigation) {
173  var backBroadcaster = document.getElementById("Browser:Back");
174  var forwardBroadcaster = document.getElementById("Browser:Forward");
175 
176  // Avoid setting attributes on broadcasters if the value hasn't changed!
177  // Remember, guys, setting attributes on elements is expensive! They
178  // get inherited into anonymous content, broadcast to other widgets, etc.!
179  // Don't do it if the value hasn't changed! - dwh
180 
181  var backDisabled = backBroadcaster.hasAttribute("disabled");
182  var forwardDisabled = forwardBroadcaster.hasAttribute("disabled");
183  if (backDisabled == aWebNavigation.canGoBack) {
184  if (backDisabled)
185  backBroadcaster.removeAttribute("disabled");
186  else
187  backBroadcaster.setAttribute("disabled", true);
188  }
189 
190  if (forwardDisabled == aWebNavigation.canGoForward) {
191  if (forwardDisabled)
192  forwardBroadcaster.removeAttribute("disabled");
193  else
194  forwardBroadcaster.setAttribute("disabled", true);
195  }
196 }
197 
198 #ifdef XP_MACOSX
199 
203 function SetClickAndHoldHandlers() {
204  var timer;
205 
206  function timerCallback(aButton) {
207  aButton.firstChild.hidden = false;
208  aButton.open = true;
209  timer = null;
210  }
211 
212  function mousedownHandler(aEvent) {
213  if (aEvent.button != 0 ||
214  aEvent.currentTarget.open ||
215  aEvent.currentTarget.disabled)
216  return;
217 
218  // Prevent the menupopup from opening immediately
219  aEvent.currentTarget.firstChild.hidden = true;
220 
221  timer = setTimeout(timerCallback, 500, aEvent.currentTarget);
222  }
223 
224  function clickHandler(aEvent) {
225  if (aEvent.button == 0 &&
226  aEvent.target == aEvent.currentTarget &&
227  !aEvent.currentTarget.open &&
228  !aEvent.currentTarget.disabled) {
229  let cmdEvent = document.createEvent("xulcommandevent");
230  cmdEvent.initCommandEvent("command", true, true, window, 0,
231  aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
232  aEvent.metaKey, null);
233  aEvent.currentTarget.dispatchEvent(cmdEvent);
234  }
235  }
236 
237  function stopTimer(aEvent) {
238  if (timer) {
239  clearTimeout(timer);
240  timer = null;
241  }
242  }
243 
244  function _addClickAndHoldListenersOnElement(aElm) {
245  aElm.addEventListener("mousedown", mousedownHandler, true);
246  aElm.addEventListener("mouseup", stopTimer, false);
247  aElm.addEventListener("mouseout", stopTimer, false);
248  aElm.addEventListener("click", clickHandler, true);
249  }
250 
251  // Bug 414797: Clone the dropmarker's menu into both the back and
252  // the forward buttons.
253  var unifiedButton = document.getElementById("unified-back-forward-button");
254  if (unifiedButton && !unifiedButton._clickHandlersAttached) {
255  var popup = document.getElementById("back-forward-dropmarker")
256  .firstChild.cloneNode(true);
257  var backButton = document.getElementById("back-button");
258  backButton.setAttribute("type", "menu");
259  backButton.appendChild(popup);
260  _addClickAndHoldListenersOnElement(backButton);
261  var forwardButton = document.getElementById("forward-button");
262  popup = popup.cloneNode(true);
263  forwardButton.setAttribute("type", "menu");
264  forwardButton.appendChild(popup);
265  _addClickAndHoldListenersOnElement(forwardButton);
266  unifiedButton._clickHandlersAttached = true;
267  }
268 }
269 #endif
270 
271 function BookmarkThisTab() {
272  PlacesCommandHook.bookmarkPage(gBrowser.mContextTab.linkedBrowser,
273  PlacesUtils.bookmarksMenuFolderId, true);
274 }
275 
277  observe: function(subject, topic, data)
278  {
279  if (topic != "browser:purge-session-history")
280  return;
281 
282  var backCommand = document.getElementById("Browser:Back");
283  backCommand.setAttribute("disabled", "true");
284  var fwdCommand = document.getElementById("Browser:Forward");
285  fwdCommand.setAttribute("disabled", "true");
286 
287  if (gURLBar) {
288  // Clear undo history of the URL bar
289  gURLBar.editor.transactionManager.clear()
290  }
291  }
292 };
293 
306 function findChildShell(aDocument, aDocShell, aSoughtURI) {
307  aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation);
308  aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
309  var doc = aDocShell.getInterface(Components.interfaces.nsIDOMDocument);
310  if ((aDocument && doc == aDocument) ||
311  (aSoughtURI && aSoughtURI.spec == aDocShell.currentURI.spec))
312  return aDocShell;
313 
314  var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
315  for (var i = 0; i < node.childCount; ++i) {
316  var docShell = node.getChildAt(i);
317  docShell = findChildShell(aDocument, docShell, aSoughtURI);
318  if (docShell)
319  return docShell;
320  }
321  return null;
322 }
323 
325  _reportButton: null,
326  _kIPM: Components.interfaces.nsIPermissionManager,
327 
328  onUpdatePageReport: function (aEvent)
329  {
330  if (aEvent.originalTarget != gBrowser.selectedBrowser)
331  return;
332 
333  if (!this._reportButton)
334  this._reportButton = document.getElementById("page-report-button");
335 
336  if (!gBrowser.pageReport) {
337  // Hide the popup blocker statusbar button
338  this._reportButton.hidden = true;
339 
340  return;
341  }
342 
343  this._reportButton.hidden = false;
344 
345  // Only show the notification again if we've not already shown it. Since
346  // notifications are per-browser, we don't need to worry about re-adding
347  // it.
348  if (!gBrowser.pageReport.reported) {
349  if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage")) {
350  var brandBundle = document.getElementById("bundle_brand");
351  var brandShortName = brandBundle.getString("brandShortName");
352  var message;
353  var popupCount = gBrowser.pageReport.length;
354 #ifdef XP_WIN
355  var popupButtonText = gNavigatorBundle.getString("popupWarningButton");
356  var popupButtonAccesskey = gNavigatorBundle.getString("popupWarningButton.accesskey");
357 #else
358  var popupButtonText = gNavigatorBundle.getString("popupWarningButtonUnix");
359  var popupButtonAccesskey = gNavigatorBundle.getString("popupWarningButtonUnix.accesskey");
360 #endif
361  if (popupCount > 1)
362  message = gNavigatorBundle.getFormattedString("popupWarningMultiple", [brandShortName, popupCount]);
363  else
364  message = gNavigatorBundle.getFormattedString("popupWarning", [brandShortName]);
365 
366  var notificationBox = gBrowser.getNotificationBox();
367  var notification = notificationBox.getNotificationWithValue("popup-blocked");
368  if (notification) {
369  notification.label = message;
370  }
371  else {
372  var buttons = [{
373  label: popupButtonText,
374  accessKey: popupButtonAccesskey,
375  popup: "blockedPopupOptions",
376  callback: null
377  }];
378 
379  const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
380  notificationBox.appendNotification(message, "popup-blocked",
381  "chrome://browser/skin/Info.png",
382  priority, buttons);
383  }
384  }
385 
386  // Record the fact that we've reported this blocked popup, so we don't
387  // show it again.
388  gBrowser.pageReport.reported = true;
389  }
390  },
391 
392  toggleAllowPopupsForSite: function (aEvent)
393  {
394  var currentURI = gBrowser.selectedBrowser.webNavigation.currentURI;
395  var pm = Components.classes["@mozilla.org/permissionmanager;1"]
396  .getService(this._kIPM);
397  var shouldBlock = aEvent.target.getAttribute("block") == "true";
398  var perm = shouldBlock ? this._kIPM.DENY_ACTION : this._kIPM.ALLOW_ACTION;
399  pm.add(currentURI, "popup", perm);
400 
401  gBrowser.getNotificationBox().removeCurrentNotification();
402  },
403 
404  fillPopupList: function (aEvent)
405  {
406  // XXXben - rather than using |currentURI| here, which breaks down on multi-framed sites
407  // we should really walk the pageReport and create a list of "allow for <host>"
408  // menuitems for the common subset of hosts present in the report, this will
409  // make us frame-safe.
410  //
411  // XXXjst - Note that when this is fixed to work with multi-framed sites,
412  // also back out the fix for bug 343772 where
413  // nsGlobalWindow::CheckOpenAllow() was changed to also
414  // check if the top window's location is whitelisted.
415  var uri = gBrowser.selectedBrowser.webNavigation.currentURI;
416  var blockedPopupAllowSite = document.getElementById("blockedPopupAllowSite");
417  try {
418  blockedPopupAllowSite.removeAttribute("hidden");
419 
420  var pm = Cc["@mozilla.org/permissionmanager;1"].getService(this._kIPM);
421  if (pm.testPermission(uri, "popup") == this._kIPM.ALLOW_ACTION) {
422  // Offer an item to block popups for this site, if a whitelist entry exists
423  // already for it.
424  let blockString = gNavigatorBundle.getFormattedString("popupBlock", [uri.host]);
425  blockedPopupAllowSite.setAttribute("label", blockString);
426  blockedPopupAllowSite.setAttribute("block", "true");
427  }
428  else {
429  // Offer an item to allow popups for this site
430  let allowString = gNavigatorBundle.getFormattedString("popupAllow", [uri.host]);
431  blockedPopupAllowSite.setAttribute("label", allowString);
432  blockedPopupAllowSite.removeAttribute("block");
433  }
434  }
435  catch (e) {
436  blockedPopupAllowSite.setAttribute("hidden", "true");
437  }
438 
439  if (gPrivateBrowsingUI.privateBrowsingEnabled)
440  blockedPopupAllowSite.setAttribute("disabled", "true");
441 
442  var item = aEvent.target.lastChild;
443  while (item && item.getAttribute("observes") != "blockedPopupsSeparator") {
444  var next = item.previousSibling;
445  item.parentNode.removeChild(item);
446  item = next;
447  }
448 
449  var foundUsablePopupURI = false;
450  var pageReport = gBrowser.pageReport;
451  if (pageReport) {
452  for (var i = 0; i < pageReport.length; ++i) {
453  var popupURIspec = pageReport[i].popupWindowURI.spec;
454 
455  // Sometimes the popup URI that we get back from the pageReport
456  // isn't useful (for instance, netscape.com's popup URI ends up
457  // being "http://www.netscape.com", which isn't really the URI of
458  // the popup they're trying to show). This isn't going to be
459  // useful to the user, so we won't create a menu item for it.
460  if (popupURIspec == "" || popupURIspec == "about:blank" ||
461  popupURIspec == uri.spec)
462  continue;
463 
464  // Because of the short-circuit above, we may end up in a situation
465  // in which we don't have any usable popup addresses to show in
466  // the menu, and therefore we shouldn't show the separator. However,
467  // since we got past the short-circuit, we must've found at least
468  // one usable popup URI and thus we'll turn on the separator later.
469  foundUsablePopupURI = true;
470 
471  var menuitem = document.createElement("menuitem");
472  var label = gNavigatorBundle.getFormattedString("popupShowPopupPrefix",
473  [popupURIspec]);
474  menuitem.setAttribute("label", label);
475  menuitem.setAttribute("popupWindowURI", popupURIspec);
476  menuitem.setAttribute("popupWindowFeatures", pageReport[i].popupWindowFeatures);
477  menuitem.setAttribute("popupWindowName", pageReport[i].popupWindowName);
478  menuitem.setAttribute("oncommand", "gPopupBlockerObserver.showBlockedPopup(event);");
479  menuitem.requestingWindow = pageReport[i].requestingWindow;
480  menuitem.requestingDocument = pageReport[i].requestingDocument;
481  aEvent.target.appendChild(menuitem);
482  }
483  }
484 
485  // Show or hide the separator, depending on whether we added any
486  // showable popup addresses to the menu.
487  var blockedPopupsSeparator =
488  document.getElementById("blockedPopupsSeparator");
489  if (foundUsablePopupURI)
490  blockedPopupsSeparator.removeAttribute("hidden");
491  else
492  blockedPopupsSeparator.setAttribute("hidden", true);
493 
494  var blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage");
495  var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
496  blockedPopupDontShowMessage.setAttribute("checked", !showMessage);
497  if (aEvent.target.localName == "popup")
498  blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromMessage"));
499  else
500  blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromStatusbar"));
501  },
502 
503  showBlockedPopup: function (aEvent)
504  {
505  var target = aEvent.target;
506  var popupWindowURI = target.getAttribute("popupWindowURI");
507  var features = target.getAttribute("popupWindowFeatures");
508  var name = target.getAttribute("popupWindowName");
509 
510  var dwi = target.requestingWindow;
511 
512  // If we have a requesting window and the requesting document is
513  // still the current document, open the popup.
514  if (dwi && dwi.document == target.requestingDocument) {
515  dwi.open(popupWindowURI, name, features);
516  }
517  },
518 
519  editPopupSettings: function ()
520  {
521  var host = "";
522  try {
523  var uri = gBrowser.selectedBrowser.webNavigation.currentURI;
524  host = uri.host;
525  }
526  catch (e) { }
527 
528  var bundlePreferences = document.getElementById("bundle_preferences");
529  var params = { blockVisible : false,
530  sessionVisible : false,
531  allowVisible : true,
532  prefilledHost : host,
533  permissionType : "popup",
534  windowTitle : bundlePreferences.getString("popuppermissionstitle"),
535  introText : bundlePreferences.getString("popuppermissionstext") };
536  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
537  .getService(Components.interfaces.nsIWindowMediator);
538  var existingWindow = wm.getMostRecentWindow("Browser:Permissions");
539  if (existingWindow) {
540  existingWindow.initWithParams(params);
541  existingWindow.focus();
542  }
543  else
544  window.openDialog("chrome://browser/content/preferences/permissions.xul",
545  "_blank", "resizable,dialog=no,centerscreen", params);
546  },
547 
548  dontShowMessage: function ()
549  {
550  var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
551  var firstTime = gPrefService.getBoolPref("privacy.popups.firstTime");
552 
553  // If the info message is showing at the top of the window, and the user has never
554  // hidden the message before, show an info box telling the user where the info
555  // will be displayed.
556  if (showMessage && firstTime)
557  this._displayPageReportFirstTime();
558 
559  gPrefService.setBoolPref("privacy.popups.showBrowserMessage", !showMessage);
560 
561  gBrowser.getNotificationBox().removeCurrentNotification();
562  },
563 
564  _displayPageReportFirstTime: function ()
565  {
566  window.openDialog("chrome://browser/content/pageReportFirstTime.xul", "_blank",
567  "dependent");
568  }
569 };
570 
572  _findChildShell: function (aDocShell, aSoughtShell)
573  {
574  if (aDocShell == aSoughtShell)
575  return aDocShell;
576 
577  var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
578  for (var i = 0; i < node.childCount; ++i) {
579  var docShell = node.getChildAt(i);
580  docShell = this._findChildShell(docShell, aSoughtShell);
581  if (docShell == aSoughtShell)
582  return docShell;
583  }
584  return null;
585  },
586 
587  _getBrowser: function (aDocShell)
588  {
589  for (var i = 0; i < gBrowser.browsers.length; ++i) {
590  var browser = gBrowser.getBrowserAtIndex(i);
591  if (this._findChildShell(browser.docShell, aDocShell))
592  return browser;
593  }
594  return null;
595  },
596 
597  observe: function (aSubject, aTopic, aData)
598  {
599  var brandBundle = document.getElementById("bundle_brand");
600  switch (aTopic) {
601  case "xpinstall-install-blocked":
602  var installInfo = aSubject.QueryInterface(Components.interfaces.nsIXPIInstallInfo);
603  var win = installInfo.originatingWindow;
604  var shell = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
605  .getInterface(Components.interfaces.nsIWebNavigation)
606  .QueryInterface(Components.interfaces.nsIDocShell);
607  var browser = this._getBrowser(shell);
608  if (browser) {
609  var host = installInfo.originatingURI.host;
610  var brandShortName = brandBundle.getString("brandShortName");
611  var notificationName, messageString, buttons;
612  if (!gPrefService.getBoolPref("xpinstall.enabled")) {
613  notificationName = "xpinstall-disabled"
614  if (gPrefService.prefIsLocked("xpinstall.enabled")) {
615  messageString = gNavigatorBundle.getString("xpinstallDisabledMessageLocked");
616  buttons = [];
617  }
618  else {
619  messageString = gNavigatorBundle.getFormattedString("xpinstallDisabledMessage",
620  [brandShortName, host]);
621 
622  buttons = [{
623  label: gNavigatorBundle.getString("xpinstallDisabledButton"),
624  accessKey: gNavigatorBundle.getString("xpinstallDisabledButton.accesskey"),
625  popup: null,
626  callback: function editPrefs() {
627  gPrefService.setBoolPref("xpinstall.enabled", true);
628  return false;
629  }
630  }];
631  }
632  }
633  else {
634  notificationName = "xpinstall"
635  messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning",
636  [brandShortName, host]);
637 
638  buttons = [{
639  label: gNavigatorBundle.getString("xpinstallPromptAllowButton"),
640  accessKey: gNavigatorBundle.getString("xpinstallPromptAllowButton.accesskey"),
641  popup: null,
642  callback: function() {
643  var mgr = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
644  .createInstance(Components.interfaces.nsIXPInstallManager);
645  mgr.initManagerWithInstallInfo(installInfo);
646  return false;
647  }
648  }];
649  }
650 
651  var notificationBox = gBrowser.getNotificationBox(browser);
652  if (!notificationBox.getNotificationWithValue(notificationName)) {
653  const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
654  const iconURL = "chrome://mozapps/skin/update/update.png";
655  notificationBox.appendNotification(messageString, notificationName,
656  iconURL, priority, buttons);
657  }
658  }
659  break;
660  }
661  }
662 };
663 
664 // Simple gestures support
665 //
666 // As per bug #412486, web content must not be allowed to receive any
667 // simple gesture events. Multi-touch gesture APIs are in their
668 // infancy and we do NOT want to be forced into supporting an API that
669 // will probably have to change in the future. (The current Mac OS X
670 // API is undocumented and was reverse-engineered.) Until support is
671 // implemented in the event dispatcher to keep these events as
672 // chrome-only, we must listen for the simple gesture events during
673 // the capturing phase and call stopPropagation on every event.
674 
682  init: function GS_init(aAddListener) {
683  const gestureEvents = ["SwipeGesture",
684  "MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
685  "RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
686  "TapGesture", "PressTapGesture"];
687 
688  let addRemove = aAddListener ? window.addEventListener :
689  window.removeEventListener;
690 
691  gestureEvents.forEach(function (event) addRemove("Moz" + event, this, true),
692  this);
693  },
694 
703  handleEvent: function GS_handleEvent(aEvent) {
704  aEvent.stopPropagation();
705 
706  // Create a preference object with some defaults
707  let def = function(aThreshold, aLatched)
708  ({ threshold: aThreshold, latched: !!aLatched });
709 
710  switch (aEvent.type) {
711  case "MozSwipeGesture":
712  aEvent.preventDefault();
713  return this.onSwipe(aEvent);
714  case "MozMagnifyGestureStart":
715  aEvent.preventDefault();
716 #ifdef XP_WIN
717  return this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in");
718 #else
719  return this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in");
720 #endif
721  case "MozRotateGestureStart":
722  aEvent.preventDefault();
723  return this._setupGesture(aEvent, "twist", def(25, 0), "right", "left");
724  case "MozMagnifyGestureUpdate":
725  case "MozRotateGestureUpdate":
726  aEvent.preventDefault();
727  return this._doUpdate(aEvent);
728  case "MozTapGesture":
729  aEvent.preventDefault();
730  return this._doAction(aEvent, ["tap"]);
731  case "MozPressTapGesture":
732  // Fall through to default behavior
733  return;
734  }
735  },
736 
752  _setupGesture: function GS__setupGesture(aEvent, aGesture, aPref, aInc, aDec) {
753  // Try to load user-set values from preferences
754  for (let [pref, def] in Iterator(aPref))
755  aPref[pref] = this._getPref(aGesture + "." + pref, def);
756 
757  // Keep track of the total deltas and latching behavior
758  let offset = 0;
759  let latchDir = aEvent.delta > 0 ? 1 : -1;
760  let isLatched = false;
761 
762  // Create the update function here to capture closure state
763  this._doUpdate = function GS__doUpdate(aEvent) {
764  // Update the offset with new event data
765  offset += aEvent.delta;
766 
767  // Check if the cumulative deltas exceed the threshold
768  if (Math.abs(offset) > aPref["threshold"]) {
769  // Trigger the action if we don't care about latching; otherwise, make
770  // sure either we're not latched and going the same direction of the
771  // initial motion; or we're latched and going the opposite way
772  let sameDir = (latchDir ^ offset) >= 0;
773  if (!aPref["latched"] || (isLatched ^ sameDir)) {
774  this._doAction(aEvent, [aGesture, offset > 0 ? aInc : aDec]);
775 
776  // We must be getting latched or leaving it, so just toggle
777  isLatched = !isLatched;
778  }
779 
780  // Reset motion counter to prepare for more of the same gesture
781  offset = 0;
782  }
783  };
784 
785  // The start event also contains deltas, so handle an update right away
786  this._doUpdate(aEvent);
787  },
788 
797  _power: function GS__power(aArray) {
798  // Create a bitmask based on the length of the array
799  let num = 1 << aArray.length;
800  while (--num >= 0)
801  // Only select array elements where the current bit is set
802  yield aArray.reduce(function(aPrev, aCurr, aIndex) {
803  if (num & 1 << aIndex)
804  aPrev.push(aCurr);
805  return aPrev;
806  }, []);
807  },
808 
820  _doAction: function GS__doAction(aEvent, aGesture) {
821  // Create a fake event that pretends the gesture is a button click
822  let fakeEvent = { shiftKey: aEvent.shiftKey, ctrlKey: aEvent.ctrlKey,
823  metaKey: aEvent.metaKey, altKey: aEvent.altKey, button: 0 };
824 
825  // Create an array of pressed keys in a fixed order so that a command for
826  // "meta" is preferred over "ctrl" when both buttons are pressed (and a
827  // command for both don't exist)
828  let keyCombos = [];
829  const keys = ["shift", "alt", "ctrl", "meta"];
830  for each (let key in keys)
831  if (aEvent[key + "Key"])
832  keyCombos.push(key);
833 
834  try {
835  // Try each combination of key presses in decreasing order for commands
836  for (let subCombo in this._power(keyCombos)) {
837  // Convert a gesture and pressed keys into the corresponding command
838  // action where the preference has the gesture before "shift" before
839  // "alt" before "ctrl" before "meta" all separated by periods
840  let command = this._getPref(aGesture.concat(subCombo).join("."));
841 
842  // Do the command if we found one to do
843  if (command) {
844  let node = document.getElementById(command);
845  // Use the command element if it exists
846  if (node && node.hasAttribute("oncommand")) {
847  // XXX: Use node.oncommand(event) once bug 246720 is fixed
848  if (node.getAttribute("disabled") != "true")
849  new Function("event", node.getAttribute("oncommand")).
850  call(node, fakeEvent);
851  }
852  // Otherwise it should be a "standard" command
853  else
854  goDoCommand(command);
855 
856  return command;
857  }
858  }
859  }
860  // The generator ran out of key combinations, so just do nothing
861  catch (e) {}
862  },
863 
872  _doUpdate: function(aEvent) {},
873 
880  onSwipe: function GS_onSwipe(aEvent) {
881  // Figure out which one (and only one) direction was triggered
882  ["UP", "RIGHT", "DOWN", "LEFT"].forEach(function (dir) {
883  if (aEvent.direction == aEvent["DIRECTION_" + dir])
884  return this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
885  }, this);
886  },
887 
896  _getPref: function GS__getPref(aPref, aDef) {
897  // Preferences branch under which all gestures preferences are stored
898  const branch = "browser.gesture.";
899 
900  try {
901  // Determine what type of data to load based on default value's type
902  let type = typeof aDef;
903  let getFunc = "get" + (type == "boolean" ? "Bool" :
904  type == "number" ? "Int" : "Char") + "Pref";
905  return gPrefService[getFunc](branch + aPref);
906  }
907  catch (e) {
908  return aDef;
909  }
910  },
911 };
912 
913 function BrowserStartup() {
914  var uriToLoad = null;
915 
916  // window.arguments[0]: URI to load (string), or an nsISupportsArray of
917  // nsISupportsStrings to load, or a xul:tab of
918  // a tabbrowser, which will be replaced by this
919  // window (for this case, all other arguments are
920  // ignored).
921  // [1]: character set (string)
922  // [2]: referrer (nsIURI)
923  // [3]: postData (nsIInputStream)
924  // [4]: allowThirdPartyFixup (bool)
925  if ("arguments" in window && window.arguments[0])
926  uriToLoad = window.arguments[0];
927 
928  var isLoadingBlank = uriToLoad == "about:blank";
929  var mustLoadSidebar = false;
930 
932 
933  if (uriToLoad && !isLoadingBlank) {
934  if (uriToLoad instanceof Ci.nsISupportsArray) {
935  let count = uriToLoad.Count();
936  let specs = [];
937  for (let i = 0; i < count; i++) {
938  let urisstring = uriToLoad.GetElementAt(i).QueryInterface(Ci.nsISupportsString);
939  specs.push(urisstring.data);
940  }
941 
942  // This function throws for certain malformed URIs, so use exception handling
943  // so that we don't disrupt startup
944  try {
945  gBrowser.loadTabs(specs, false, true);
946  } catch (e) {}
947  }
948  else if (uriToLoad instanceof XULElement) {
949  // swap the given tab with the default about:blank tab and then close
950  // the original tab in the other window.
951 
952  // Stop the about:blank load
953  gBrowser.selectedBrowser.stop();
954  // make sure it has a docshell
955  gBrowser.selectedBrowser.docShell;
956 
957  gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad);
958  }
959  else if (window.arguments.length >= 3) {
960  loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
961  window.arguments[4] || false);
962  content.focus();
963  }
964  // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
965  // Such callers expect that window.arguments[0] is handled as a single URI.
966  else
967  loadOneOrMoreURIs(uriToLoad);
968  }
969 
970  if (window.opener && !window.opener.closed) {
971  let openerFindBar = window.opener.gFindBar;
972  if (openerFindBar && !openerFindBar.hidden &&
973  openerFindBar.findMode == gFindBar.FIND_NORMAL)
974  gFindBar.open();
975 
976  let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
977  // If the opener had a sidebar, open the same sidebar in our window.
978  // The opener can be the hidden window too, if we're coming from the state
979  // where no windows are open, and the hidden window has no sidebar box.
980  if (openerSidebarBox && !openerSidebarBox.hidden) {
981  let sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand");
982  let sidebarCmdElem = document.getElementById(sidebarCmd);
983 
984  // dynamically generated sidebars will fail this check.
985  if (sidebarCmdElem) {
986  let sidebarBox = document.getElementById("sidebar-box");
987  let sidebarTitle = document.getElementById("sidebar-title");
988 
989  sidebarTitle.setAttribute(
990  "value", window.opener.document.getElementById("sidebar-title").getAttribute("value"));
991  sidebarBox.setAttribute("width", openerSidebarBox.boxObject.width);
992 
993  sidebarBox.setAttribute("sidebarcommand", sidebarCmd);
994  // Note: we're setting 'src' on sidebarBox, which is a <vbox>, not on
995  // the <browser id="sidebar">. This lets us delay the actual load until
996  // delayedStartup().
997  sidebarBox.setAttribute(
998  "src", window.opener.document.getElementById("sidebar").getAttribute("src"));
999  mustLoadSidebar = true;
1000 
1001  sidebarBox.hidden = false;
1002  document.getElementById("sidebar-splitter").hidden = false;
1003  sidebarCmdElem.setAttribute("checked", "true");
1004  }
1005  }
1006  }
1007  else {
1008  let box = document.getElementById("sidebar-box");
1009  if (box.hasAttribute("sidebarcommand")) {
1010  let commandID = box.getAttribute("sidebarcommand");
1011  if (commandID) {
1012  let command = document.getElementById(commandID);
1013  if (command) {
1014  mustLoadSidebar = true;
1015  box.hidden = false;
1016  document.getElementById("sidebar-splitter").hidden = false;
1017  command.setAttribute("checked", "true");
1018  }
1019  else {
1020  // Remove the |sidebarcommand| attribute, because the element it
1021  // refers to no longer exists, so we should assume this sidebar
1022  // panel has been uninstalled. (249883)
1023  box.removeAttribute("sidebarcommand");
1024  }
1025  }
1026  }
1027  }
1028 
1029  // Certain kinds of automigration rely on this notification to complete their
1030  // tasks BEFORE the browser window is shown.
1031  Cc["@mozilla.org/observer-service;1"]
1032  .getService(Ci.nsIObserverService)
1033  .notifyObservers(null, "browser-window-before-show", "");
1034 
1035  // Set a sane starting width/height for all resolutions on new profiles.
1036  if (!document.documentElement.hasAttribute("width")) {
1037  let defaultWidth = 994;
1038  let defaultHeight;
1039  if (screen.availHeight <= 600) {
1040  document.documentElement.setAttribute("sizemode", "maximized");
1041  defaultWidth = 610;
1042  defaultHeight = 450;
1043  }
1044  else {
1045  // Create a narrower window for large or wide-aspect displays, to suggest
1046  // side-by-side page view.
1047  if (screen.availWidth >= 1600)
1048  defaultWidth = (screen.availWidth / 2) - 20;
1049  defaultHeight = screen.availHeight - 10;
1050 #ifdef MOZ_WIDGET_GTK2
1051  // On X, we're not currently able to account for the size of the window
1052  // border. Use 28px as a guess (titlebar + bottom window border)
1053  defaultHeight -= 28;
1054 #endif
1055  }
1056  document.documentElement.setAttribute("width", defaultWidth);
1057  document.documentElement.setAttribute("height", defaultHeight);
1058  }
1059 
1060  if (gURLBar &&
1061  document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
1062  gURLBar.setAttribute("readonly", "true");
1063  gURLBar.setAttribute("enablehistory", "false");
1064  }
1065 
1066  allTabs.readPref();
1067 
1068  setTimeout(delayedStartup, 0, isLoadingBlank, mustLoadSidebar);
1069 }
1070 
1071 function HandleAppCommandEvent(evt) {
1072  evt.stopPropagation();
1073  switch (evt.command) {
1074  case "Back":
1075  BrowserBack();
1076  break;
1077  case "Forward":
1078  BrowserForward();
1079  break;
1080  case "Reload":
1082  break;
1083  case "Stop":
1084  BrowserStop();
1085  break;
1086  case "Search":
1087  BrowserSearch.webSearch();
1088  break;
1089  case "Bookmarks":
1090  toggleSidebar('viewBookmarksSidebar');
1091  break;
1092  case "Home":
1093  BrowserHome();
1094  break;
1095  default:
1096  break;
1097  }
1098 }
1099 
1100 function prepareForStartup() {
1101  gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver.onUpdatePageReport, false);
1102  // Note: we need to listen to untrusted events, because the pluginfinder XBL
1103  // binding can't fire trusted ones (runs with page privileges).
1104  gBrowser.addEventListener("PluginNotFound", gMissingPluginInstaller.newMissingPlugin, true, true);
1105  gBrowser.addEventListener("PluginBlocklisted", gMissingPluginInstaller.newMissingPlugin, true, true);
1106  gBrowser.addEventListener("PluginOutdated", gMissingPluginInstaller.newMissingPlugin, true, true);
1107  gBrowser.addEventListener("PluginDisabled", gMissingPluginInstaller.newDisabledPlugin, true, true);
1108  gBrowser.addEventListener("NewPluginInstalled", gMissingPluginInstaller.refreshBrowser, false);
1109  gBrowser.addEventListener("NewTab", BrowserOpenTab, false);
1110  window.addEventListener("AppCommand", HandleAppCommandEvent, true);
1111 
1112  var webNavigation;
1113  try {
1114  webNavigation = getWebNavigation();
1115  if (!webNavigation)
1116  throw "no XBL binding for browser";
1117  } catch (e) {
1118  alert("Error launching browser window:" + e);
1119  window.close(); // Give up.
1120  return;
1121  }
1122 
1123  // initialize observers and listeners
1124  // and give C++ access to gBrowser
1125  XULBrowserWindow.init();
1126  window.QueryInterface(Ci.nsIInterfaceRequestor)
1127  .getInterface(nsIWebNavigation)
1128  .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
1129  .QueryInterface(Ci.nsIInterfaceRequestor)
1130  .getInterface(Ci.nsIXULWindow)
1131  .XULBrowserWindow = window.XULBrowserWindow;
1132  window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
1133  new nsBrowserAccess();
1134 
1135  // set default character set if provided
1136  if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
1137  if (window.arguments[1].indexOf("charset=") != -1) {
1138  var arrayArgComponents = window.arguments[1].split("=");
1139  if (arrayArgComponents) {
1140  //we should "inherit" the charset menu setting in a new window
1141  getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1];
1142  }
1143  }
1144  }
1145 
1146  // Manually hook up session and global history for the first browser
1147  // so that we don't have to load global history before bringing up a
1148  // window.
1149  // Wire up session and global history before any possible
1150  // progress notifications for back/forward button updating
1151  webNavigation.sessionHistory = Components.classes["@mozilla.org/browser/shistory;1"]
1152  .createInstance(Components.interfaces.nsISHistory);
1153  var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
1154  os.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false);
1155 
1156  // remove the disablehistory attribute so the browser cleans up, as
1157  // though it had done this work itself
1158  gBrowser.browsers[0].removeAttribute("disablehistory");
1159 
1160  // enable global history
1161  try {
1162  gBrowser.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = true;
1163  } catch(ex) {
1164  Components.utils.reportError("Places database may be locked: " + ex);
1165  }
1166 
1167  // hook up UI through progress listener
1168  gBrowser.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
1169  gBrowser.addTabsProgressListener(window.TabsProgressListener);
1170 
1171  // setup our common DOMLinkAdded listener
1172  gBrowser.addEventListener("DOMLinkAdded", DOMLinkHandler, false);
1173 
1174  // setup our MozApplicationManifest listener
1175  gBrowser.addEventListener("MozApplicationManifest",
1176  OfflineApps, false);
1177 
1178  // setup simple gestures support
1179  gGestureSupport.init(true);
1180 }
1181 
1182 function delayedStartup(isLoadingBlank, mustLoadSidebar) {
1183  var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
1184  os.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
1185  os.addObserver(gXPInstallObserver, "xpinstall-install-blocked", false);
1186 
1187  BrowserOffline.init();
1188  OfflineApps.init();
1189 
1190  gBrowser.addEventListener("pageshow", function(evt) { setTimeout(pageShowEventHandlers, 0, evt); }, true);
1191 
1192  // Ensure login manager is up and running.
1193  Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
1194 
1195  if (mustLoadSidebar) {
1196  let sidebar = document.getElementById("sidebar");
1197  let sidebarBox = document.getElementById("sidebar-box");
1198  sidebar.setAttribute("src", sidebarBox.getAttribute("src"));
1199  }
1200 
1202 
1203  PlacesStarButton.init();
1204 
1205  // called when we go into full screen, even if it is
1206  // initiated by a web page script
1207  window.addEventListener("fullscreen", onFullScreen, true);
1208 
1209  if (isLoadingBlank && gURLBar && isElementVisible(gURLBar))
1210  gURLBar.focus();
1211  else
1212  gBrowser.selectedBrowser.focus();
1213 
1214  if (gURLBar)
1215  gURLBar.emptyText = gURLBarEmptyText.value;
1216 
1217  gNavToolbox.customizeDone = BrowserToolboxCustomizeDone;
1218  gNavToolbox.customizeChange = BrowserToolboxCustomizeChange;
1219 
1220  // Set up Sanitize Item
1221  initializeSanitizer();
1222 
1223  // Enable/Disable auto-hide tabbar
1224  gAutoHideTabbarPrefListener = new AutoHideTabbarPrefListener();
1225  gPrefService.addObserver(gAutoHideTabbarPrefListener.domain,
1226  gAutoHideTabbarPrefListener, false);
1227 
1228  gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false);
1229 
1230  gPrefService.addObserver(gURLBarEmptyText.domain, gURLBarEmptyText, false);
1231 
1232  var homeButton = document.getElementById("home-button");
1233  gHomeButton.updateTooltip(homeButton);
1234  gHomeButton.updatePersonalToolbarStyle(homeButton);
1235 
1236 #ifdef HAVE_SHELL_SERVICE
1237  // Perform default browser checking (after window opens).
1238  var shell = getShellService();
1239  if (shell) {
1240  var shouldCheck = shell.shouldCheckDefaultBrowser;
1241  var willRecoverSession = false;
1242  try {
1243  var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
1244  getService(Ci.nsISessionStartup);
1245  willRecoverSession =
1246  (ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
1247  }
1248  catch (ex) { /* never mind; suppose SessionStore is broken */ }
1249  if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) {
1250  var brandBundle = document.getElementById("bundle_brand");
1251  var shellBundle = document.getElementById("bundle_shell");
1252 
1253  var brandShortName = brandBundle.getString("brandShortName");
1254  var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
1255  var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
1256  [brandShortName]);
1257  var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
1258  [brandShortName]);
1259  const IPS = Components.interfaces.nsIPromptService;
1260  var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
1261  .getService(IPS);
1262  var checkEveryTime = { value: shouldCheck };
1263  var rv = ps.confirmEx(window, promptTitle, promptMessage,
1264  IPS.STD_YES_NO_BUTTONS,
1265  null, null, null, checkboxLabel, checkEveryTime);
1266  if (rv == 0)
1267  shell.setDefaultBrowser(true, false);
1268  shell.shouldCheckDefaultBrowser = checkEveryTime.value;
1269  }
1270  }
1271 #endif
1272 
1273  // BiDi UI
1274  gBidiUI = isBidiEnabled();
1275  if (gBidiUI) {
1276  document.getElementById("documentDirection-separator").hidden = false;
1277  document.getElementById("documentDirection-swap").hidden = false;
1278  document.getElementById("textfieldDirection-separator").hidden = false;
1279  document.getElementById("textfieldDirection-swap").hidden = false;
1280  }
1281 
1282 #ifdef XP_MACOSX
1283  // Setup click-and-hold gestures access to the session history
1284  // menus if global click-and-hold isn't turned on
1285  if (!getBoolPref("ui.click_hold_context_menus", false))
1286  SetClickAndHoldHandlers();
1287 #endif
1288 
1289  // Initialize the full zoom setting.
1290  // We do this before the session restore service gets initialized so we can
1291  // apply full zoom settings to tabs restored by the session restore service.
1292  try {
1293  FullZoom.init();
1294  }
1295  catch(ex) {
1296  Components.utils.reportError("Failed to init content pref service:\n" + ex);
1297  }
1298 
1299  let NP = {};
1300  Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
1301  NP.trackBrowserWindow(window);
1302 
1303  // initialize the session-restore service (in case it's not already running)
1304  if (document.documentElement.getAttribute("windowtype") == "navigator:browser") {
1305  try {
1306  var ss = Cc["@mozilla.org/browser/sessionstore;1"].
1307  getService(Ci.nsISessionStore);
1308  ss.init(window);
1309  } catch(ex) {
1310  dump("nsSessionStore could not be initialized: " + ex + "\n");
1311  }
1312  }
1313 
1314  // bookmark-all-tabs command
1315  gBookmarkAllTabsHandler = new BookmarkAllTabsHandler();
1316 
1317  // Attach a listener to watch for "command" events bubbling up from error
1318  // pages. This lets us fix bugs like 401575 which require error page UI to
1319  // do privileged things, without letting error pages have any privilege
1320  // themselves.
1321  gBrowser.addEventListener("command", BrowserOnCommand, false);
1322 
1323  tabPreviews.init();
1324  ctrlTab.readPref();
1325  gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false);
1326  gPrefService.addObserver(allTabs.prefName, allTabs, false);
1327 
1328  // Initialize the microsummary service by retrieving it, prompting its factory
1329  // to create its singleton, whose constructor initializes the service.
1330  // Started 4 seconds after delayedStartup (before the livemarks service below).
1331  setTimeout(function() {
1332  try {
1333  Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService);
1334  } catch (ex) {
1335  Components.utils.reportError("Failed to init microsummary service:\n" + ex);
1336  }
1337  }, 4000);
1338 
1339  // Delayed initialization of the livemarks update timer.
1340  // Livemark updates don't need to start until after bookmark UI
1341  // such as the toolbar has initialized. Starting 5 seconds after
1342  // delayedStartup in order to stagger this after the microsummary
1343  // service (see above) and before the download manager starts (see below).
1344  setTimeout(function() PlacesUtils.livemarks.start(), 5000);
1345 
1346  // Initialize the download manager some time after the app starts so that
1347  // auto-resume downloads begin (such as after crashing or quitting with
1348  // active downloads) and speeds up the first-load of the download manager UI.
1349  // If the user manually opens the download manager before the timeout, the
1350  // downloads will start right away, and getting the service again won't hurt.
1351  setTimeout(function() {
1352  gDownloadMgr = Cc["@mozilla.org/download-manager;1"].
1353  getService(Ci.nsIDownloadManager);
1354 
1355  // Initialize the downloads monitor panel listener
1356  DownloadMonitorPanel.init();
1357  }, 10000);
1358 
1359  // Delayed initialization of PlacesDBUtils.
1360  // This component checks for database coherence once per day, on
1361  // an idle timer, taking corrective actions where needed.
1362  setTimeout(function() PlacesUtils.startPlacesDBUtils(), 15000);
1363 
1364 #ifndef XP_MACOSX
1366  let placesContext = document.getElementById("placesContext");
1367  placesContext.addEventListener("popupshowing", updateEditUIVisibility, false);
1368  placesContext.addEventListener("popuphiding", updateEditUIVisibility, false);
1369 #endif
1370 
1371  // initialize the private browsing UI
1372  gPrivateBrowsingUI.init();
1373 
1374  gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme", LightWeightThemeWebInstaller, false, true);
1375  gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme", LightWeightThemeWebInstaller, false, true);
1376  gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview", LightWeightThemeWebInstaller, false, true);
1377 
1378  if (Win7Features)
1379  Win7Features.onOpenWindow();
1380 }
1381 
1383 {
1384  if (Win7Features)
1385  Win7Features.onCloseWindow();
1386 
1387  gPrefService.removeObserver(ctrlTab.prefName, ctrlTab);
1388  gPrefService.removeObserver(allTabs.prefName, allTabs);
1389  tabPreviews.uninit();
1390  ctrlTab.uninit();
1391  allTabs.uninit();
1392 
1393  gGestureSupport.init(false);
1394 
1395  try {
1396  FullZoom.destroy();
1397  }
1398  catch(ex) {
1399  Components.utils.reportError(ex);
1400  }
1401 
1402  var os = Components.classes["@mozilla.org/observer-service;1"]
1403  .getService(Components.interfaces.nsIObserverService);
1404  os.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
1405  os.removeObserver(gXPInstallObserver, "xpinstall-install-blocked");
1406 
1407  try {
1408  gBrowser.removeProgressListener(window.XULBrowserWindow);
1409  gBrowser.removeTabsProgressListener(window.TabsProgressListener);
1410  } catch (ex) {
1411  }
1412 
1413  PlacesStarButton.uninit();
1414 
1415  try {
1416  gPrefService.removeObserver(gAutoHideTabbarPrefListener.domain,
1417  gAutoHideTabbarPrefListener);
1418  gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton);
1419  gPrefService.removeObserver(gURLBarEmptyText.domain, gURLBarEmptyText);
1420  } catch (ex) {
1421  Components.utils.reportError(ex);
1422  }
1423 
1424  BrowserOffline.uninit();
1425  OfflineApps.uninit();
1426  DownloadMonitorPanel.uninit();
1427  gPrivateBrowsingUI.uninit();
1428 
1429  var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
1430  var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
1431  var enumerator = windowManagerInterface.getEnumerator(null);
1432  enumerator.getNext();
1433  if (!enumerator.hasMoreElements()) {
1434  document.persist("sidebar-box", "sidebarcommand");
1435  document.persist("sidebar-box", "width");
1436  document.persist("sidebar-box", "src");
1437  document.persist("sidebar-title", "value");
1438  }
1439 
1440  window.XULBrowserWindow.destroy();
1441  window.XULBrowserWindow = null;
1442  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
1443  .getInterface(Components.interfaces.nsIWebNavigation)
1444  .QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner
1445  .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
1446  .getInterface(Components.interfaces.nsIXULWindow)
1447  .XULBrowserWindow = null;
1448  window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = null;
1449 }
1450 
1451 #ifdef XP_MACOSX
1452 // nonBrowserWindowStartup(), nonBrowserWindowDelayedStartup(), and
1453 // nonBrowserWindowShutdown() are used for non-browser windows in
1454 // macBrowserOverlay
1455 function nonBrowserWindowStartup()
1456 {
1457  // Disable inappropriate commands / submenus
1458  var disabledItems = ['Browser:SavePage',
1459  'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain',
1460  'viewToolbarsMenu', 'cmd_toggleTaskbar', 'viewSidebarMenuMenu', 'Browser:Reload',
1461  'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
1462  'viewHistorySidebar', 'Browser:AddBookmarkAs', 'View:PageInfo', 'Tasks:InspectPage'];
1463  var element;
1464 
1465  for (var id in disabledItems)
1466  {
1467  element = document.getElementById(disabledItems[id]);
1468  if (element)
1469  element.setAttribute("disabled", "true");
1470  }
1471 
1472  // If no windows are active (i.e. we're the hidden window), disable the close, minimize
1473  // and zoom menu commands as well
1474  if (window.location.href == "chrome://browser/content/hiddenWindow.xul")
1475  {
1476  var hiddenWindowDisabledItems = ['cmd_close', 'minimizeWindow', 'zoomWindow'];
1477  for (var id in hiddenWindowDisabledItems)
1478  {
1479  element = document.getElementById(hiddenWindowDisabledItems[id]);
1480  if (element)
1481  element.setAttribute("disabled", "true");
1482  }
1483 
1484  // also hide the window-list separator
1485  element = document.getElementById("sep-window-list");
1486  element.setAttribute("hidden", "true");
1487  }
1488 
1489 
1490  setTimeout(nonBrowserWindowDelayedStartup, 0);
1491 }
1492 
1493 function nonBrowserWindowDelayedStartup()
1494 {
1495  // initialise the offline listener
1496  BrowserOffline.init();
1497 
1498  // Set up Sanitize Item
1499  initializeSanitizer();
1500 
1501  // initialize the private browsing UI
1502  gPrivateBrowsingUI.init();
1503 }
1504 
1505 function nonBrowserWindowShutdown()
1506 {
1507  BrowserOffline.uninit();
1508 
1509  gPrivateBrowsingUI.uninit();
1510 }
1511 #endif
1512 
1514 {
1515  this.toggleAutoHideTabbar();
1516 }
1517 
1519 {
1520  domain: "browser.tabs.autoHide",
1521  observe: function (aSubject, aTopic, aPrefName)
1522  {
1523  if (aTopic != "nsPref:changed" || aPrefName != this.domain)
1524  return;
1525 
1526  this.toggleAutoHideTabbar();
1527  },
1528 
1529  toggleAutoHideTabbar: function ()
1530  {
1531  if (gBrowser.tabContainer.childNodes.length == 1 &&
1532  window.toolbar.visible) {
1533  var aVisible = false;
1534  try {
1535  aVisible = !gPrefService.getBoolPref(this.domain);
1536  }
1537  catch (e) {
1538  }
1539  gBrowser.setStripVisibilityTo(aVisible);
1540  }
1541  }
1542 }
1543 
1544 function initializeSanitizer()
1545 {
1546  // Always use the label with ellipsis
1547  var label = gNavigatorBundle.getString("sanitizeWithPromptLabel2");
1548  document.getElementById("sanitizeItem").setAttribute("label", label);
1549 
1550  const kDidSanitizeDomain = "privacy.sanitize.didShutdownSanitize";
1551  if (gPrefService.prefHasUserValue(kDidSanitizeDomain)) {
1552  gPrefService.clearUserPref(kDidSanitizeDomain);
1553  // We need to persist this preference change, since we want to
1554  // check it at next app start even if the browser exits abruptly
1555  gPrefService.savePrefFile(null);
1556  }
1557 
1564  if (!gPrefService.getBoolPref("privacy.sanitize.migrateFx3Prefs")) {
1565  let itemBranch = gPrefService.getBranch("privacy.item.");
1566  let itemCount = { value: 0 };
1567  let itemArray = itemBranch.getChildList("", itemCount);
1568 
1569  // See if any privacy.item prefs are set
1570  let doMigrate = itemArray.some(function (name) itemBranch.prefHasUserValue(name));
1571  // Or if sanitizeOnShutdown is set
1572  if (!doMigrate)
1573  doMigrate = gPrefService.getBoolPref("privacy.sanitize.sanitizeOnShutdown");
1574 
1575  if (doMigrate) {
1576  let cpdBranch = gPrefService.getBranch("privacy.cpd.");
1577  let clearOnShutdownBranch = gPrefService.getBranch("privacy.clearOnShutdown.");
1578  itemArray.forEach(function (name) {
1579  try {
1580  // don't migrate password or offlineApps clearing in the CRH dialog since
1581  // there's no UI for those anymore. They default to false. bug 497656
1582  if (name != "passwords" && name != "offlineApps")
1583  cpdBranch.setBoolPref(name, itemBranch.getBoolPref(name));
1584  clearOnShutdownBranch.setBoolPref(name, itemBranch.getBoolPref(name));
1585  }
1586  catch(e) {
1587  Cu.reportError("Exception thrown during privacy pref migration: " + e);
1588  }
1589  });
1590  }
1591 
1592  gPrefService.setBoolPref("privacy.sanitize.migrateFx3Prefs", true);
1593  }
1594 }
1595 
1596 function gotoHistoryIndex(aEvent)
1597 {
1598  var index = aEvent.target.getAttribute("index");
1599  if (!index)
1600  return false;
1601 
1602  var where = whereToOpenLink(aEvent);
1603 
1604  if (where == "current") {
1605  // Normal click. Go there in the current tab and update session history.
1606 
1607  try {
1608  gBrowser.gotoIndex(index);
1609  }
1610  catch(ex) {
1611  return false;
1612  }
1613  return true;
1614  }
1615  else {
1616  // Modified click. Go there in a new tab/window.
1617  // This code doesn't copy history or work well with framed pages.
1618 
1619  var sessionHistory = getWebNavigation().sessionHistory;
1620  var entry = sessionHistory.getEntryAtIndex(index, false);
1621  var url = entry.URI.spec;
1622  openUILinkIn(url, where);
1623  return true;
1624  }
1625 }
1626 
1627 function BrowserForward(aEvent) {
1628  var where = whereToOpenLink(aEvent, false, true);
1629 
1630  if (where == "current") {
1631  try {
1632  gBrowser.goForward();
1633  }
1634  catch(ex) {
1635  }
1636  }
1637  else {
1638  var sessionHistory = getWebNavigation().sessionHistory;
1639  var currentIndex = sessionHistory.index;
1640  var entry = sessionHistory.getEntryAtIndex(currentIndex + 1, false);
1641  var url = entry.URI.spec;
1642  openUILinkIn(url, where);
1643  }
1644 }
1645 
1646 function BrowserBack(aEvent) {
1647  var where = whereToOpenLink(aEvent, false, true);
1648 
1649  if (where == "current") {
1650  try {
1651  gBrowser.goBack();
1652  }
1653  catch(ex) {
1654  }
1655  }
1656  else {
1657  var sessionHistory = getWebNavigation().sessionHistory;
1658  var currentIndex = sessionHistory.index;
1659  var entry = sessionHistory.getEntryAtIndex(currentIndex - 1, false);
1660  var url = entry.URI.spec;
1661  openUILinkIn(url, where);
1662  }
1663 }
1664 
1665 function BrowserHandleBackspace()
1666 {
1667  switch (gPrefService.getIntPref("browser.backspace_action")) {
1668  case 0:
1669  BrowserBack();
1670  break;
1671  case 1:
1672  goDoCommand("cmd_scrollPageUp");
1673  break;
1674  }
1675 }
1676 
1677 function BrowserHandleShiftBackspace()
1678 {
1679  switch (gPrefService.getIntPref("browser.backspace_action")) {
1680  case 0:
1681  BrowserForward();
1682  break;
1683  case 1:
1684  goDoCommand("cmd_scrollPageDown");
1685  break;
1686  }
1687 }
1688 
1689 function BrowserStop()
1690 {
1691  try {
1692  const stopFlags = nsIWebNavigation.STOP_ALL;
1693  getWebNavigation().stop(stopFlags);
1694  }
1695  catch(ex) {
1696  }
1697 }
1698 
1699 function BrowserReloadOrDuplicate(aEvent) {
1700  var backgroundTabModifier = aEvent.button == 1 ||
1701 #ifdef XP_MACOSX
1702  aEvent.metaKey;
1703 #else
1704  aEvent.ctrlKey;
1705 #endif
1706  if (aEvent.shiftKey && !backgroundTabModifier) {
1708  return;
1709  }
1710 
1711  var where = whereToOpenLink(aEvent, false, true);
1712  if (where == "current")
1713  BrowserReload();
1714  else
1715  openUILinkIn(getWebNavigation().currentURI.spec, where);
1716 }
1717 
1718 function BrowserReload() {
1719  const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE;
1720  BrowserReloadWithFlags(reloadFlags);
1721 }
1722 
1723 function BrowserReloadSkipCache() {
1724  // Bypass proxy and cache.
1725  const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
1726  BrowserReloadWithFlags(reloadFlags);
1727 }
1728 
1729 function BrowserHome()
1730 {
1731  var homePage = gHomeButton.getHomePage();
1732  loadOneOrMoreURIs(homePage);
1733 }
1734 
1735 function BrowserGoHome(aEvent) {
1736  if (aEvent && "button" in aEvent &&
1737  aEvent.button == 2) // right-click: do nothing
1738  return;
1739 
1740  var homePage = gHomeButton.getHomePage();
1741  var where = whereToOpenLink(aEvent, false, true);
1742  var urls;
1743 
1744  // openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages
1745  switch (where) {
1746  case "current":
1747  loadOneOrMoreURIs(homePage);
1748  break;
1749  case "tabshifted":
1750  case "tab":
1751  urls = homePage.split("|");
1752  var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false);
1753  gBrowser.loadTabs(urls, loadInBackground);
1754  break;
1755  case "window":
1756  OpenBrowserWindow();
1757  break;
1758  }
1759 }
1760 
1761 function loadOneOrMoreURIs(aURIString)
1762 {
1763 #ifdef XP_MACOSX
1764  // we're not a browser window, pass the URI string to a new browser window
1765  if (window.location.href != getBrowserURL())
1766  {
1767  window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", aURIString);
1768  return;
1769  }
1770 #endif
1771  // This function throws for certain malformed URIs, so use exception handling
1772  // so that we don't disrupt startup
1773  try {
1774  gBrowser.loadTabs(aURIString.split("|"), false, true);
1775  }
1776  catch (e) {
1777  }
1778 }
1779 
1780 function focusAndSelectUrlBar() {
1781  if (gURLBar && !gURLBar.readOnly) {
1782  if (window.fullScreen)
1783  FullScreen.mouseoverToggle(true);
1784  if (isElementVisible(gURLBar)) {
1785  gURLBar.focus();
1786  gURLBar.select();
1787  return true;
1788  }
1789  }
1790  return false;
1791 }
1792 
1793 function openLocation() {
1794  if (focusAndSelectUrlBar())
1795  return;
1796 
1797 #ifdef XP_MACOSX
1798  if (window.location.href != getBrowserURL()) {
1799  var win = getTopWin();
1800  if (win) {
1801  // If there's an open browser window, it should handle this command
1802  win.focus()
1803  win.openLocation();
1804  }
1805  else {
1806  // If there are no open browser windows, open a new one
1807  win = window.openDialog("chrome://browser/content/", "_blank",
1808  "chrome,all,dialog=no", "about:blank");
1809  win.addEventListener("load", openLocationCallback, false);
1810  }
1811  return;
1812  }
1813 #endif
1814  openDialog("chrome://browser/content/openLocation.xul", "_blank",
1815  "chrome,modal,titlebar", window);
1816 }
1817 
1818 function openLocationCallback()
1819 {
1820  // make sure the DOM is ready
1821  setTimeout(function() { this.openLocation(); }, 0);
1822 }
1823 
1824 function BrowserOpenTab()
1825 {
1826  if (!gBrowser) {
1827  // If there are no open browser windows, open a new one
1828  window.openDialog("chrome://browser/content/", "_blank",
1829  "chrome,all,dialog=no", "about:blank");
1830  return;
1831  }
1832  gBrowser.loadOneTab("about:blank", {inBackground: false});
1833  focusAndSelectUrlBar();
1834 }
1835 
1836 /* Called from the openLocation dialog. This allows that dialog to instruct
1837  its opener to open a new window and then step completely out of the way.
1838  Anything less byzantine is causing horrible crashes, rather believably,
1839  though oddly only on Linux. */
1840 function delayedOpenWindow(chrome, flags, href, postData)
1841 {
1842  // The other way to use setTimeout,
1843  // setTimeout(openDialog, 10, chrome, "_blank", flags, url),
1844  // doesn't work here. The extra "magic" extra argument setTimeout adds to
1845  // the callback function would confuse prepareForStartup() by making
1846  // window.arguments[1] be an integer instead of null.
1847  setTimeout(function() { openDialog(chrome, "_blank", flags, href, null, null, postData); }, 10);
1848 }
1849 
1850 /* Required because the tab needs time to set up its content viewers and get the load of
1851  the URI kicked off before becoming the active content area. */
1852 function delayedOpenTab(aUrl, aReferrer, aCharset, aPostData, aAllowThirdPartyFixup)
1853 {
1854  gBrowser.loadOneTab(aUrl, {
1855  referrerURI: aReferrer,
1856  charset: aCharset,
1857  postData: aPostData,
1858  inBackground: false,
1859  allowThirdPartyFixup: aAllowThirdPartyFixup});
1860 }
1861 
1862 var gLastOpenDirectory = {
1863  _lastDir: null,
1864  get path() {
1865  if (!this._lastDir || !this._lastDir.exists()) {
1866  try {
1867  this._lastDir = gPrefService.getComplexValue("browser.open.lastDir",
1868  Ci.nsILocalFile);
1869  if (!this._lastDir.exists())
1870  this._lastDir = null;
1871  }
1872  catch(e) {}
1873  }
1874  return this._lastDir;
1875  },
1876  set path(val) {
1877  if (!val || !val.exists() || !val.isDirectory())
1878  return;
1879  this._lastDir = val.clone();
1880 
1881  // Don't save the last open directory pref inside the Private Browsing mode
1882  if (!gPrivateBrowsingUI.privateBrowsingEnabled)
1883  gPrefService.setComplexValue("browser.open.lastDir", Ci.nsILocalFile,
1884  this._lastDir);
1885  },
1886  reset: function() {
1887  this._lastDir = null;
1888  }
1889 };
1890 
1892 {
1893  // Get filepicker component.
1894  try {
1895  const nsIFilePicker = Components.interfaces.nsIFilePicker;
1896  var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
1897  fp.init(window, gNavigatorBundle.getString("openFile"), nsIFilePicker.modeOpen);
1898  fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | nsIFilePicker.filterImages |
1899  nsIFilePicker.filterXML | nsIFilePicker.filterHTML);
1900  fp.displayDirectory = gLastOpenDirectory.path;
1901 
1902  if (fp.show() == nsIFilePicker.returnOK) {
1903  if (fp.file && fp.file.exists())
1904  gLastOpenDirectory.path = fp.file.parent.QueryInterface(Ci.nsILocalFile);
1905  openTopWin(fp.fileURL.spec);
1906  }
1907  } catch (ex) {
1908  }
1909 }
1910 
1912 #ifdef XP_MACOSX
1913  // If we're not a browser window, just close the window
1914  if (window.location.href != getBrowserURL()) {
1915  closeWindow(true);
1916  return;
1917  }
1918 #endif
1919 
1920  // If the current tab is the last one, this will close the window.
1921  gBrowser.removeCurrentTab();
1922 }
1923 
1925 {
1926  if (WindowIsClosing()) {
1927  if (window.fullScreen) {
1928  gBrowser.mPanelContainer.removeEventListener("mousemove",
1929  FullScreen._collapseCallback, false);
1930  document.removeEventListener("keypress", FullScreen._keyToggleCallback, false);
1931  document.removeEventListener("popupshown", FullScreen._setPopupOpen, false);
1932  document.removeEventListener("popuphidden", FullScreen._setPopupOpen, false);
1933  gPrefService.removeObserver("browser.fullscreen", FullScreen);
1934 
1935  var fullScrToggler = document.getElementById("fullscr-toggler");
1936  if (fullScrToggler) {
1937  fullScrToggler.removeEventListener("mouseover", FullScreen._expandCallback, false);
1938  fullScrToggler.removeEventListener("dragenter", FullScreen._expandCallback, false);
1939  }
1940  }
1941 
1942  window.close(); // WindowIsClosing does all the necessary checks
1943  }
1944 }
1945 
1946 function loadURI(uri, referrer, postData, allowThirdPartyFixup)
1947 {
1948  try {
1949  if (postData === undefined)
1950  postData = null;
1951  var flags = nsIWebNavigation.LOAD_FLAGS_NONE;
1952  if (allowThirdPartyFixup) {
1953  flags = nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
1954  }
1955  gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData);
1956  } catch (e) {
1957  }
1958 }
1959 
1960 function getShortcutOrURI(aURL, aPostDataRef) {
1961  var shortcutURL = null;
1962  var keyword = aURL;
1963  var param = "";
1964  var searchService = Cc["@mozilla.org/browser/search-service;1"].
1965  getService(Ci.nsIBrowserSearchService);
1966 
1967  var offset = aURL.indexOf(" ");
1968  if (offset > 0) {
1969  keyword = aURL.substr(0, offset);
1970  param = aURL.substr(offset + 1);
1971  }
1972 
1973  if (!aPostDataRef)
1974  aPostDataRef = {};
1975 
1976  var engine = searchService.getEngineByAlias(keyword);
1977  if (engine) {
1978  var submission = engine.getSubmission(param, null);
1979  aPostDataRef.value = submission.postData;
1980  return submission.uri.spec;
1981  }
1982 
1983  [shortcutURL, aPostDataRef.value] =
1984  PlacesUtils.getURLAndPostDataForKeyword(keyword);
1985 
1986  if (!shortcutURL)
1987  return aURL;
1988 
1989  var postData = "";
1990  if (aPostDataRef.value)
1991  postData = unescape(aPostDataRef.value);
1992 
1993  if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) {
1994  var charset = "";
1995  const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/;
1996  var matches = shortcutURL.match(re);
1997  if (matches)
1998  [, shortcutURL, charset] = matches;
1999  else {
2000  // Try to get the saved character-set.
2001  try {
2002  // makeURI throws if URI is invalid.
2003  // Will return an empty string if character-set is not found.
2004  charset = PlacesUtils.history.getCharsetForURI(makeURI(shortcutURL));
2005  } catch (e) {}
2006  }
2007 
2008  var encodedParam = "";
2009  if (charset)
2010  encodedParam = escape(convertFromUnicode(charset, param));
2011  else // Default charset is UTF-8
2012  encodedParam = encodeURIComponent(param);
2013 
2014  shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param);
2015 
2016  if (/%s/i.test(postData)) // POST keyword
2017  aPostDataRef.value = getPostDataStream(postData, param, encodedParam,
2018  "application/x-www-form-urlencoded");
2019  }
2020  else if (param) {
2021  // This keyword doesn't take a parameter, but one was provided. Just return
2022  // the original URL.
2023  aPostDataRef.value = null;
2024 
2025  return aURL;
2026  }
2027 
2028  return shortcutURL;
2029 }
2030 
2031 function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) {
2032  var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
2033  createInstance(Ci.nsIStringInputStream);
2034  aStringData = aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword);
2035  dataStream.data = aStringData;
2036 
2037  var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].
2038  createInstance(Ci.nsIMIMEInputStream);
2039  mimeStream.addHeader("Content-Type", aType);
2040  mimeStream.addContentLength = true;
2041  mimeStream.setData(dataStream);
2042  return mimeStream.QueryInterface(Ci.nsIInputStream);
2043 }
2044 
2046 {
2047  var url;
2048 
2049  try {
2050  // Get clipboard.
2051  var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
2052  .getService(Components.interfaces.nsIClipboard);
2053 
2054  // Create transferable that will transfer the text.
2055  var trans = Components.classes["@mozilla.org/widget/transferable;1"]
2056  .createInstance(Components.interfaces.nsITransferable);
2057 
2058  trans.addDataFlavor("text/unicode");
2059 
2060  // If available, use selection clipboard, otherwise global one
2061  if (clipboard.supportsSelectionClipboard())
2062  clipboard.getData(trans, clipboard.kSelectionClipboard);
2063  else
2064  clipboard.getData(trans, clipboard.kGlobalClipboard);
2065 
2066  var data = {};
2067  var dataLen = {};
2068  trans.getTransferData("text/unicode", data, dataLen);
2069 
2070  if (data) {
2071  data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
2072  url = data.data.substring(0, dataLen.value / 2);
2073  }
2074  } catch (ex) {
2075  }
2076 
2077  return url;
2078 }
2079 
2081 {
2082  var pageCookie;
2083  var webNav;
2084 
2085  // Get the document charset
2086  var docCharset = "charset=" + aDocument.characterSet;
2087 
2088  // Get the nsIWebNavigation associated with the document
2089  try {
2090  var win;
2091  var ifRequestor;
2092 
2093  // Get the DOMWindow for the requested document. If the DOMWindow
2094  // cannot be found, then just use the content window...
2095  //
2096  // XXX: This is a bit of a hack...
2097  win = aDocument.defaultView;
2098  if (win == window) {
2099  win = content;
2100  }
2101  ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
2102 
2103  webNav = ifRequestor.getInterface(nsIWebNavigation);
2104  } catch(err) {
2105  // If nsIWebNavigation cannot be found, just get the one for the whole
2106  // window...
2107  webNav = getWebNavigation();
2108  }
2109  //
2110  // Get the 'PageDescriptor' for the current document. This allows the
2111  // view-source to access the cached copy of the content rather than
2112  // refetching it from the network...
2113  //
2114  try{
2115  var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);
2116 
2117  pageCookie = PageLoader.currentDescriptor;
2118  } catch(err) {
2119  // If no page descriptor is available, just use the view-source URL...
2120  }
2121 
2122  top.gViewSourceUtils.viewSource(webNav.currentURI.spec, pageCookie, aDocument);
2123 }
2124 
2125 // doc - document to use for source, or null for this window's document
2126 // initialTab - name of the initial tab to display, or null for the first tab
2127 // imageElement - image to load in the Media Tab of the Page Info window; can be null/omitted
2128 function BrowserPageInfo(doc, initialTab, imageElement) {
2129  var args = {doc: doc, initialTab: initialTab, imageElement: imageElement};
2130  var windows = Cc['@mozilla.org/appshell/window-mediator;1']
2131  .getService(Ci.nsIWindowMediator)
2132  .getEnumerator("Browser:page-info");
2133 
2134  var documentURL = doc ? doc.location : window.content.document.location;
2135 
2136  // Check for windows matching the url
2137  while (windows.hasMoreElements()) {
2138  var currentWindow = windows.getNext();
2139  if (currentWindow.document.documentElement.getAttribute("relatedUrl") == documentURL) {
2140  currentWindow.focus();
2141  currentWindow.resetPageInfo(args);
2142  return currentWindow;
2143  }
2144  }
2145 
2146  // We didn't find a matching window, so open a new one.
2147  return openDialog("chrome://browser/content/pageinfo/pageInfo.xul", "",
2148  "chrome,toolbar,dialog=no,resizable", args);
2149 }
2150 
2151 #ifdef DEBUG
2152 // Initialize the LeakDetector class.
2153 function LeakDetector(verbose)
2154 {
2155  this.verbose = verbose;
2156 }
2157 
2158 const NS_LEAKDETECTOR_CONTRACTID = "@mozilla.org/xpcom/leakdetector;1";
2159 
2160 if (NS_LEAKDETECTOR_CONTRACTID in Components.classes) {
2161  try {
2162  LeakDetector.prototype = Components.classes[NS_LEAKDETECTOR_CONTRACTID]
2163  .createInstance(Components.interfaces.nsILeakDetector);
2164  } catch (err) {
2165  LeakDetector.prototype = Object.prototype;
2166  }
2167 } else {
2168  LeakDetector.prototype = Object.prototype;
2169 }
2170 
2171 var leakDetector = new LeakDetector(false);
2172 
2173 // Dumps current set of memory leaks.
2174 function dumpMemoryLeaks()
2175 {
2176  leakDetector.dumpLeaks();
2177 }
2178 
2179 // Traces all objects reachable from the chrome document.
2180 function traceChrome()
2181 {
2182  leakDetector.traceObject(document, leakDetector.verbose);
2183 }
2184 
2185 // Traces all objects reachable from the content document.
2186 function traceDocument()
2187 {
2188  // keep the chrome document out of the dump.
2189  leakDetector.markObject(document, true);
2190  leakDetector.traceObject(content, leakDetector.verbose);
2191  leakDetector.markObject(document, false);
2192 }
2193 
2194 // Controls whether or not we do verbose tracing.
2195 function traceVerbose(verbose)
2196 {
2197  leakDetector.verbose = (verbose == "true");
2198 }
2199 #endif
2200 
2201 function URLBarSetURI(aURI, aValid) {
2202  var value = gBrowser.userTypedValue;
2203  var valid = false;
2204 
2205  if (value == null) {
2206  let uri = aURI || getWebNavigation().currentURI;
2207 
2208  // Replace initial page URIs with an empty string
2209  // only if there's no opener (bug 370555).
2210  if (gInitialPages.indexOf(uri.spec) != -1)
2211  value = content.opener ? uri.spec : "";
2212  else
2213  value = losslessDecodeURI(uri);
2214 
2215  let isBlank = (uri.spec == "about:blank");
2216  valid = !isBlank && (!aURI || aValid);
2217  }
2218 
2219  gURLBar.value = value;
2220  SetPageProxyState(valid ? "valid" : "invalid");
2221 }
2222 
2223 function losslessDecodeURI(aURI) {
2224  var value = aURI.spec;
2225  // Try to decode as UTF-8 if there's no encoding sequence that we would break.
2226  if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value))
2227  try {
2228  value = decodeURI(value)
2229  // 1. decodeURI decodes %25 to %, which creates unintended
2230  // encoding sequences. Re-encode it, unless it's part of
2231  // a sequence that survived decodeURI, i.e. one for:
2232  // ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#'
2233  // (RFC 3987 section 3.2)
2234  // 2. Re-encode whitespace so that it doesn't get eaten away
2235  // by the location bar (bug 410726).
2236  .replace(/%(?!3B|2F|3F|3A|40|26|3D|2B|24|2C|23)|[\r\n\t]/ig,
2238  } catch (e) {}
2239 
2240  // Encode invisible characters (soft hyphen, zero-width space, BOM,
2241  // line and paragraph separator, word joiner, invisible times,
2242  // invisible separator, object replacement character) (bug 452979)
2243  value = value.replace(/[\v\x0c\x1c\x1d\x1e\x1f\u00ad\u200b\ufeff\u2028\u2029\u2060\u2062\u2063\ufffc]/g,
2245 
2246  // Encode bidirectional formatting characters.
2247  // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
2248  value = value.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
2250  return value;
2251 }
2252 
2254 {
2255  var splitter = document.getElementById("urlbar-search-splitter");
2256  var urlbar = document.getElementById("urlbar-container");
2257  var searchbar = document.getElementById("search-container");
2258 
2259  var ibefore = null;
2260  if (urlbar && searchbar) {
2261  if (urlbar.nextSibling == searchbar)
2262  ibefore = searchbar;
2263  else if (searchbar.nextSibling == urlbar)
2264  ibefore = urlbar;
2265  }
2266 
2267  if (ibefore) {
2268  if (!splitter) {
2269  splitter = document.createElement("splitter");
2270  splitter.id = "urlbar-search-splitter";
2271  splitter.setAttribute("resizebefore", "flex");
2272  splitter.setAttribute("resizeafter", "flex");
2273  splitter.className = "chromeclass-toolbar-additional";
2274  }
2275  urlbar.parentNode.insertBefore(splitter, ibefore);
2276  } else if (splitter)
2277  splitter.parentNode.removeChild(splitter);
2278 }
2279 
2281  _timeoutID: null,
2282 
2283  _searchBegin: function LocBar_searchBegin() {
2284  function delayedBegin(self) {
2285  self._timeoutID = null;
2286  document.getElementById("urlbar-throbber").setAttribute("busy", "true");
2287  }
2288 
2289  this._timeoutID = setTimeout(delayedBegin, 500, this);
2290  },
2291 
2292  _searchComplete: function LocBar_searchComplete() {
2293  // Did we finish the search before delayedBegin was invoked?
2294  if (this._timeoutID) {
2295  clearTimeout(this._timeoutID);
2296  this._timeoutID = null;
2297  }
2298  document.getElementById("urlbar-throbber").removeAttribute("busy");
2299  }
2300 };
2301 
2303 {
2304  if (gURLBar && gURLBar.value != gLastValidURLStr)
2305  SetPageProxyState("invalid");
2306 }
2307 
2309 {
2310  if (!gURLBar)
2311  return;
2312 
2313  if (!gProxyFavIcon)
2314  gProxyFavIcon = document.getElementById("page-proxy-favicon");
2315 
2316  gURLBar.setAttribute("pageproxystate", aState);
2317  gProxyFavIcon.setAttribute("pageproxystate", aState);
2318 
2319  // the page proxy state is set to valid via OnLocationChange, which
2320  // gets called when we switch tabs.
2321  if (aState == "valid") {
2322  gLastValidURLStr = gURLBar.value;
2323  gURLBar.addEventListener("input", UpdatePageProxyState, false);
2324 
2325  PageProxySetIcon(gBrowser.mCurrentBrowser.mIconURL);
2326  } else if (aState == "invalid") {
2327  gURLBar.removeEventListener("input", UpdatePageProxyState, false);
2329  }
2330 }
2331 
2332 function PageProxySetIcon (aURL)
2333 {
2334  if (!gProxyFavIcon)
2335  return;
2336 
2337  if (!aURL)
2339  else if (gProxyFavIcon.getAttribute("src") != aURL)
2340  gProxyFavIcon.setAttribute("src", aURL);
2341 }
2342 
2344 {
2345  gProxyFavIcon.removeAttribute("src");
2346 }
2347 
2348 function PageProxyClickHandler(aEvent)
2349 {
2350  if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
2351  middleMousePaste(aEvent);
2352 }
2353 
2354 function BrowserImport()
2355 {
2356 #ifdef XP_MACOSX
2357  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
2358  .getService(Components.interfaces.nsIWindowMediator);
2359  var win = wm.getMostRecentWindow("Browser:MigrationWizard");
2360  if (win)
2361  win.focus();
2362  else {
2363  window.openDialog("chrome://browser/content/migration/migration.xul",
2364  "migration", "centerscreen,chrome,resizable=no");
2365  }
2366 #else
2367  window.openDialog("chrome://browser/content/migration/migration.xul",
2368  "migration", "modal,centerscreen,chrome,resizable=no");
2369 #endif
2370 }
2371 
2376  // Don't trust synthetic events
2377  if (!event.isTrusted)
2378  return;
2379 
2380  var ot = event.originalTarget;
2381  var errorDoc = ot.ownerDocument;
2382 
2383  // If the event came from an ssl error page, it is probably either the "Add
2384  // Exception…" or "Get me out of here!" button
2385  if (/^about:certerror/.test(errorDoc.documentURI)) {
2386  if (ot == errorDoc.getElementById('exceptionDialogButton')) {
2387  var params = { exceptionAdded : false, handlePrivateBrowsing : true };
2388 
2389  try {
2390  switch (gPrefService.getIntPref("browser.ssl_override_behavior")) {
2391  case 2 : // Pre-fetch & pre-populate
2392  params.prefetchCert = true;
2393  case 1 : // Pre-populate
2394  params.location = errorDoc.location.href;
2395  }
2396  } catch (e) {
2397  Components.utils.reportError("Couldn't get ssl_override pref: " + e);
2398  }
2399 
2400  window.openDialog('chrome://pippki/content/exceptionDialog.xul',
2401  '','chrome,centerscreen,modal', params);
2402 
2403  // If the user added the exception cert, attempt to reload the page
2404  if (params.exceptionAdded)
2405  errorDoc.location.reload();
2406  }
2407  else if (ot == errorDoc.getElementById('getMeOutOfHereButton')) {
2408  getMeOutOfHere();
2409  }
2410  }
2411  else if (/^about:blocked/.test(errorDoc.documentURI)) {
2412  // The event came from a button on a malware/phishing block page
2413  // First check whether it's malware or phishing, so that we can
2414  // use the right strings/links
2415  var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
2416 
2417  if (ot == errorDoc.getElementById('getMeOutButton')) {
2418  getMeOutOfHere();
2419  }
2420  else if (ot == errorDoc.getElementById('reportButton')) {
2421  // This is the "Why is this site blocked" button. For malware,
2422  // we can fetch a site-specific report, for phishing, we redirect
2423  // to the generic page describing phishing protection.
2424  var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
2425  .getService(Components.interfaces.nsIURLFormatter);
2426 
2427  if (isMalware) {
2428  // Get the stop badware "why is this blocked" report url,
2429  // append the current url, and go there.
2430  try {
2431  var reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL");
2432  reportURL += errorDoc.location.href;
2433  content.location = reportURL;
2434  } catch (e) {
2435  Components.utils.reportError("Couldn't get malware report URL: " + e);
2436  }
2437  }
2438  else { // It's a phishing site, not malware
2439  try {
2440  content.location = formatter.formatURLPref("browser.safebrowsing.warning.infoURL");
2441  } catch (e) {
2442  Components.utils.reportError("Couldn't get phishing info URL: " + e);
2443  }
2444  }
2445  }
2446  else if (ot == errorDoc.getElementById('ignoreWarningButton')) {
2447  // Allow users to override and continue through to the site,
2448  // but add a notify bar as a reminder, so that they don't lose
2449  // track after, e.g., tab switching.
2450  gBrowser.loadURIWithFlags(content.location.href,
2451  nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
2452  null, null, null);
2453  var buttons = [{
2454  label: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"),
2455  accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
2456  callback: function() { getMeOutOfHere(); }
2457  }];
2458 
2459  if (isMalware) {
2460  var title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
2461  buttons[1] = {
2462  label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"),
2463  accessKey: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.accessKey"),
2464  callback: function() {
2465  openUILinkIn(safebrowsing.getReportURL('MalwareError'), 'tab');
2466  }
2467  };
2468  } else {
2469  title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
2470  buttons[1] = {
2471  label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
2472  accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
2473  callback: function() {
2474  openUILinkIn(safebrowsing.getReportURL('Error'), 'tab');
2475  }
2476  };
2477  }
2478 
2479  var notificationBox = gBrowser.getNotificationBox();
2480  notificationBox.appendNotification(
2481  title,
2482  "blocked-badware-page",
2483  "chrome://global/skin/icons/blacklist_favicon.png",
2484  notificationBox.PRIORITY_CRITICAL_HIGH,
2485  buttons
2486  );
2487  }
2488  }
2489  else if (/^about:privatebrowsing/.test(errorDoc.documentURI)) {
2490  if (ot == errorDoc.getElementById("startPrivateBrowsing")) {
2491  gPrivateBrowsingUI.toggleMode();
2492  }
2493  }
2494 }
2495 
2503 function getMeOutOfHere() {
2504  // Get the start page from the *default* pref branch, not the user's
2505  var prefs = Cc["@mozilla.org/preferences-service;1"]
2506  .getService(Ci.nsIPrefService).getDefaultBranch(null);
2507  var url = "about:blank";
2508  try {
2509  url = prefs.getComplexValue("browser.startup.homepage",
2510  Ci.nsIPrefLocalizedString).data;
2511  // If url is a pipe-delimited set of pages, just take the first one.
2512  if (url.indexOf("|") != -1)
2513  url = url.split("|")[0];
2514  } catch(e) {
2515  Components.utils.reportError("Couldn't get homepage pref: " + e);
2516  }
2517  content.location = url;
2518 }
2519 
2521 {
2522  window.fullScreen = !window.fullScreen;
2523 }
2524 
2525 function onFullScreen()
2526 {
2527  FullScreen.toggle();
2528 }
2529 
2531 {
2532  try {
2533  return gBrowser.webNavigation;
2534  } catch (e) {
2535  return null;
2536  }
2537 }
2538 
2539 function BrowserReloadWithFlags(reloadFlags) {
2540  /* First, we'll try to use the session history object to reload so
2541  * that framesets are handled properly. If we're in a special
2542  * window (such as view-source) that has no session history, fall
2543  * back on using the web navigation's reload method.
2544  */
2545 
2546  var webNav = getWebNavigation();
2547  try {
2548  var sh = webNav.sessionHistory;
2549  if (sh)
2550  webNav = sh.QueryInterface(nsIWebNavigation);
2551  } catch (e) {
2552  }
2553 
2554  try {
2555  webNav.reload(reloadFlags);
2556  } catch (e) {
2557  }
2558 }
2559 
2560 function toggleAffectedChrome(aHide)
2561 {
2562  // chrome to toggle includes:
2563  // (*) menubar
2564  // (*) navigation bar
2565  // (*) bookmarks toolbar
2566  // (*) tabstrip
2567  // (*) browser messages
2568  // (*) sidebar
2569  // (*) find bar
2570  // (*) statusbar
2571 
2572  gNavToolbox.hidden = aHide;
2573  if (aHide)
2574  {
2575  gChromeState = {};
2576  var sidebar = document.getElementById("sidebar-box");
2577  gChromeState.sidebarOpen = !sidebar.hidden;
2578  gSidebarCommand = sidebar.getAttribute("sidebarcommand");
2579 
2580  gChromeState.hadTabStrip = gBrowser.getStripVisibility();
2581  gBrowser.setStripVisibilityTo(false);
2582 
2583  var notificationBox = gBrowser.getNotificationBox();
2584  gChromeState.notificationsOpen = !notificationBox.notificationsHidden;
2585  notificationBox.notificationsHidden = aHide;
2586 
2587  document.getElementById("sidebar").setAttribute("src", "about:blank");
2588  var statusbar = document.getElementById("status-bar");
2589  gChromeState.statusbarOpen = !statusbar.hidden;
2590  statusbar.hidden = aHide;
2591 
2592  gChromeState.findOpen = !gFindBar.hidden;
2593  gFindBar.close();
2594  }
2595  else {
2596  if (gChromeState.hadTabStrip) {
2597  gBrowser.setStripVisibilityTo(true);
2598  }
2599 
2600  if (gChromeState.notificationsOpen) {
2601  gBrowser.getNotificationBox().notificationsHidden = aHide;
2602  }
2603 
2604  if (gChromeState.statusbarOpen) {
2605  var statusbar = document.getElementById("status-bar");
2606  statusbar.hidden = aHide;
2607  }
2608 
2609  if (gChromeState.findOpen)
2610  gFindBar.open();
2611  }
2612 
2613  if (gChromeState.sidebarOpen)
2614  toggleSidebar(gSidebarCommand);
2615 }
2616 
2618 {
2619  gInPrintPreviewMode = true;
2620  toggleAffectedChrome(true);
2621 }
2622 
2624 {
2625  // restore chrome to original state
2626  gInPrintPreviewMode = false;
2627  toggleAffectedChrome(false);
2628 }
2629 
2630 function getPPBrowser()
2631 {
2632  return gBrowser;
2633 }
2634 
2636 {
2637  return gBrowser.markupDocumentViewer;
2638 }
2639 
2653 function FillInHTMLTooltip(tipElement)
2654 {
2655  var retVal = false;
2656  if (tipElement.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")
2657  return retVal;
2658 
2659  const XLinkNS = "http://www.w3.org/1999/xlink";
2660 
2661 
2662  var titleText = null;
2663  var XLinkTitleText = null;
2664  var direction = tipElement.ownerDocument.dir;
2665 
2666  while (!titleText && !XLinkTitleText && tipElement) {
2667  if (tipElement.nodeType == Node.ELEMENT_NODE) {
2668  titleText = tipElement.getAttribute("title");
2669  XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
2670  var defView = tipElement.ownerDocument.defaultView;
2671  // XXX Work around bug 350679:
2672  // "Tooltips can be fired in documents with no view".
2673  if (!defView)
2674  return retVal;
2675  direction = defView.getComputedStyle(tipElement, "")
2676  .getPropertyValue("direction");
2677  }
2678  tipElement = tipElement.parentNode;
2679  }
2680 
2681  var tipNode = document.getElementById("aHTMLTooltip");
2682  tipNode.style.direction = direction;
2683 
2684  [titleText, XLinkTitleText].forEach(function (t) {
2685  if (t && /\S/.test(t)) {
2686 
2687  // Per HTML 4.01 6.2 (CDATA section), literal CRs and tabs should be
2688  // replaced with spaces, and LFs should be removed entirely.
2689  // XXX Bug 322270: We don't preserve the result of entities like &#13;,
2690  // which should result in a line break in the tooltip, because we can't
2691  // distinguish that from a literal character in the source by this point.
2692  t = t.replace(/[\r\t]/g, ' ');
2693  t = t.replace(/\n/g, '');
2694 
2695  tipNode.setAttribute("label", t);
2696  retVal = true;
2697  }
2698  });
2699 
2700  return retVal;
2701 }
2702 
2704  getDragURLFromDataTransfer : function (dt)
2705  {
2706  var types = dt.types;
2707  for (var t = 0; t < types.length; t++) {
2708  var type = types[t];
2709  switch (type) {
2710  case "text/uri-list":
2711  var url = dt.getData("URL").replace(/^\s+|\s+$/g, "");
2712  return [url, url];
2713  case "text/plain":
2714  case "text/x-moz-text-internal":
2715  var url = dt.getData(type).replace(/^\s+|\s+$/g, "");
2716  return [url, url];
2717  case "text/x-moz-url":
2718  var split = dt.getData(type).split("\n");
2719  return [split[0], split[1]];
2720  }
2721  }
2722 
2723  // For shortcuts, we want to check for the file type last, so that the
2724  // url pointed to in one of the url types is found first before the file
2725  // type, which points to the actual file.
2726  var file = dt.mozGetDataAt("application/x-moz-file", 0);
2727  if (file) {
2728  var name = file instanceof Ci.nsIFile ? file.leafName : "";
2729  var fileHandler = ContentAreaUtils.ioService
2730  .getProtocolHandler("file")
2731  .QueryInterface(Ci.nsIFileProtocolHandler);
2732  return [fileHandler.getURLSpecFromFile(file), name];
2733  }
2734 
2735  return [ , ];
2736  },
2737 
2738  dragOver : function (aEvent, statusString)
2739  {
2740  var types = aEvent.dataTransfer.types;
2741  if (types.contains("application/x-moz-file") ||
2742  types.contains("text/x-moz-url") ||
2743  types.contains("text/uri-list") ||
2744  types.contains("text/x-moz-text-internal") ||
2745  types.contains("text/plain")) {
2746  aEvent.preventDefault();
2747 
2748  if (statusString) {
2749  var statusTextFld = document.getElementById("statusbar-display");
2750  statusTextFld.label = gNavigatorBundle.getString(statusString);
2751  }
2752  }
2753  }
2754 }
2755 
2756 
2757 var proxyIconDNDObserver = {
2758  onDragStart: function (aEvent, aXferData, aDragAction)
2759  {
2760  if (gProxyFavIcon.getAttribute("pageproxystate") != "valid")
2761  return;
2762 
2763  var value = content.location.href;
2764  var urlString = value + "\n" + content.document.title;
2765  var htmlString = "<a href=\"" + value + "\">" + value + "</a>";
2766 
2767  var dt = aEvent.dataTransfer;
2768  dt.setData("text/x-moz-url", urlString);
2769  dt.setData("text/uri-list", value);
2770  dt.setData("text/plain", value);
2771  dt.setData("text/html", htmlString);
2772  }
2773 }
2774 
2775 var homeButtonObserver = {
2776  onDrop: function (aEvent)
2777  {
2778  let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
2779  setTimeout(openHomeDialog, 0, url);
2780  },
2781 
2782  onDragOver: function (aEvent)
2783  {
2784  browserDragAndDrop.dragOver(aEvent, "droponhomebutton");
2785  aEvent.dropEffect = "link";
2786  },
2787  onDragLeave: function (aEvent)
2788  {
2789  var statusTextFld = document.getElementById("statusbar-display");
2790  statusTextFld.label = "";
2791  }
2792 }
2793 
2794 function openHomeDialog(aURL)
2795 {
2796  var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
2797  var promptTitle = gNavigatorBundle.getString("droponhometitle");
2798  var promptMsg = gNavigatorBundle.getString("droponhomemsg");
2799  var pressedVal = promptService.confirmEx(window, promptTitle, promptMsg,
2800  promptService.STD_YES_NO_BUTTONS,
2801  null, null, null, null, {value:0});
2802 
2803  if (pressedVal == 0) {
2804  try {
2805  var str = Components.classes["@mozilla.org/supports-string;1"]
2806  .createInstance(Components.interfaces.nsISupportsString);
2807  str.data = aURL;
2808  gPrefService.setComplexValue("browser.startup.homepage",
2809  Components.interfaces.nsISupportsString, str);
2810  var homeButton = document.getElementById("home-button");
2811  homeButton.setAttribute("tooltiptext", aURL);
2812  } catch (ex) {
2813  dump("Failed to set the home page.\n"+ex+"\n");
2814  }
2815  }
2816 }
2817 
2818 var bookmarksButtonObserver = {
2819  onDrop: function (aEvent)
2820  {
2821  let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
2822  try {
2823  PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(url), name);
2824  } catch(ex) { }
2825  },
2826 
2827  onDragOver: function (aEvent)
2828  {
2829  browserDragAndDrop.dragOver(aEvent, "droponbookmarksbutton");
2830  aEvent.dropEffect = "link";
2831  },
2832 
2833  onDragLeave: function (aEvent)
2834  {
2835  var statusTextFld = document.getElementById("statusbar-display");
2836  statusTextFld.label = "";
2837  }
2838 }
2839 
2840 var newTabButtonObserver = {
2841  onDragOver: function (aEvent)
2842  {
2843  browserDragAndDrop.dragOver(aEvent, "droponnewtabbutton");
2844  },
2845 
2846  onDragLeave: function (aEvent)
2847  {
2848  var statusTextFld = document.getElementById("statusbar-display");
2849  statusTextFld.label = "";
2850  },
2851 
2852  onDrop: function (aEvent)
2853  {
2854  let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
2855  var postData = {};
2856  url = getShortcutOrURI(url, postData);
2857  if (url) {
2858  nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
2859  // allow third-party services to fixup this URL
2860  openNewTabWith(url, null, postData.value, aEvent, true);
2861  }
2862  }
2863 }
2864 
2865 var newWindowButtonObserver = {
2866  onDragOver: function (aEvent)
2867  {
2868  browserDragAndDrop.dragOver(aEvent, "droponnewwindowbutton");
2869  },
2870  onDragLeave: function (aEvent)
2871  {
2872  var statusTextFld = document.getElementById("statusbar-display");
2873  statusTextFld.label = "";
2874  },
2875  onDrop: function (aEvent)
2876  {
2877  let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
2878  var postData = {};
2879  url = getShortcutOrURI(url, postData);
2880  if (url) {
2881  nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
2882  // allow third-party services to fixup this URL
2883  openNewWindowWith(url, null, postData.value, true);
2884  }
2885  }
2886 }
2887 
2888 var DownloadsButtonDNDObserver = {
2890  // nsDragAndDrop
2891  onDragOver: function (aEvent)
2892  {
2893  var statusTextFld = document.getElementById("statusbar-display");
2894  statusTextFld.label = gNavigatorBundle.getString("dropondownloadsbutton");
2895  var types = aEvent.dataTransfer.types;
2896  if (types.contains("text/x-moz-url") ||
2897  types.contains("text/uri-list") ||
2898  types.contains("text/plain"))
2899  aEvent.preventDefault();
2900  },
2901 
2902  onDragLeave: function (aEvent)
2903  {
2904  var statusTextFld = document.getElementById("statusbar-display");
2905  statusTextFld.label = "";
2906  },
2907 
2908  onDrop: function (aEvent)
2909  {
2910  let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
2911  nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
2912  saveURL(url, name, null, true, true);
2913  }
2914 }
2915 
2916 const DOMLinkHandler = {
2917  handleEvent: function (event) {
2918  switch (event.type) {
2919  case "DOMLinkAdded":
2920  this.onLinkAdded(event);
2921  break;
2922  }
2923  },
2924  onLinkAdded: function (event) {
2925  var link = event.originalTarget;
2926  var rel = link.rel && link.rel.toLowerCase();
2927  if (!link || !link.ownerDocument || !rel || !link.href)
2928  return;
2929 
2930  var feedAdded = false;
2931  var iconAdded = false;
2932  var searchAdded = false;
2933  var relStrings = rel.split(/\s+/);
2934  var rels = {};
2935  for (let i = 0; i < relStrings.length; i++)
2936  rels[relStrings[i]] = true;
2937 
2938  for (let relVal in rels) {
2939  switch (relVal) {
2940  case "feed":
2941  case "alternate":
2942  if (!feedAdded) {
2943  if (!rels.feed && rels.alternate && rels.stylesheet)
2944  break;
2945 
2946  if (isValidFeed(link, link.ownerDocument.nodePrincipal, rels.feed)) {
2947  FeedHandler.addFeed(link, link.ownerDocument);
2948  feedAdded = true;
2949  }
2950  }
2951  break;
2952  case "icon":
2953  if (!iconAdded) {
2954  if (!gPrefService.getBoolPref("browser.chrome.site_icons"))
2955  break;
2956 
2957  var targetDoc = link.ownerDocument;
2958  var uri = makeURI(link.href, targetDoc.characterSet);
2959 
2960  if (gBrowser.isFailedIcon(uri))
2961  break;
2962 
2963  // Verify that the load of this icon is legal.
2964  // error pages can load their favicon, to be on the safe side,
2965  // only allow chrome:// favicons
2966  const aboutNeterr = /^about:neterror\?/;
2967  const aboutBlocked = /^about:blocked\?/;
2968  const aboutCert = /^about:certerror\?/;
2969  if (!(aboutNeterr.test(targetDoc.documentURI) ||
2970  aboutBlocked.test(targetDoc.documentURI) ||
2971  aboutCert.test(targetDoc.documentURI)) ||
2972  !uri.schemeIs("chrome")) {
2973  var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
2974  getService(Ci.nsIScriptSecurityManager);
2975  try {
2976  ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
2977  Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
2978  } catch(e) {
2979  break;
2980  }
2981  }
2982 
2983  try {
2984  var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"].
2985  getService(Ci.nsIContentPolicy);
2986  } catch(e) {
2987  break; // Refuse to load if we can't do a security check.
2988  }
2989 
2990  // Security says okay, now ask content policy
2991  if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
2992  uri, targetDoc.documentURIObject,
2993  link, link.type, null)
2994  != Ci.nsIContentPolicy.ACCEPT)
2995  break;
2996 
2997  var browserIndex = gBrowser.getBrowserIndexForDocument(targetDoc);
2998  // no browser? no favicon.
2999  if (browserIndex == -1)
3000  break;
3001 
3002  var tab = gBrowser.mTabContainer.childNodes[browserIndex];
3003  gBrowser.setIcon(tab, link.href);
3004  iconAdded = true;
3005  }
3006  break;
3007  case "search":
3008  if (!searchAdded) {
3009  var type = link.type && link.type.toLowerCase();
3010  type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
3011 
3012  if (type == "application/opensearchdescription+xml" && link.title &&
3013  /^(?:https?|ftp):/i.test(link.href)) {
3014  var engine = { title: link.title, href: link.href };
3015  BrowserSearch.addEngine(engine, link.ownerDocument);
3016  searchAdded = true;
3017  }
3018  }
3019  break;
3020  }
3021  }
3022  }
3023 }
3024 
3025 const BrowserSearch = {
3026  addEngine: function(engine, targetDoc) {
3027  if (!this.searchBar)
3028  return;
3029 
3030  var browser = gBrowser.getBrowserForDocument(targetDoc);
3031  // ignore search engines from subframes (see bug 479408)
3032  if (!browser)
3033  return;
3034 
3035  // Check to see whether we've already added an engine with this title
3036  if (browser.engines) {
3037  if (browser.engines.some(function (e) e.title == engine.title))
3038  return;
3039  }
3040 
3041  // Append the URI and an appropriate title to the browser data.
3042  // Use documentURIObject in the check for shouldLoadFavIcon so that we
3043  // do the right thing with about:-style error pages. Bug 453442
3044  var iconURL = null;
3045  if (gBrowser.shouldLoadFavIcon(targetDoc.documentURIObject))
3046  iconURL = targetDoc.documentURIObject.prePath + "/favicon.ico";
3047 
3048  var hidden = false;
3049  // If this engine (identified by title) is already in the list, add it
3050  // to the list of hidden engines rather than to the main list.
3051  // XXX This will need to be changed when engines are identified by URL;
3052  // see bug 335102.
3053  var searchService = Cc["@mozilla.org/browser/search-service;1"].
3054  getService(Ci.nsIBrowserSearchService);
3055  if (searchService.getEngineByName(engine.title))
3056  hidden = true;
3057 
3058  var engines = (hidden ? browser.hiddenEngines : browser.engines) || [];
3059 
3060  engines.push({ uri: engine.href,
3061  title: engine.title,
3062  icon: iconURL });
3063 
3064  if (hidden)
3065  browser.hiddenEngines = engines;
3066  else {
3067  browser.engines = engines;
3068  if (browser == gBrowser.mCurrentBrowser)
3069  this.updateSearchButton();
3070  }
3071  },
3072 
3078  updateSearchButton: function() {
3079  var searchBar = this.searchBar;
3080 
3081  // The search bar binding might not be applied even though the element is
3082  // in the document (e.g. when the navigation toolbar is hidden), so check
3083  // for .searchButton specifically.
3084  if (!searchBar || !searchBar.searchButton)
3085  return;
3086 
3087  var engines = gBrowser.mCurrentBrowser.engines;
3088  if (engines && engines.length > 0)
3089  searchBar.searchButton.setAttribute("addengines", "true");
3090  else
3091  searchBar.searchButton.removeAttribute("addengines");
3092  },
3093 
3099  webSearch: function BrowserSearch_webSearch() {
3100 #ifdef XP_MACOSX
3101  if (window.location.href != getBrowserURL()) {
3102  var win = getTopWin();
3103  if (win) {
3104  // If there's an open browser window, it should handle this command
3105  win.focus()
3106  win.BrowserSearch.webSearch();
3107  } else {
3108  // If there are no open browser windows, open a new one
3109 
3110  // This needs to be in a timeout so that we don't end up refocused
3111  // in the url bar
3112  function webSearchCallback() {
3113  setTimeout(BrowserSearch.webSearch, 0);
3114  }
3115 
3116  win = window.openDialog("chrome://browser/content/", "_blank",
3117  "chrome,all,dialog=no", "about:blank");
3118  win.addEventListener("load", webSearchCallback, false);
3119  }
3120  return;
3121  }
3122 #endif
3123  if (window.fullScreen)
3124  FullScreen.mouseoverToggle(true);
3125 
3126  var searchBar = this.searchBar;
3127  if (isElementVisible(searchBar)) {
3128  searchBar.select();
3129  searchBar.focus();
3130  } else {
3131  var ss = Cc["@mozilla.org/browser/search-service;1"].
3132  getService(Ci.nsIBrowserSearchService);
3133  var searchForm = ss.defaultEngine.searchForm;
3134  loadURI(searchForm, null, null, false);
3135  }
3136  },
3137 
3149  loadSearch: function BrowserSearch_search(searchText, useNewTab) {
3150  var ss = Cc["@mozilla.org/browser/search-service;1"].
3151  getService(Ci.nsIBrowserSearchService);
3152  var engine;
3153 
3154  // If the search bar is visible, use the current engine, otherwise, fall
3155  // back to the default engine.
3156  if (isElementVisible(this.searchBar))
3157  engine = ss.currentEngine;
3158  else
3159  engine = ss.defaultEngine;
3160 
3161  var submission = engine.getSubmission(searchText, null); // HTML response
3162 
3163  // getSubmission can return null if the engine doesn't have a URL
3164  // with a text/html response type. This is unlikely (since
3165  // SearchService._addEngineToStore() should fail for such an engine),
3166  // but let's be on the safe side.
3167  if (!submission)
3168  return;
3169 
3170  if (useNewTab) {
3171  gBrowser.loadOneTab(submission.uri.spec, {
3172  postData: submission.postData,
3173  relatedToCurrent: true});
3174  } else
3175  loadURI(submission.uri.spec, null, submission.postData, false);
3176  },
3177 
3181  get searchBar() {
3182  return document.getElementById("searchbar");
3183  },
3184 
3185  loadAddEngines: function BrowserSearch_loadAddEngines() {
3186  var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
3187  var where = newWindowPref == 3 ? "tab" : "window";
3188  var regionBundle = document.getElementById("bundle_browser_region");
3189  var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true);
3190  openUILinkIn(searchEnginesURL, where);
3191  }
3192 }
3193 
3194 function FillHistoryMenu(aParent) {
3195  // Lazily add the hover listeners on first showing and never remove them
3196  if (!aParent.hasStatusListener) {
3197  // Show history item's uri in the status bar when hovering, and clear on exit
3198  aParent.addEventListener("DOMMenuItemActive", function(aEvent) {
3199  // Only the current page should have the checked attribute, so skip it
3200  if (!aEvent.target.hasAttribute("checked"))
3201  XULBrowserWindow.setOverLink(aEvent.target.getAttribute("uri"));
3202  }, false);
3203  aParent.addEventListener("DOMMenuItemInactive", function() {
3204  XULBrowserWindow.setOverLink("");
3205  }, false);
3206 
3207  aParent.hasStatusListener = true;
3208  }
3209 
3210  // Remove old entries if any
3211  var children = aParent.childNodes;
3212  for (var i = children.length - 1; i >= 0; --i) {
3213  if (children[i].hasAttribute("index"))
3214  aParent.removeChild(children[i]);
3215  }
3216 
3217  var webNav = getWebNavigation();
3218  var sessionHistory = webNav.sessionHistory;
3219 
3220  var count = sessionHistory.count;
3221  if (count <= 1) // don't display the popup for a single item
3222  return false;
3223 
3224  const MAX_HISTORY_MENU_ITEMS = 15;
3225  var index = sessionHistory.index;
3226  var half_length = Math.floor(MAX_HISTORY_MENU_ITEMS / 2);
3227  var start = Math.max(index - half_length, 0);
3228  var end = Math.min(start == 0 ? MAX_HISTORY_MENU_ITEMS : index + half_length + 1, count);
3229  if (end == count)
3230  start = Math.max(count - MAX_HISTORY_MENU_ITEMS, 0);
3231 
3232  var tooltipBack = gNavigatorBundle.getString("tabHistory.goBack");
3233  var tooltipCurrent = gNavigatorBundle.getString("tabHistory.current");
3234  var tooltipForward = gNavigatorBundle.getString("tabHistory.goForward");
3235 
3236  for (var j = end - 1; j >= start; j--) {
3237  let item = document.createElement("menuitem");
3238  let entry = sessionHistory.getEntryAtIndex(j, false);
3239  let uri = entry.URI.spec;
3240 
3241  item.setAttribute("uri", uri);
3242  item.setAttribute("label", entry.title || uri);
3243  item.setAttribute("index", j);
3244 
3245  if (j != index) {
3246  try {
3247  let iconURL = Cc["@mozilla.org/browser/favicon-service;1"]
3248  .getService(Ci.nsIFaviconService)
3249  .getFaviconForPage(entry.URI).spec;
3250  item.style.listStyleImage = "url(" + iconURL + ")";
3251  } catch (ex) {}
3252  }
3253 
3254  if (j < index) {
3255  item.className = "unified-nav-back menuitem-iconic";
3256  item.setAttribute("tooltiptext", tooltipBack);
3257  } else if (j == index) {
3258  item.setAttribute("type", "radio");
3259  item.setAttribute("checked", "true");
3260  item.className = "unified-nav-current";
3261  item.setAttribute("tooltiptext", tooltipCurrent);
3262  } else {
3263  item.className = "unified-nav-forward menuitem-iconic";
3264  item.setAttribute("tooltiptext", tooltipForward);
3265  }
3266 
3267  aParent.appendChild(item);
3268  }
3269  return true;
3270 }
3271 
3272 function addToUrlbarHistory(aUrlToAdd) {
3273  if (aUrlToAdd &&
3274  aUrlToAdd.indexOf(" ") == -1 &&
3275  !/[\x00-\x1F]/.test(aUrlToAdd))
3276  PlacesUIUtils.markPageAsTyped(aUrlToAdd);
3277 }
3278 
3279 function toJavaScriptConsole()
3280 {
3281  toOpenWindowByType("global:console", "chrome://global/content/console.xul");
3282 }
3283 
3284 function BrowserDownloadsUI()
3285 {
3286  Cc["@mozilla.org/download-manager-ui;1"].
3287  getService(Ci.nsIDownloadManagerUI).show(window);
3288 }
3289 
3290 function toOpenWindowByType(inType, uri, features)
3291 {
3292  var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
3293  var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
3294  var topWindow = windowManagerInterface.getMostRecentWindow(inType);
3295 
3296  if (topWindow)
3297  topWindow.focus();
3298  else if (features)
3299  window.open(uri, "_blank", features);
3300  else
3301  window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
3302 }
3303 
3304 function toOpenDialogByTypeAndUrl(inType, relatedUrl, windowUri, features, extraArgument)
3305 {
3306  var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
3307  var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
3308  var windows = windowManagerInterface.getEnumerator(inType);
3309 
3310  // Check for windows matching the url
3311  while (windows.hasMoreElements()) {
3312  var currentWindow = windows.getNext();
3313  if (currentWindow.document.documentElement.getAttribute("relatedUrl") == relatedUrl) {
3314  currentWindow.focus();
3315  return;
3316  }
3317  }
3318 
3319  // We didn't find a matching window, so open a new one.
3320  if (features)
3321  return window.openDialog(windowUri, "_blank", features, extraArgument);
3322 
3323  return window.openDialog(windowUri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar", extraArgument);
3324 }
3325 
3326 function OpenBrowserWindow()
3327 {
3328  var charsetArg = new String();
3329  var handler = Components.classes["@mozilla.org/browser/clh;1"]
3330  .getService(Components.interfaces.nsIBrowserHandler);
3331  var defaultArgs = handler.defaultArgs;
3332  var wintype = document.documentElement.getAttribute('windowtype');
3333 
3334  // if and only if the current window is a browser window and it has a document with a character
3335  // set, then extract the current charset menu setting from the current document and use it to
3336  // initialize the new browser window...
3337  var win;
3338  if (window && (wintype == "navigator:browser") && window.content && window.content.document)
3339  {
3340  var DocCharset = window.content.document.characterSet;
3341  charsetArg = "charset="+DocCharset;
3342 
3343  //we should "inherit" the charset menu setting in a new window
3344  win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no", defaultArgs, charsetArg);
3345  }
3346  else // forget about the charset information.
3347  {
3348  win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no", defaultArgs);
3349  }
3350 
3351  return win;
3352 }
3353 
3354 var gCustomizeSheet = false;
3355 // Returns a reference to the window in which the toolbar
3356 // customization document is loaded.
3358 {
3359  // Disable the toolbar context menu items
3360  var menubar = document.getElementById("main-menubar");
3361  for (var i = 0; i < menubar.childNodes.length; ++i)
3362  menubar.childNodes[i].setAttribute("disabled", true);
3363 
3364  var cmd = document.getElementById("cmd_CustomizeToolbars");
3365  cmd.setAttribute("disabled", "true");
3366 
3367  var splitter = document.getElementById("urlbar-search-splitter");
3368  if (splitter)
3369  splitter.parentNode.removeChild(splitter);
3370 
3371  var customizeURL = "chrome://global/content/customizeToolbar.xul";
3372  gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
3373 
3374  if (gCustomizeSheet) {
3375  var sheetFrame = document.getElementById("customizeToolbarSheetIFrame");
3376  sheetFrame.hidden = false;
3377  sheetFrame.toolbox = gNavToolbox;
3378 
3379  // The document might not have been loaded yet, if this is the first time.
3380  // If it is already loaded, reload it so that the onload initialization code
3381  // re-runs.
3382  if (sheetFrame.getAttribute("src") == customizeURL)
3383  sheetFrame.contentWindow.location.reload()
3384  else
3385  sheetFrame.setAttribute("src", customizeURL);
3386 
3387  // XXXmano: there's apparently no better way to get this when the iframe is
3388  // hidden
3389  var sheetWidth = sheetFrame.style.width.match(/([0-9]+)px/)[1];
3390  document.getElementById("customizeToolbarSheetPopup")
3391  .openPopup(gNavToolbox, "after_start",
3392  (window.innerWidth - sheetWidth) / 2, 0);
3393 
3394  return sheetFrame.contentWindow;
3395  } else {
3396  return window.openDialog(customizeURL,
3397  "CustomizeToolbar",
3398  "chrome,titlebar,toolbar,location,resizable,dependent",
3399  gNavToolbox);
3400  }
3401 }
3402 
3403 function BrowserToolboxCustomizeDone(aToolboxChanged) {
3404  if (gCustomizeSheet) {
3405  document.getElementById("customizeToolbarSheetIFrame").hidden = true;
3406  document.getElementById("customizeToolbarSheetPopup").hidePopup();
3407  }
3408 
3409  // Update global UI elements that may have been added or removed
3410  if (aToolboxChanged) {
3411  gURLBar = document.getElementById("urlbar");
3412  if (gURLBar)
3413  gURLBar.emptyText = gURLBarEmptyText.value;
3414 
3415  gProxyFavIcon = document.getElementById("page-proxy-favicon");
3416  gHomeButton.updateTooltip();
3417  gIdentityHandler._cacheElements();
3418  window.XULBrowserWindow.init();
3419 
3420  var backForwardDropmarker = document.getElementById("back-forward-dropmarker");
3421  if (backForwardDropmarker)
3422  backForwardDropmarker.disabled =
3423  document.getElementById('Browser:Back').hasAttribute('disabled') &&
3424  document.getElementById('Browser:Forward').hasAttribute('disabled');
3425 
3426  // support downgrading to Firefox 2.0
3427  var navBar = document.getElementById("nav-bar");
3428  navBar.setAttribute("currentset",
3429  navBar.getAttribute("currentset")
3430  .replace("unified-back-forward-button",
3431  "unified-back-forward-button,back-button,forward-button"));
3432  document.persist(navBar.id, "currentset");
3433 
3434 #ifndef XP_MACOSX
3436 #endif
3437  }
3438 
3440 
3441  gHomeButton.updatePersonalToolbarStyle();
3442 
3443  // Update the urlbar
3444  if (gURLBar) {
3445  URLBarSetURI();
3446  XULBrowserWindow.asyncUpdateUI();
3447  PlacesStarButton.updateState();
3448  }
3449 
3450  // Re-enable parts of the UI we disabled during the dialog
3451  var menubar = document.getElementById("main-menubar");
3452  for (var i = 0; i < menubar.childNodes.length; ++i)
3453  menubar.childNodes[i].setAttribute("disabled", false);
3454  var cmd = document.getElementById("cmd_CustomizeToolbars");
3455  cmd.removeAttribute("disabled");
3456 
3457 #ifdef XP_MACOSX
3458  // make sure to re-enable click-and-hold
3459  if (!getBoolPref("ui.click_hold_context_menus", false))
3460  SetClickAndHoldHandlers();
3461 #endif
3462 
3463  // XXX Shouldn't have to do this, but I do
3464  if (!gCustomizeSheet)
3465  window.focus();
3466 
3467 }
3468 
3470  gHomeButton.updatePersonalToolbarStyle();
3471 }
3472 
3494 {
3495 #ifndef XP_MACOSX
3496  let editMenuPopupState = document.getElementById("menu_EditPopup").state;
3497  let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
3498  let placesContextMenuPopupState = document.getElementById("placesContext").state;
3499 
3500  // The UI is visible if the Edit menu is opening or open, if the context menu
3501  // is open, or if the toolbar has been customized to include the Cut, Copy,
3502  // or Paste toolbar buttons.
3503  gEditUIVisible = editMenuPopupState == "showing" ||
3504  editMenuPopupState == "open" ||
3505  contextMenuPopupState == "showing" ||
3506  contextMenuPopupState == "open" ||
3507  placesContextMenuPopupState == "showing" ||
3508  placesContextMenuPopupState == "open" ||
3509  document.getElementById("cut-button") ||
3510  document.getElementById("copy-button") ||
3511  document.getElementById("paste-button") ? true : false;
3512 
3513  // If UI is visible, update the edit commands' enabled state to reflect
3514  // whether or not they are actually enabled for the current focus/selection.
3515  if (gEditUIVisible)
3516  goUpdateGlobalEditMenuItems();
3517 
3518  // Otherwise, enable all commands, so that keyboard shortcuts still work,
3519  // then lazily determine their actual enabled state when the user presses
3520  // a keyboard shortcut.
3521  else {
3522  goSetCommandEnabled("cmd_undo", true);
3523  goSetCommandEnabled("cmd_redo", true);
3524  goSetCommandEnabled("cmd_cut", true);
3525  goSetCommandEnabled("cmd_copy", true);
3526  goSetCommandEnabled("cmd_paste", true);
3527  goSetCommandEnabled("cmd_selectAll", true);
3528  goSetCommandEnabled("cmd_delete", true);
3529  goSetCommandEnabled("cmd_switchTextDirection", true);
3530  }
3531 #endif
3532 }
3533 
3535 {
3536  _XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
3537  toggle: function()
3538  {
3539  // show/hide all menubars, toolbars, and statusbars (except the full screen toolbar)
3540  this.showXULChrome("toolbar", window.fullScreen);
3541  this.showXULChrome("statusbar", window.fullScreen);
3542  document.getElementById("View:FullScreen").setAttribute("checked", !window.fullScreen);
3543 
3544  var fullScrToggler = document.getElementById("fullscr-toggler");
3545  if (!window.fullScreen) {
3546  // Add a tiny toolbar to receive mouseover and dragenter events, and provide affordance.
3547  // This will help simulate the "collapse" metaphor while also requiring less code and
3548  // events than raw listening of mouse coords.
3549  if (!fullScrToggler) {
3550  fullScrToggler = document.createElement("toolbar");
3551  fullScrToggler.id = "fullscr-toggler";
3552  fullScrToggler.setAttribute("customizable", "false");
3553  fullScrToggler.setAttribute("moz-collapsed", "true");
3554  var navBar = document.getElementById("nav-bar");
3555  navBar.parentNode.insertBefore(fullScrToggler, navBar);
3556  }
3557  fullScrToggler.addEventListener("mouseover", this._expandCallback, false);
3558  fullScrToggler.addEventListener("dragenter", this._expandCallback, false);
3559 
3560  if (gPrefService.getBoolPref("browser.fullscreen.autohide"))
3561  gBrowser.mPanelContainer.addEventListener("mousemove",
3562  this._collapseCallback, false);
3563 
3564  document.addEventListener("keypress", this._keyToggleCallback, false);
3565  document.addEventListener("popupshown", this._setPopupOpen, false);
3566  document.addEventListener("popuphidden", this._setPopupOpen, false);
3567  this._shouldAnimate = true;
3568  this.mouseoverToggle(false);
3569 
3570  // Autohide prefs
3571  gPrefService.addObserver("browser.fullscreen", this, false);
3572  }
3573  else {
3574  document.removeEventListener("keypress", this._keyToggleCallback, false);
3575  document.removeEventListener("popupshown", this._setPopupOpen, false);
3576  document.removeEventListener("popuphidden", this._setPopupOpen, false);
3577  gPrefService.removeObserver("browser.fullscreen", this);
3578 
3579  if (fullScrToggler) {
3580  fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
3581  fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
3582  }
3583 
3584  // The user may quit fullscreen during an animation
3585  clearInterval(this._animationInterval);
3586  clearTimeout(this._animationTimeout);
3587  gNavToolbox.style.marginTop = "0px";
3588  if (this._isChromeCollapsed)
3589  this.mouseoverToggle(true);
3590  this._isAnimating = false;
3591  // This is needed if they use the context menu to quit fullscreen
3592  this._isPopupOpen = false;
3593 
3594  gBrowser.mPanelContainer.removeEventListener("mousemove",
3595  this._collapseCallback, false);
3596  }
3597  },
3598 
3599  observe: function(aSubject, aTopic, aData)
3600  {
3601  if (aData == "browser.fullscreen.autohide") {
3602  if (gPrefService.getBoolPref("browser.fullscreen.autohide")) {
3603  gBrowser.mPanelContainer.addEventListener("mousemove",
3604  this._collapseCallback, false);
3605  }
3606  else {
3607  gBrowser.mPanelContainer.removeEventListener("mousemove",
3608  this._collapseCallback, false);
3609  }
3610  }
3611  },
3612 
3613  // Event callbacks
3614  _expandCallback: function()
3615  {
3616  FullScreen.mouseoverToggle(true);
3617  },
3618  _collapseCallback: function()
3619  {
3620  FullScreen.mouseoverToggle(false);
3621  },
3622  _keyToggleCallback: function(aEvent)
3623  {
3624  // if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we
3625  // should provide a way to collapse them too.
3626  if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
3627  FullScreen._shouldAnimate = false;
3628  FullScreen.mouseoverToggle(false, true);
3629  }
3630  // F6 is another shortcut to the address bar, but its not covered in OpenLocation()
3631  else if (aEvent.keyCode == aEvent.DOM_VK_F6)
3632  FullScreen.mouseoverToggle(true);
3633  },
3634 
3635  // Checks whether we are allowed to collapse the chrome
3636  _isPopupOpen: false,
3637  _isChromeCollapsed: false,
3638  _safeToCollapse: function(forceHide)
3639  {
3640  if (!gPrefService.getBoolPref("browser.fullscreen.autohide"))
3641  return false;
3642 
3643  // a popup menu is open in chrome: don't collapse chrome
3644  if (!forceHide && this._isPopupOpen)
3645  return false;
3646 
3647  // a textbox in chrome is focused (location bar anyone?): don't collapse chrome
3648  if (document.commandDispatcher.focusedElement &&
3649  document.commandDispatcher.focusedElement.ownerDocument == document &&
3650  document.commandDispatcher.focusedElement.localName == "input") {
3651  if (forceHide)
3652  // hidden textboxes that still have focus are bad bad bad
3653  document.commandDispatcher.focusedElement.blur();
3654  else
3655  return false;
3656  }
3657  return true;
3658  },
3659 
3660  _setPopupOpen: function(aEvent)
3661  {
3662  // Popups should only veto chrome collapsing if they were opened when the chrome was not collapsed.
3663  // Otherwise, they would not affect chrome and the user would expect the chrome to go away.
3664  // e.g. we wouldn't want the autoscroll icon firing this event, so when the user
3665  // toggles chrome when moving mouse to the top, it doesn't go away again.
3666  if (aEvent.type == "popupshown" && !FullScreen._isChromeCollapsed &&
3667  aEvent.target.localName != "tooltip" && aEvent.target.localName != "window")
3668  FullScreen._isPopupOpen = true;
3669  else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" &&
3670  aEvent.target.localName != "window")
3671  FullScreen._isPopupOpen = false;
3672  },
3673 
3674  // Autohide helpers for the context menu item
3675  getAutohide: function(aItem)
3676  {
3677  aItem.setAttribute("checked", gPrefService.getBoolPref("browser.fullscreen.autohide"));
3678  },
3679  setAutohide: function()
3680  {
3681  gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide"));
3682  },
3683 
3684  // Animate the toolbars disappearing
3685  _shouldAnimate: true,
3686  _isAnimating: false,
3687  _animationTimeout: null,
3688  _animationInterval: null,
3689  _animateUp: function()
3690  {
3691  // check again, the user may have done something before the animation was due to start
3692  if (!window.fullScreen || !FullScreen._safeToCollapse(false)) {
3693  FullScreen._isAnimating = false;
3694  FullScreen._shouldAnimate = true;
3695  return;
3696  }
3697 
3698  var animateFrameAmount = 2;
3699  function animateUpFrame() {
3700  animateFrameAmount *= 2;
3701  if (animateFrameAmount >=
3702  (gNavToolbox.boxObject.height + gBrowser.mStrip.boxObject.height)) {
3703  // We've animated enough
3704  clearInterval(FullScreen._animationInterval);
3705  gNavToolbox.style.marginTop = "0px";
3706  FullScreen._isAnimating = false;
3707  FullScreen._shouldAnimate = false; // Just to make sure
3708  FullScreen.mouseoverToggle(false);
3709  return;
3710  }
3711  gNavToolbox.style.marginTop = (animateFrameAmount * -1) + "px";
3712  }
3713 
3714  FullScreen._animationInterval = setInterval(animateUpFrame, 70);
3715  },
3716 
3717  mouseoverToggle: function(aShow, forceHide)
3718  {
3719  // Don't do anything if:
3720  // a) we're already in the state we want,
3721  // b) we're animating and will become collapsed soon, or
3722  // c) we can't collapse because it would be undesirable right now
3723  if (aShow != this._isChromeCollapsed || (!aShow && this._isAnimating) ||
3724  (!aShow && !this._safeToCollapse(forceHide)))
3725  return;
3726 
3727  // browser.fullscreen.animateUp
3728  // 0 - never animate up
3729  // 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
3730  // 2 - animate every time it collapses
3731  if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0)
3732  this._shouldAnimate = false;
3733 
3734  if (!aShow && this._shouldAnimate) {
3735  this._isAnimating = true;
3736  this._shouldAnimate = false;
3737  this._animationTimeout = setTimeout(this._animateUp, 800);
3738  return;
3739  }
3740 
3741  // The chrome is collapsed so don't spam needless mousemove events
3742  if (aShow) {
3743  gBrowser.mPanelContainer.addEventListener("mousemove",
3744  this._collapseCallback, false);
3745  }
3746  else {
3747  gBrowser.mPanelContainer.removeEventListener("mousemove",
3748  this._collapseCallback, false);
3749  }
3750 
3751  gBrowser.mStrip.setAttribute("moz-collapsed", !aShow);
3752  var allFSToolbars = document.getElementsByTagNameNS(this._XULNS, "toolbar");
3753  for (var i = 0; i < allFSToolbars.length; i++) {
3754  if (allFSToolbars[i].getAttribute("fullscreentoolbar") == "true")
3755  allFSToolbars[i].setAttribute("moz-collapsed", !aShow);
3756  }
3757  document.getElementById("fullscr-toggler").setAttribute("moz-collapsed", aShow);
3758  this._isChromeCollapsed = !aShow;
3759  if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2)
3760  this._shouldAnimate = true;
3761  },
3762 
3763  showXULChrome: function(aTag, aShow)
3764  {
3765  var els = document.getElementsByTagNameNS(this._XULNS, aTag);
3766 
3767  for (var i = 0; i < els.length; ++i) {
3768  // XXX don't interfere with previously collapsed toolbars
3769  if (els[i].getAttribute("fullscreentoolbar") == "true") {
3770  if (!aShow) {
3771 
3772  var toolbarMode = els[i].getAttribute("mode");
3773  if (toolbarMode != "text") {
3774  els[i].setAttribute("saved-mode", toolbarMode);
3775  els[i].setAttribute("saved-iconsize",
3776  els[i].getAttribute("iconsize"));
3777  els[i].setAttribute("mode", "icons");
3778  els[i].setAttribute("iconsize", "small");
3779  }
3780 
3781  // Give the main nav bar the fullscreen context menu, otherwise remove it
3782  // to prevent breakage
3783  els[i].setAttribute("saved-context",
3784  els[i].getAttribute("context"));
3785  if (els[i].id == "nav-bar")
3786  els[i].setAttribute("context", "autohide-context");
3787  else
3788  els[i].removeAttribute("context");
3789 
3790  // Set the inFullscreen attribute to allow specific styling
3791  // in fullscreen mode
3792  els[i].setAttribute("inFullscreen", true);
3793  }
3794  else {
3795  function restoreAttr(attrName) {
3796  var savedAttr = "saved-" + attrName;
3797  if (els[i].hasAttribute(savedAttr)) {
3798  els[i].setAttribute(attrName, els[i].getAttribute(savedAttr));
3799  els[i].removeAttribute(savedAttr);
3800  }
3801  }
3802 
3803  restoreAttr("mode");
3804  restoreAttr("iconsize");
3805  restoreAttr("context");
3806 
3807  els[i].removeAttribute("inFullscreen");
3808  }
3809  } else {
3810  // use moz-collapsed so it doesn't persist hidden/collapsed,
3811  // so that new windows don't have missing toolbars
3812  if (aShow)
3813  els[i].removeAttribute("moz-collapsed");
3814  else
3815  els[i].setAttribute("moz-collapsed", "true");
3816  }
3817  }
3818 
3819  if (aShow)
3820  gNavToolbox.removeAttribute("inFullscreen");
3821  else
3822  gNavToolbox.setAttribute("inFullscreen", true);
3823 
3824  var controls = document.getElementsByAttribute("fullscreencontrol", "true");
3825  for (var i = 0; i < controls.length; ++i)
3826  controls[i].hidden = aShow;
3827  }
3828 };
3829 
3839 function mimeTypeIsTextBased(aMimeType)
3840 {
3841  return /^text\/|\+xml$/.test(aMimeType) ||
3842  aMimeType == "application/x-javascript" ||
3843  aMimeType == "application/javascript" ||
3844  aMimeType == "application/xml" ||
3845  aMimeType == "mozilla.application/cached-xul";
3846 }
3847 
3849  // Stored Status, Link and Loading values
3850  status: "",
3851  defaultStatus: "",
3852  jsStatus: "",
3853  jsDefaultStatus: "",
3854  overLink: "",
3855  startTime: 0,
3856  statusText: "",
3857  lastURI: null,
3858  isBusy: false,
3859 
3860  statusTimeoutInEffect: false,
3861 
3862  QueryInterface: function (aIID) {
3863  if (aIID.equals(Ci.nsIWebProgressListener) ||
3864  aIID.equals(Ci.nsIWebProgressListener2) ||
3865  aIID.equals(Ci.nsISupportsWeakReference) ||
3866  aIID.equals(Ci.nsIXULBrowserWindow) ||
3867  aIID.equals(Ci.nsISupports))
3868  return this;
3869  throw Cr.NS_NOINTERFACE;
3870  },
3871 
3872  get statusMeter () {
3873  delete this.statusMeter;
3874  return this.statusMeter = document.getElementById("statusbar-icon");
3875  },
3876  get stopCommand () {
3877  delete this.stopCommand;
3878  return this.stopCommand = document.getElementById("Browser:Stop");
3879  },
3880  get reloadCommand () {
3881  delete this.reloadCommand;
3882  return this.reloadCommand = document.getElementById("Browser:Reload");
3883  },
3884  get statusTextField () {
3885  delete this.statusTextField;
3886  return this.statusTextField = document.getElementById("statusbar-display");
3887  },
3888  get securityButton () {
3889  delete this.securityButton;
3890  return this.securityButton = document.getElementById("security-button");
3891  },
3892  get isImage () {
3893  delete this.isImage;
3894  return this.isImage = document.getElementById("isImage");
3895  },
3896  get _uriFixup () {
3897  delete this._uriFixup;
3898  return this._uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
3899  .getService(Ci.nsIURIFixup);
3900  },
3901 
3902  init: function () {
3903  this.throbberElement = document.getElementById("navigator-throbber");
3904 
3905  // Initialize the security button's state and tooltip text. Remember to reset
3906  // _hostChanged, otherwise onSecurityChange will short circuit.
3907  var securityUI = gBrowser.securityUI;
3908  this._hostChanged = true;
3909  this.onSecurityChange(null, null, securityUI.state);
3910  },
3911 
3912  destroy: function () {
3913  // XXXjag to avoid leaks :-/, see bug 60729
3914  delete this.throbberElement;
3915  delete this.statusMeter;
3916  delete this.stopCommand;
3917  delete this.reloadCommand;
3918  delete this.statusTextField;
3919  delete this.securityButton;
3920  delete this.statusText;
3921  delete this.lastURI;
3922  },
3923 
3924  setJSStatus: function (status) {
3925  this.jsStatus = status;
3926  this.updateStatusField();
3927  },
3928 
3929  setJSDefaultStatus: function (status) {
3930  this.jsDefaultStatus = status;
3931  this.updateStatusField();
3932  },
3933 
3934  setDefaultStatus: function (status) {
3935  this.defaultStatus = status;
3936  this.updateStatusField();
3937  },
3938 
3939  setOverLink: function (link, b) {
3940  // Encode bidirectional formatting characters.
3941  // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
3942  this.overLink = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
3944  this.updateStatusField();
3945  },
3946 
3947  updateStatusField: function () {
3948  var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
3949 
3950  // check the current value so we don't trigger an attribute change
3951  // and cause needless (slow!) UI updates
3952  if (this.statusText != text) {
3953  this.statusTextField.label = text;
3954  this.statusText = text;
3955  }
3956  },
3957 
3958  onLinkIconAvailable: function (aBrowser) {
3959  if (gProxyFavIcon && gBrowser.userTypedValue === null)
3960  PageProxySetIcon(aBrowser.mIconURL); // update the favicon in the URL bar
3961  },
3962 
3963  onProgressChange: function (aWebProgress, aRequest,
3964  aCurSelfProgress, aMaxSelfProgress,
3965  aCurTotalProgress, aMaxTotalProgress) {
3966  // Check this._busyUI to be safe, because we don't want to update
3967  // the progress meter when restoring a page from bfcache.
3968  if (aMaxTotalProgress > 0 && this._busyUI) {
3969  // This is highly optimized. Don't touch this code unless
3970  // you are intimately familiar with the cost of setting
3971  // attrs on XUL elements. -- hyatt
3972  let percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
3973  this.statusMeter.value = percentage;
3974  }
3975  },
3976 
3977  onProgressChange64: function (aWebProgress, aRequest,
3978  aCurSelfProgress, aMaxSelfProgress,
3979  aCurTotalProgress, aMaxTotalProgress) {
3980  return this.onProgressChange(aWebProgress, aRequest,
3981  aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress,
3982  aMaxTotalProgress);
3983  },
3984 
3985  onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
3986  const nsIWebProgressListener = Ci.nsIWebProgressListener;
3987  const nsIChannel = Ci.nsIChannel;
3988  if (aStateFlags & nsIWebProgressListener.STATE_START) {
3989  // This (thanks to the filter) is a network start or the first
3990  // stray request (the first request outside of the document load),
3991  // initialize the throbber and his friends.
3992 
3993  // Call start document load listeners (only if this is a network load)
3994  if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK &&
3995  aRequest && aWebProgress.DOMWindow == content)
3996  this.startDocumentLoad(aRequest);
3997 
3998  this.isBusy = true;
3999 
4000  if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
4001  this._busyUI = true;
4002 
4003  // Turn the throbber on.
4004  if (this.throbberElement)
4005  this.throbberElement.setAttribute("busy", "true");
4006 
4007  // Turn the status meter on.
4008  this.statusMeter.value = 0; // be sure to clear the progress bar
4009  if (gProgressCollapseTimer) {
4010  window.clearTimeout(gProgressCollapseTimer);
4011  gProgressCollapseTimer = null;
4012  }
4013  else
4014  this.statusMeter.parentNode.collapsed = false;
4015 
4016  // XXX: This needs to be based on window activity...
4017  this.stopCommand.removeAttribute("disabled");
4018  }
4019  }
4020  else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
4021  if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
4022  if (aWebProgress.DOMWindow == content) {
4023  if (aRequest)
4024  this.endDocumentLoad(aRequest, aStatus);
4025  if (!gBrowser.mTabbedMode && !gBrowser.mCurrentBrowser.mIconURL)
4026  gBrowser.useDefaultIcon(gBrowser.mCurrentTab);
4027  }
4028  }
4029 
4030  // This (thanks to the filter) is a network stop or the last
4031  // request stop outside of loading the document, stop throbbers
4032  // and progress bars and such
4033  if (aRequest) {
4034  let msg = "";
4035  let location;
4036  // Get the URI either from a channel or a pseudo-object
4037  if (aRequest instanceof nsIChannel || "URI" in aRequest) {
4038  location = aRequest.URI;
4039 
4040  // For keyword URIs clear the user typed value since they will be changed into real URIs
4041  if (location.scheme == "keyword" && aWebProgress.DOMWindow == content)
4042  gBrowser.userTypedValue = null;
4043 
4044  if (location.spec != "about:blank") {
4045  switch (aStatus) {
4046  case Components.results.NS_BINDING_ABORTED:
4047  msg = gNavigatorBundle.getString("nv_stopped");
4048  break;
4049  case Components.results.NS_ERROR_NET_TIMEOUT:
4050  msg = gNavigatorBundle.getString("nv_timeout");
4051  break;
4052  }
4053  }
4054  }
4055  // If msg is false then we did not have an error (channel may have
4056  // been null, in the case of a stray image load).
4057  if (!msg && (!location || location.spec != "about:blank"))
4058  msg = gNavigatorBundle.getString("nv_done");
4059 
4060  this.status = "";
4061  this.setDefaultStatus(msg);
4062 
4063  // Disable menu entries for images, enable otherwise
4064  if (content.document && mimeTypeIsTextBased(content.document.contentType))
4065  this.isImage.removeAttribute('disabled');
4066  else
4067  this.isImage.setAttribute('disabled', 'true');
4068  }
4069 
4070  this.isBusy = false;
4071 
4072  if (this._busyUI) {
4073  this._busyUI = false;
4074 
4075  // Turn the progress meter and throbber off.
4076  gProgressCollapseTimer = window.setTimeout(function () {
4077  gProgressMeterPanel.collapsed = true;
4078  gProgressCollapseTimer = null;
4079  }, 100);
4080 
4081  if (this.throbberElement)
4082  this.throbberElement.removeAttribute("busy");
4083 
4084  this.stopCommand.setAttribute("disabled", "true");
4085  }
4086  }
4087  },
4088 
4089  onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
4090  var location = aLocationURI ? aLocationURI.spec : "";
4091  this._hostChanged = true;
4092 
4093  if (document.tooltipNode) {
4094  // Optimise for the common case
4095  if (aWebProgress.DOMWindow == content) {
4096  document.getElementById("aHTMLTooltip").hidePopup();
4097  document.tooltipNode = null;
4098  }
4099  else {
4100  for (let tooltipWindow =
4101  document.tooltipNode.ownerDocument.defaultView;
4102  tooltipWindow != tooltipWindow.parent;
4103  tooltipWindow = tooltipWindow.parent) {
4104  if (tooltipWindow == aWebProgress.DOMWindow) {
4105  document.getElementById("aHTMLTooltip").hidePopup();
4106  document.tooltipNode = null;
4107  break;
4108  }
4109  }
4110  }
4111  }
4112 
4113  // This code here does not compare uris exactly when determining
4114  // whether or not the message should be hidden since the message
4115  // may be prematurely hidden when an install is invoked by a click
4116  // on a link that looks like this:
4117  //
4118  // <a href="#" onclick="return install();">Install Foo</a>
4119  //
4120  // - which fires a onLocationChange message to uri + '#'...
4121  var selectedBrowser = gBrowser.selectedBrowser;
4122  if (selectedBrowser.lastURI) {
4123  let oldSpec = selectedBrowser.lastURI.spec;
4124  let oldIndexOfHash = oldSpec.indexOf("#");
4125  if (oldIndexOfHash != -1)
4126  oldSpec = oldSpec.substr(0, oldIndexOfHash);
4127  let newSpec = location;
4128  let newIndexOfHash = newSpec.indexOf("#");
4129  if (newIndexOfHash != -1)
4130  newSpec = newSpec.substr(0, newSpec.indexOf("#"));
4131  if (newSpec != oldSpec) {
4132  // Remove all the notifications, except for those which want to
4133  // persist across the first location change.
4134  let nBox = gBrowser.getNotificationBox(selectedBrowser);
4135  nBox.removeTransientNotifications();
4136  }
4137  }
4138  selectedBrowser.lastURI = aLocationURI;
4139 
4140  // Disable menu entries for images, enable otherwise
4141  if (content.document && mimeTypeIsTextBased(content.document.contentType))
4142  this.isImage.removeAttribute('disabled');
4143  else
4144  this.isImage.setAttribute('disabled', 'true');
4145 
4146  this.setOverLink("", null);
4147 
4148  // We should probably not do this if the value has changed since the user
4149  // searched
4150  // Update urlbar only if a new page was loaded on the primary content area
4151  // Do not update urlbar if there was a subframe navigation
4152 
4153  var browser = gBrowser.selectedBrowser;
4154  if (aWebProgress.DOMWindow == content) {
4155  if ((location == "about:blank" && !content.opener) ||
4156  location == "") { // Second condition is for new tabs, otherwise
4157  // reload function is enabled until tab is refreshed.
4158  this.reloadCommand.setAttribute("disabled", "true");
4159  } else {
4160  this.reloadCommand.removeAttribute("disabled");
4161  }
4162 
4163  if (!gBrowser.mTabbedMode && aWebProgress.isLoadingDocument)
4164  gBrowser.setIcon(gBrowser.mCurrentTab, null);
4165 
4166  if (gURLBar) {
4167  // Strip off "wyciwyg://" and passwords for the location bar
4168  let uri = aLocationURI;
4169  try {
4170  uri = this._uriFixup.createExposableURI(uri);
4171  } catch (e) {}
4172  URLBarSetURI(uri, true);
4173 
4174  // Update starring UI
4175  PlacesStarButton.updateState();
4176  }
4177  }
4178  UpdateBackForwardCommands(gBrowser.webNavigation);
4179 
4180  if (gFindBar.findMode != gFindBar.FIND_NORMAL) {
4181  // Close the Find toolbar if we're in old-style TAF mode
4182  gFindBar.close();
4183  }
4184 
4185  // XXXmano new-findbar, do something useful once it lands.
4186  // Of course, this is especially wrong with bfcache on...
4187 
4188  // fix bug 253793 - turn off highlight when page changes
4189  gFindBar.getElement("highlight").checked = false;
4190 
4191  // See bug 358202, when tabs are switched during a drag operation,
4192  // timers don't fire on windows (bug 203573)
4193  if (aRequest)
4194  setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0);
4195  else
4196  this.asyncUpdateUI();
4197  },
4198 
4199  asyncUpdateUI: function () {
4200  FeedHandler.updateFeeds();
4201  BrowserSearch.updateSearchButton();
4202  },
4203 
4204  onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
4205  this.status = aMessage;
4206  this.updateStatusField();
4207  },
4208 
4209  // Properties used to cache security state used to update the UI
4210  _state: null,
4211  _tooltipText: null,
4212  _hostChanged: false, // onLocationChange will flip this bit
4213 
4214  onSecurityChange: function (aWebProgress, aRequest, aState) {
4215  // Don't need to do anything if the data we use to update the UI hasn't
4216  // changed
4217  if (this._state == aState &&
4218  this._tooltipText == gBrowser.securityUI.tooltipText &&
4219  !this._hostChanged) {
4220 #ifdef DEBUG
4221  try {
4222  var contentHost = gBrowser.contentWindow.location.host;
4223  if (this._host !== undefined && this._host != contentHost) {
4224  Components.utils.reportError(
4225  "ASSERTION: browser.js host is inconsistent. Content window has " +
4226  "<" + contentHost + "> but cached host is <" + this._host + ">.\n"
4227  );
4228  }
4229  } catch (ex) {}
4230 #endif
4231  return;
4232  }
4233  this._state = aState;
4234 
4235 #ifdef DEBUG
4236  try {
4237  this._host = gBrowser.contentWindow.location.host;
4238  } catch(ex) {
4239  this._host = null;
4240  }
4241 #endif
4242 
4243  this._hostChanged = false;
4244  this._tooltipText = gBrowser.securityUI.tooltipText
4245 
4246  // aState is defined as a bitmask that may be extended in the future.
4247  // We filter out any unknown bits before testing for known values.
4248  const wpl = Components.interfaces.nsIWebProgressListener;
4249  const wpl_security_bits = wpl.STATE_IS_SECURE |
4250  wpl.STATE_IS_BROKEN |
4251  wpl.STATE_IS_INSECURE |
4252  wpl.STATE_SECURE_HIGH |
4253  wpl.STATE_SECURE_MED |
4254  wpl.STATE_SECURE_LOW;
4255  var level;
4256 
4257  switch (this._state & wpl_security_bits) {
4258  case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
4259  level = "high";
4260  break;
4261  case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_MED:
4262  case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW:
4263  level = "low";
4264  break;
4265  case wpl.STATE_IS_BROKEN:
4266  level = "broken";
4267  break;
4268  }
4269 
4270  if (level) {
4271  this.securityButton.setAttribute("level", level);
4272  this.securityButton.hidden = false;
4273  // We don't style the Location Bar based on the the 'level' attribute
4274  // anymore, but still set it for third-party themes.
4275  if (gURLBar)
4276  gURLBar.setAttribute("level", level);
4277  } else {
4278  this.securityButton.hidden = true;
4279  this.securityButton.removeAttribute("level");
4280  if (gURLBar)
4281  gURLBar.removeAttribute("level");
4282  }
4283 
4284  this.securityButton.setAttribute("tooltiptext", this._tooltipText);
4285 
4286  // Don't pass in the actual location object, since it can cause us to
4287  // hold on to the window object too long. Just pass in the fields we
4288  // care about. (bug 424829)
4289  var location = gBrowser.contentWindow.location;
4290  var locationObj = {};
4291  try {
4292  locationObj.host = location.host;
4293  locationObj.hostname = location.hostname;
4294  locationObj.port = location.port;
4295  } catch (ex) {
4296  // Can sometimes throw if the URL being visited has no host/hostname,
4297  // e.g. about:blank. The _state for these pages means we won't need these
4298  // properties anyways, though.
4299  }
4300  gIdentityHandler.checkIdentity(this._state, locationObj);
4301  },
4302 
4303  // simulate all change notifications after switching tabs
4304  onUpdateCurrentBrowser: function (aStateFlags, aStatus, aMessage, aTotalProgress) {
4305  if (FullZoom.updateBackgroundTabs)
4306  FullZoom.onLocationChange(gBrowser.currentURI, true);
4307  var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
4308  var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP;
4309  // use a pseudo-object instead of a (potentially non-existing) channel for getting
4310  // a correct error message - and make sure that the UI is always either in
4311  // loading (STATE_START) or done (STATE_STOP) mode
4312  this.onStateChange(
4313  gBrowser.webProgress,
4314  { URI: gBrowser.currentURI },
4315  loadingDone ? nsIWebProgressListener.STATE_STOP : nsIWebProgressListener.STATE_START,
4316  aStatus
4317  );
4318  // status message and progress value are undefined if we're done with loading
4319  if (loadingDone)
4320  return;
4321  this.onStatusChange(gBrowser.webProgress, null, 0, aMessage);
4322  this.onProgressChange(gBrowser.webProgress, 0, 0, aTotalProgress, 1);
4323  },
4324 
4325  startDocumentLoad: function (aRequest) {
4326  // clear out feed data
4327  gBrowser.mCurrentBrowser.feeds = null;
4328 
4329  // clear out search-engine data
4330  gBrowser.mCurrentBrowser.engines = null;
4331 
4332  var uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
4333  var observerService = Cc["@mozilla.org/observer-service;1"]
4334  .getService(Ci.nsIObserverService);
4335 
4336  if (gURLBar &&
4337  gURLBar.value == "" &&
4338  getWebNavigation().currentURI.spec == "about:blank")
4339  URLBarSetURI(uri);
4340 
4341  try {
4342  observerService.notifyObservers(content, "StartDocumentLoad", uri.spec);
4343  } catch (e) {
4344  }
4345  },
4346 
4347  endDocumentLoad: function (aRequest, aStatus) {
4348  var urlStr = aRequest.QueryInterface(Ci.nsIChannel).originalURI.spec;
4349 
4350  var observerService = Cc["@mozilla.org/observer-service;1"]
4351  .getService(Ci.nsIObserverService);
4352 
4353  var notification = Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad";
4354  try {
4355  observerService.notifyObservers(content, notification, urlStr);
4356  } catch (e) {
4357  }
4358  }
4359 }
4360 
4361 var TabsProgressListener = {
4362  onProgressChange: function (aBrowser, aWebProgress, aRequest,
4363  aCurSelfProgress, aMaxSelfProgress,
4364  aCurTotalProgress, aMaxTotalProgress) {
4365  },
4366 
4367  onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
4368 #ifdef MOZ_CRASHREPORTER
4369  if (aRequest instanceof Ci.nsIChannel &&
4370  aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
4371  aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
4372  gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
4373  }
4374 #endif
4375  },
4376 
4377  onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
4378  // Filter out any sub-frame loads
4379  if (aBrowser.contentWindow == aWebProgress.DOMWindow)
4380  FullZoom.onLocationChange(aLocationURI, false, aBrowser);
4381  },
4382 
4383  onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
4384  },
4385 
4386  onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
4387  if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
4388  let brandBundle = document.getElementById("bundle_brand");
4389  let brandShortName = brandBundle.getString("brandShortName");
4390  let refreshButtonText =
4391  gNavigatorBundle.getString("refreshBlocked.goButton");
4392  let refreshButtonAccesskey =
4393  gNavigatorBundle.getString("refreshBlocked.goButton.accesskey");
4394  let message =
4395  gNavigatorBundle.getFormattedString(aSameURI ? "refreshBlocked.refreshLabel"
4396  : "refreshBlocked.redirectLabel",
4397  [brandShortName]);
4398  let docShell = aWebProgress.DOMWindow
4399  .QueryInterface(Ci.nsIInterfaceRequestor)
4400  .getInterface(Ci.nsIWebNavigation)
4401  .QueryInterface(Ci.nsIDocShell);
4402  let notificationBox = gBrowser.getNotificationBox(aBrowser);
4403  let notification = notificationBox.getNotificationWithValue("refresh-blocked");
4404  if (notification) {
4405  notification.label = message;
4406  notification.refreshURI = aURI;
4407  notification.delay = aDelay;
4408  notification.docShell = docShell;
4409  } else {
4410  let buttons = [{
4411  label: refreshButtonText,
4412  accessKey: refreshButtonAccesskey,
4413  callback: function (aNotification, aButton) {
4414  var refreshURI = aNotification.docShell
4415  .QueryInterface(Ci.nsIRefreshURI);
4416  refreshURI.forceRefreshURI(aNotification.refreshURI,
4417  aNotification.delay, true);
4418  }
4419  }];
4420  notification =
4421  notificationBox.appendNotification(message, "refresh-blocked",
4422  "chrome://browser/skin/Info.png",
4423  notificationBox.PRIORITY_INFO_MEDIUM,
4424  buttons);
4425  notification.refreshURI = aURI;
4426  notification.delay = aDelay;
4427  notification.docShell = docShell;
4428  }
4429  return false;
4430  }
4431  return true;
4432  },
4433 
4434  onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
4435  }
4436 }
4437 
4438 function nsBrowserAccess()
4439 {
4440 }
4441 
4442 nsBrowserAccess.prototype =
4443 {
4444  QueryInterface : function(aIID)
4445  {
4446  if (aIID.equals(Ci.nsIBrowserDOMWindow) ||
4447  aIID.equals(Ci.nsISupports))
4448  return this;
4449  throw Components.results.NS_NOINTERFACE;
4450  },
4451 
4452  openURI : function(aURI, aOpener, aWhere, aContext)
4453  {
4454  var newWindow = null;
4455  var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
4456 
4457  if (isExternal && aURI && aURI.schemeIs("chrome")) {
4458  dump("use -chrome command-line option to load external chrome urls\n");
4459  return null;
4460  }
4461 
4462  var loadflags = isExternal ?
4463  Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
4464  Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
4465  if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW)
4466  aWhere = gPrefService.getIntPref("browser.link.open_newwindow");
4467  switch (aWhere) {
4468  case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW :
4469  // FIXME: Bug 408379. So how come this doesn't send the
4470  // referrer like the other loads do?
4471  var url = aURI ? aURI.spec : "about:blank";
4472  // Pass all params to openDialog to ensure that "url" isn't passed through
4473  // loadOneOrMoreURIs, which splits based on "|"
4474  newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null);
4475  break;
4476  case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB :
4477  let win, needToFocusWin;
4478 
4479  // try the current window. if we're in a popup, fall back on the most recent browser window
4480  if (!window.document.documentElement.getAttribute("chromehidden"))
4481  win = window;
4482  else {
4483  win = Cc["@mozilla.org/browser/browserglue;1"]
4484  .getService(Ci.nsIBrowserGlue)
4485  .getMostRecentBrowserWindow();
4486  needToFocusWin = true;
4487  }
4488 
4489  if (!win) {
4490  // we couldn't find a suitable window, a new one needs to be opened.
4491  return null;
4492  }
4493 
4494  let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
4495  let referrer = aOpener ? makeURI(aOpener.location.href) : null;
4496 
4497  // If this is an external load, we need to load a blank tab first,
4498  // because loadflags can't be passed to loadOneTab.
4499  let loadBlankFirst = !aURI || isExternal;
4500  let tab = win.gBrowser.loadOneTab(loadBlankFirst ? "about:blank" : aURI.spec,
4501  referrer, null, null, loadInBackground, false);
4502  let browser = win.gBrowser.getBrowserForTab(tab);
4503 
4504  if (loadBlankFirst && aURI)
4505  browser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);
4506 
4507  newWindow = browser.contentWindow;
4508  if (needToFocusWin || (!loadInBackground && isExternal))
4509  newWindow.focus();
4510  break;
4511  default : // OPEN_CURRENTWINDOW or an illegal value
4512  newWindow = content;
4513  if (aURI) {
4514  let referrer = aOpener ? makeURI(aOpener.location.href) : null;
4515  gBrowser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);
4516  }
4517  if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"))
4518  content.focus();
4519  }
4520  return newWindow;
4521  },
4522 
4523  isTabContentWindow : function(aWindow)
4524  {
4525  return gBrowser.browsers.some(function (browser) browser.contentWindow == aWindow);
4526  }
4527 }
4528 
4529 function onViewToolbarsPopupShowing(aEvent)
4530 {
4531  var popup = aEvent.target;
4532  var i;
4533 
4534  // Empty the menu
4535  for (i = popup.childNodes.length-1; i >= 0; --i) {
4536  var deadItem = popup.childNodes[i];
4537  if (deadItem.hasAttribute("toolbarindex"))
4538  popup.removeChild(deadItem);
4539  }
4540 
4541  var firstMenuItem = popup.firstChild;
4542 
4543  for (i = 0; i < gNavToolbox.childNodes.length; ++i) {
4544  var toolbar = gNavToolbox.childNodes[i];
4545  var toolbarName = toolbar.getAttribute("toolbarname");
4546  if (toolbarName) {
4547  let menuItem = document.createElement("menuitem");
4548  let hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
4549  "autohide" : "collapsed";
4550  menuItem.setAttribute("toolbarindex", i);
4551  menuItem.setAttribute("type", "checkbox");
4552  menuItem.setAttribute("label", toolbarName);
4553  menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
4554  menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute) != "true");
4555  popup.insertBefore(menuItem, firstMenuItem);
4556 
4557  menuItem.addEventListener("command", onViewToolbarCommand, false);
4558  }
4559  toolbar = toolbar.nextSibling;
4560  }
4561 }
4562 
4563 function onViewToolbarCommand(aEvent)
4564 {
4565  var index = aEvent.originalTarget.getAttribute("toolbarindex");
4566  var toolbar = gNavToolbox.childNodes[index];
4567  var hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
4568  "autohide" : "collapsed";
4569 
4570  toolbar.setAttribute(hidingAttribute,
4571  aEvent.originalTarget.getAttribute("checked") != "true");
4572  document.persist(toolbar.id, hidingAttribute);
4573 }
4574 
4575 function displaySecurityInfo()
4576 {
4577  BrowserPageInfo(null, "securityTab");
4578 }
4579 
4600 function toggleSidebar(commandID, forceOpen) {
4601 
4602  var sidebarBox = document.getElementById("sidebar-box");
4603  if (!commandID)
4604  commandID = sidebarBox.getAttribute("sidebarcommand");
4605 
4606  var sidebarBroadcaster = document.getElementById(commandID);
4607  var sidebar = document.getElementById("sidebar"); // xul:browser
4608  var sidebarTitle = document.getElementById("sidebar-title");
4609  var sidebarSplitter = document.getElementById("sidebar-splitter");
4610 
4611  if (sidebarBroadcaster.getAttribute("checked") == "true") {
4612  if (!forceOpen) {
4613  sidebarBroadcaster.removeAttribute("checked");
4614  sidebarBox.setAttribute("sidebarcommand", "");
4615  sidebarTitle.value = "";
4616  sidebar.setAttribute("src", "about:blank");
4617  sidebarBox.hidden = true;
4618  sidebarSplitter.hidden = true;
4619  content.focus();
4620  } else {
4621  fireSidebarFocusedEvent();
4622  }
4623  return;
4624  }
4625 
4626  // now we need to show the specified sidebar
4627 
4628  // ..but first update the 'checked' state of all sidebar broadcasters
4629  var broadcasters = document.getElementsByAttribute("group", "sidebar");
4630  for (var i = 0; i < broadcasters.length; ++i) {
4631  // skip elements that observe sidebar broadcasters and random
4632  // other elements
4633  if (broadcasters[i].localName != "broadcaster")
4634  continue;
4635 
4636  if (broadcasters[i] != sidebarBroadcaster)
4637  broadcasters[i].removeAttribute("checked");
4638  else
4639  sidebarBroadcaster.setAttribute("checked", "true");
4640  }
4641 
4642  sidebarBox.hidden = false;
4643  sidebarSplitter.hidden = false;
4644 
4645  var url = sidebarBroadcaster.getAttribute("sidebarurl");
4646  var title = sidebarBroadcaster.getAttribute("sidebartitle");
4647  if (!title)
4648  title = sidebarBroadcaster.getAttribute("label");
4649  sidebar.setAttribute("src", url); // kick off async load
4650  sidebarBox.setAttribute("sidebarcommand", sidebarBroadcaster.id);
4651  sidebarTitle.value = title;
4652 
4653  // We set this attribute here in addition to setting it on the <browser>
4654  // element itself, because the code in BrowserShutdown persists this
4655  // attribute, not the "src" of the <browser id="sidebar">. The reason it
4656  // does that is that we want to delay sidebar load a bit when a browser
4657  // window opens. See delayedStartup().
4658  sidebarBox.setAttribute("src", url);
4659 
4660  if (sidebar.contentDocument.location.href != url)
4661  sidebar.addEventListener("load", sidebarOnLoad, true);
4662  else // older code handled this case, so we do it too
4663  fireSidebarFocusedEvent();
4664 }
4665 
4666 function sidebarOnLoad(event) {
4667  var sidebar = document.getElementById("sidebar");
4668  sidebar.removeEventListener("load", sidebarOnLoad, true);
4669  // We're handling the 'load' event before it bubbles up to the usual
4670  // (non-capturing) event handlers. Let it bubble up before firing the
4671  // SidebarFocused event.
4672  setTimeout(fireSidebarFocusedEvent, 0);
4673 }
4674 
4681 function fireSidebarFocusedEvent() {
4682  var sidebar = document.getElementById("sidebar");
4683  var event = document.createEvent("Events");
4684  event.initEvent("SidebarFocused", true, false);
4685  sidebar.contentWindow.dispatchEvent(event);
4686 }
4687 
4688 var gHomeButton = {
4689  prefDomain: "browser.startup.homepage",
4690  observe: function (aSubject, aTopic, aPrefName)
4691  {
4692  if (aTopic != "nsPref:changed" || aPrefName != this.prefDomain)
4693  return;
4694 
4695  this.updateTooltip();
4696  },
4697 
4698  updateTooltip: function (homeButton)
4699  {
4700  if (!homeButton)
4701  homeButton = document.getElementById("home-button");
4702  if (homeButton) {
4703  var homePage = this.getHomePage();
4704  homePage = homePage.replace(/\|/g,', ');
4705  homeButton.setAttribute("tooltiptext", homePage);
4706  }
4707  },
4708 
4709  getHomePage: function ()
4710  {
4711  var url;
4712  try {
4713  url = gPrefService.getComplexValue(this.prefDomain,
4714  Components.interfaces.nsIPrefLocalizedString).data;
4715  } catch (e) {
4716  }
4717 
4718  // use this if we can't find the pref
4719  if (!url) {
4720  var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
4721  var configBundle = SBS.createBundle("resource:/browserconfig.properties");
4722  url = configBundle.GetStringFromName(this.prefDomain);
4723  }
4724 
4725  return url;
4726  },
4727 
4728  updatePersonalToolbarStyle: function (homeButton)
4729  {
4730  if (!homeButton)
4731  homeButton = document.getElementById("home-button");
4732  if (homeButton)
4733  homeButton.className = homeButton.parentNode.id == "PersonalToolbar"
4734  || homeButton.parentNode.parentNode.id == "PersonalToolbar" ?
4735  homeButton.className.replace("toolbarbutton-1", "bookmark-item") :
4736  homeButton.className.replace("bookmark-item", "toolbarbutton-1");
4737  }
4738 };
4739 
4749 function getBrowserSelection(aCharLen) {
4750  // selections of more than 150 characters aren't useful
4751  const kMaxSelectionLen = 150;
4752  const charLen = Math.min(aCharLen || kMaxSelectionLen, kMaxSelectionLen);
4753 
4754  var focusedWindow = document.commandDispatcher.focusedWindow;
4755  var selection = focusedWindow.getSelection().toString();
4756 
4757  if (selection) {
4758  if (selection.length > charLen) {
4759  // only use the first charLen important chars. see bug 221361
4760  var pattern = new RegExp("^(?:\\s*.){0," + charLen + "}");
4761  pattern.test(selection);
4762  selection = RegExp.lastMatch;
4763  }
4764 
4765  selection = selection.replace(/^\s+/, "")
4766  .replace(/\s+$/, "")
4767  .replace(/\s+/g, " ");
4768 
4769  if (selection.length > charLen)
4770  selection = selection.substr(0, charLen);
4771  }
4772  return selection;
4773 }
4774 
4776 function openWebPanel(aTitle, aURI)
4777 {
4778  // Ensure that the web panels sidebar is open.
4779  toggleSidebar('viewWebPanelsSidebar', true);
4780 
4781  // Set the title of the panel.
4782  document.getElementById("sidebar-title").value = aTitle;
4783 
4784  // Tell the Web Panels sidebar to load the bookmark.
4785  var sidebar = document.getElementById("sidebar");
4786  if (sidebar.docShell && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser')) {
4787  sidebar.contentWindow.loadWebPanel(aURI);
4788  if (gWebPanelURI) {
4789  gWebPanelURI = "";
4790  sidebar.removeEventListener("load", asyncOpenWebPanel, true);
4791  }
4792  }
4793  else {
4794  // The panel is still being constructed. Attach an onload handler.
4795  if (!gWebPanelURI)
4796  sidebar.addEventListener("load", asyncOpenWebPanel, true);
4797  gWebPanelURI = aURI;
4798  }
4799 }
4800 
4802 {
4803  var sidebar = document.getElementById("sidebar");
4804  if (gWebPanelURI && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser'))
4805  sidebar.contentWindow.loadWebPanel(gWebPanelURI);
4806  gWebPanelURI = "";
4807  sidebar.removeEventListener("load", asyncOpenWebPanel, true);
4808 }
4809 
4810 /*
4811  * - [ Dependencies ] ---------------------------------------------------------
4812  * utilityOverlay.js:
4813  * - gatherTextUnder
4814  */
4815 
4816  // Called whenever the user clicks in the content area,
4817  // except when left-clicking on links (special case)
4818  // should always return true for click to go through
4819  function contentAreaClick(event, fieldNormalClicks)
4820  {
4821  if (!event.isTrusted || event.getPreventDefault()) {
4822  return true;
4823  }
4824 
4825  var target = event.target;
4826  var linkNode;
4827 
4828  if (target instanceof HTMLAnchorElement ||
4829  target instanceof HTMLAreaElement ||
4830  target instanceof HTMLLinkElement) {
4831  if (target.hasAttribute("href"))
4832  linkNode = target;
4833 
4834  // xxxmpc: this is kind of a hack to work around a Gecko bug (see bug 266932)
4835  // we're going to walk up the DOM looking for a parent link node,
4836  // this shouldn't be necessary, but we're matching the existing behaviour for left click
4837  var parent = target.parentNode;
4838  while (parent) {
4839  if (parent instanceof HTMLAnchorElement ||
4840  parent instanceof HTMLAreaElement ||
4841  parent instanceof HTMLLinkElement) {
4842  if (parent.hasAttribute("href"))
4843  linkNode = parent;
4844  }
4845  parent = parent.parentNode;
4846  }
4847  }
4848  else {
4849  linkNode = event.originalTarget;
4850  while (linkNode && !(linkNode instanceof HTMLAnchorElement))
4851  linkNode = linkNode.parentNode;
4852  // <a> cannot be nested. So if we find an anchor without an
4853  // href, there is no useful <a> around the target
4854  if (linkNode && !linkNode.hasAttribute("href"))
4855  linkNode = null;
4856  }
4857  var wrapper = null;
4858  if (linkNode) {
4859  wrapper = linkNode;
4860  if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
4861  !event.altKey && !event.metaKey) {
4862  // A Web panel's links should target the main content area. Do this
4863  // if no modifier keys are down and if there's no target or the target equals
4864  // _main (the IE convention) or _content (the Mozilla convention).
4865  // XXX Now that markLinkVisited is gone, we may not need to field _main and
4866  // _content here.
4867  target = wrapper.getAttribute("target");
4868  if (fieldNormalClicks &&
4869  (!target || target == "_content" || target == "_main"))
4870  // IE uses _main, SeaMonkey uses _content, we support both
4871  {
4872  if (!wrapper.href)
4873  return true;
4874  if (wrapper.getAttribute("onclick"))
4875  return true;
4876  // javascript links should be executed in the current browser
4877  if (wrapper.href.substr(0, 11) === "javascript:")
4878  return true;
4879  // data links should be executed in the current browser
4880  if (wrapper.href.substr(0, 5) === "data:")
4881  return true;
4882 
4883  try {
4884  urlSecurityCheck(wrapper.href, wrapper.ownerDocument.nodePrincipal);
4885  }
4886  catch(ex) {
4887  return false;
4888  }
4889 
4890  var postData = { };
4891  var url = getShortcutOrURI(wrapper.href, postData);
4892  if (!url)
4893  return true;
4894  loadURI(url, null, postData.value, false);
4895  event.preventDefault();
4896  return false;
4897  }
4898  else if (linkNode.getAttribute("rel") == "sidebar") {
4899  // This is the Opera convention for a special link that - when clicked - allows
4900  // you to add a sidebar panel. We support the Opera convention here. The link's
4901  // title attribute contains the title that should be used for the sidebar panel.
4902  PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
4903  wrapper.getAttribute("title"),
4904  null, null, true, true);
4905  event.preventDefault();
4906  return false;
4907  }
4908  }
4909  else {
4910  handleLinkClick(event, wrapper.href, linkNode);
4911  }
4912 
4913  return true;
4914  } else {
4915  // Try simple XLink
4916  var href, realHref, baseURI;
4917  linkNode = target;
4918  while (linkNode) {
4919  if (linkNode.nodeType == Node.ELEMENT_NODE) {
4920  wrapper = linkNode;
4921 
4922  realHref = wrapper.getAttributeNS("http://www.w3.org/1999/xlink", "href");
4923  if (realHref) {
4924  href = realHref;
4925  baseURI = wrapper.baseURI
4926  }
4927  }
4928  linkNode = linkNode.parentNode;
4929  }
4930  if (href) {
4931  href = makeURLAbsolute(baseURI, href);
4932  handleLinkClick(event, href, null);
4933  return true;
4934  }
4935  }
4936  if (event.button == 1 &&
4937  gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
4938  !gPrefService.getBoolPref("general.autoScroll")) {
4940  }
4941  return true;
4942  }
4943 
4944 function handleLinkClick(event, href, linkNode)
4945 {
4946  var doc = event.target.ownerDocument;
4947 
4948  switch (event.button) {
4949  case 0: // if left button clicked
4950 #ifdef XP_MACOSX
4951  if (event.metaKey) { // Cmd
4952 #else
4953  if (event.ctrlKey) {
4954 #endif
4955  openNewTabWith(href, doc, null, event, false);
4956  event.stopPropagation();
4957  return true;
4958  }
4959 
4960  if (event.shiftKey && event.altKey) {
4961  var feedService =
4962  Cc["@mozilla.org/browser/feeds/result-service;1"].
4963  getService(Ci.nsIFeedResultService);
4964  feedService.forcePreviewPage = true;
4965  loadURI(href, null, null, false);
4966  return false;
4967  }
4968 
4969  if (event.shiftKey) {
4970  openNewWindowWith(href, doc, null, false);
4971  event.stopPropagation();
4972  return true;
4973  }
4974 
4975  if (event.altKey) {
4976  saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
4977  true, doc.documentURIObject);
4978  return true;
4979  }
4980 
4981  return false;
4982  case 1: // if middle button clicked
4983  var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
4984  if (tab)
4985  openNewTabWith(href, doc, null, event, false);
4986  else
4987  openNewWindowWith(href, doc, null, false);
4988  event.stopPropagation();
4989  return true;
4990  }
4991  return false;
4992 }
4993 
4995 {
4996  var url = readFromClipboard();
4997  if (!url)
4998  return;
4999 
5000  var postData = { };
5001  url = getShortcutOrURI(url, postData);
5002  if (!url)
5003  return;
5004 
5005  try {
5006  addToUrlbarHistory(url);
5007  } catch (ex) {
5008  // Things may go wrong when adding url to session history,
5009  // but don't let that interfere with the loading of the url.
5010  Cu.reportError(ex);
5011  }
5012 
5013  openUILink(url,
5014  event,
5015  true /* ignore the fact this is a middle click */);
5016 
5017  event.stopPropagation();
5018 }
5019 
5020 /*
5021  * Note that most of this routine has been moved into C++ in order to
5022  * be available for all <browser> tags as well as gecko embedding. See
5023  * mozilla/content/base/src/nsContentAreaDragDrop.cpp.
5024  *
5025  * Do not add any new fuctionality here other than what is needed for
5026  * a standalone product.
5027  */
5028 
5030  onDrop: function (aEvent)
5031  {
5032  if (aEvent.getPreventDefault())
5033  return;
5034 
5035  var types = aEvent.dataTransfer.types;
5036  if (!types.contains("application/x-moz-file") &&
5037  !types.contains("text/x-moz-url") &&
5038  !types.contains("text/uri-list") &&
5039  !types.contains("text/plain")) {
5040  aEvent.preventDefault();
5041  return;
5042  }
5043 
5044  let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
5045 
5046  // valid urls don't contain spaces ' '; if we have a space it
5047  // isn't a valid url, or if it's a javascript: or data: url,
5048  // bail out
5049  if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
5050  /^\s*(javascript|data):/.test(url))
5051  return;
5052 
5053  nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
5054 
5055  switch (document.documentElement.getAttribute('windowtype')) {
5056  case "navigator:browser":
5057  var postData = { };
5058  var uri = getShortcutOrURI(url, postData);
5059  loadURI(uri, null, postData.value, false);
5060  break;
5061  case "navigator:view-source":
5062  viewSource(url);
5063  break;
5064  }
5065 
5066  // keep the event from being handled by the dragDrop listeners
5067  // built-in to gecko if they happen to be above us.
5068  aEvent.preventDefault();
5069  }
5070 };
5071 
5073 { try {
5074  var node = event.target;
5075  var name = node.getAttribute('name');
5076 
5077  if (name == 'detectorGroup') {
5078  SetForcedDetector(true);
5079  SelectDetector(event, false);
5080  } else if (name == 'charsetGroup') {
5081  var charset = node.getAttribute('id');
5082  charset = charset.substring('charset.'.length, charset.length)
5083  SetForcedCharset(charset);
5084  } else if (name == 'charsetCustomize') {
5085  //do nothing - please remove this else statement, once the charset prefs moves to the pref window
5086  } else {
5087  SetForcedCharset(node.getAttribute('id'));
5088  }
5089  } catch(ex) { alert(ex); }
5090 }
5091 
5092 function SelectDetector(event, doReload)
5093 {
5094  var uri = event.target.getAttribute("id");
5095  var prefvalue = uri.substring('chardet.'.length, uri.length);
5096  if ("off" == prefvalue) { // "off" is special value to turn off the detectors
5097  prefvalue = "";
5098  }
5099 
5100  try {
5101  var pref = Components.classes["@mozilla.org/preferences-service;1"]
5102  .getService(Components.interfaces.nsIPrefBranch);
5103  var str = Components.classes["@mozilla.org/supports-string;1"]
5104  .createInstance(Components.interfaces.nsISupportsString);
5105 
5106  str.data = prefvalue;
5107  pref.setComplexValue("intl.charset.detector",
5108  Components.interfaces.nsISupportsString, str);
5109  if (doReload) window.content.location.reload();
5110  }
5111  catch (ex) {
5112  dump("Failed to set the intl.charset.detector preference.\n");
5113  }
5114 }
5115 
5116 function SetForcedDetector(doReload)
5117 {
5118  BrowserSetForcedDetector(doReload);
5119 }
5120 
5122 {
5124 }
5125 
5127 {
5128  var docCharset = gBrowser.docShell.QueryInterface(Ci.nsIDocCharset);
5129  docCharset.charset = aCharset;
5130  // Save the forced character-set
5131  PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, aCharset);
5132  BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
5133 }
5134 
5135 function BrowserSetForcedDetector(doReload)
5136 {
5137  gBrowser.documentCharsetInfo.forcedDetector = true;
5138  if (doReload)
5139  BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
5140 }
5141 
5143 {
5144  // extract the charset from DOM
5145  var wnd = document.commandDispatcher.focusedWindow;
5146  if ((window == wnd) || (wnd == null)) wnd = window.content;
5147 
5148  // Uncheck previous item
5149  if (gPrevCharset) {
5150  var pref_item = document.getElementById('charset.' + gPrevCharset);
5151  if (pref_item)
5152  pref_item.setAttribute('checked', 'false');
5153  }
5154 
5155  var menuitem = document.getElementById('charset.' + wnd.document.characterSet);
5156  if (menuitem) {
5157  menuitem.setAttribute('checked', 'true');
5158  }
5159 }
5160 
5162 {
5163  var prefvalue;
5164 
5165  try {
5166  var pref = Components.classes["@mozilla.org/preferences-service;1"]
5167  .getService(Components.interfaces.nsIPrefBranch);
5168  prefvalue = pref.getComplexValue("intl.charset.detector",
5169  Components.interfaces.nsIPrefLocalizedString).data;
5170  }
5171  catch (ex) {
5172  prefvalue = "";
5173  }
5174 
5175  if (prefvalue == "") prefvalue = "off";
5176  dump("intl.charset.detector = "+ prefvalue + "\n");
5177 
5178  prefvalue = 'chardet.' + prefvalue;
5179  var menuitem = document.getElementById(prefvalue);
5180 
5181  if (menuitem) {
5182  menuitem.setAttribute('checked', 'true');
5183  }
5184 }
5185 
5187 {
5188  // use setTimeout workaround to delay checkmark the menu
5189  // when onmenucomplete is ready then use it instead of oncreate
5190  // see bug 78290 for the detail
5195 }
5196 
5197 function CreateMenu(node)
5198 {
5199  var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
5200  observerService.notifyObservers(null, "charsetmenu-selected", node);
5201 }
5202 
5204 {
5205  var charset = window.content.document.characterSet;
5206 
5207  if (charset.length > 0 && (charset != gLastBrowserCharset)) {
5208  if (!gCharsetMenu)
5209  gCharsetMenu = Components.classes['@mozilla.org/rdf/datasource;1?name=charset-menu'].getService().QueryInterface(Components.interfaces.nsICurrentCharsetListener);
5210  gCharsetMenu.SetCurrentCharset(charset);
5211  gPrevCharset = gLastBrowserCharset;
5212  gLastBrowserCharset = charset;
5213  }
5214 }
5215 
5216 /* Begin Page Style Functions */
5217 function getAllStyleSheets(frameset) {
5218  var styleSheetsArray = Array.slice(frameset.document.styleSheets);
5219  for (let i = 0; i < frameset.frames.length; i++) {
5220  let frameSheets = getAllStyleSheets(frameset.frames[i]);
5221  styleSheetsArray = styleSheetsArray.concat(frameSheets);
5222  }
5223  return styleSheetsArray;
5224 }
5225 
5226 function stylesheetFillPopup(menuPopup) {
5227  var noStyle = menuPopup.firstChild;
5228  var persistentOnly = noStyle.nextSibling;
5229  var sep = persistentOnly.nextSibling;
5230  while (sep.nextSibling)
5231  menuPopup.removeChild(sep.nextSibling);
5232 
5233  var styleSheets = getAllStyleSheets(window.content);
5234  var currentStyleSheets = {};
5235  var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
5236  var haveAltSheets = false;
5237  var altStyleSelected = false;
5238 
5239  for (let i = 0; i < styleSheets.length; ++i) {
5240  let currentStyleSheet = styleSheets[i];
5241 
5242  if (!currentStyleSheet.title)
5243  continue;
5244 
5245  // Skip any stylesheets that don't match the screen media type.
5246  let (media = currentStyleSheet.media.mediaText.toLowerCase()) {
5247  if (media && (media.indexOf("screen") == -1) && (media.indexOf("all") == -1))
5248  continue;
5249  }
5250 
5251  if (!currentStyleSheet.disabled)
5252  altStyleSelected = true;
5253 
5254  haveAltSheets = true;
5255 
5256  let lastWithSameTitle = null;
5257  if (currentStyleSheet.title in currentStyleSheets)
5258  lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
5259 
5260  if (!lastWithSameTitle) {
5261  let menuItem = document.createElement("menuitem");
5262  menuItem.setAttribute("type", "radio");
5263  menuItem.setAttribute("label", currentStyleSheet.title);
5264  menuItem.setAttribute("data", currentStyleSheet.title);
5265  menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled);
5266  menuPopup.appendChild(menuItem);
5267  currentStyleSheets[currentStyleSheet.title] = menuItem;
5268  } else if (currentStyleSheet.disabled) {
5269  lastWithSameTitle.removeAttribute("checked");
5270  }
5271  }
5272 
5273  noStyle.setAttribute("checked", styleDisabled);
5274  persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
5275  persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false;
5276  sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
5277  return true;
5278 }
5279 
5280 function stylesheetInFrame(frame, title) {
5281  return Array.some(frame.document.styleSheets,
5282  function (stylesheet) stylesheet.title == title);
5283 }
5284 
5285 function stylesheetSwitchFrame(frame, title) {
5286  var docStyleSheets = frame.document.styleSheets;
5287 
5288  for (let i = 0; i < docStyleSheets.length; ++i) {
5289  let docStyleSheet = docStyleSheets[i];
5290 
5291  if (title == "_nostyle")
5292  docStyleSheet.disabled = true;
5293  else if (docStyleSheet.title)
5294  docStyleSheet.disabled = (docStyleSheet.title != title);
5295  else if (docStyleSheet.disabled)
5296  docStyleSheet.disabled = false;
5297  }
5298 }
5299 
5300 function stylesheetSwitchAll(frameset, title) {
5301  if (!title || title == "_nostyle" || stylesheetInFrame(frameset, title))
5302  stylesheetSwitchFrame(frameset, title);
5303 
5304  for (let i = 0; i < frameset.frames.length; i++)
5305  stylesheetSwitchAll(frameset.frames[i], title);
5306 }
5307 
5308 function setStyleDisabled(disabled) {
5309  getMarkupDocumentViewer().authorStyleDisabled = disabled;
5310 }
5311 /* End of the Page Style functions */
5312 
5315  // BrowserOffline Public Methods
5316  init: function ()
5317  {
5318  if (!this._uiElement)
5319  this._uiElement = document.getElementById("goOfflineMenuitem");
5320 
5321  var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
5322  os.addObserver(this, "network:offline-status-changed", false);
5323 
5324  var ioService = Components.classes["@mozilla.org/network/io-service;1"].
5325  getService(Components.interfaces.nsIIOService2);
5326 
5327  // if ioService is managing the offline status, then ioservice.offline
5328  // is already set correctly. We will continue to allow the ioService
5329  // to manage its offline state until the user uses the "Work Offline" UI.
5330 
5331  if (!ioService.manageOfflineStatus) {
5332  // set the initial state
5333  var isOffline = false;
5334  try {
5335  isOffline = gPrefService.getBoolPref("browser.offline");
5336  }
5337  catch (e) { }
5338  ioService.offline = isOffline;
5339  }
5340 
5341  this._updateOfflineUI(ioService.offline);
5342  },
5343 
5344  uninit: function ()
5345  {
5346  try {
5347  var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
5348  os.removeObserver(this, "network:offline-status-changed");
5349  } catch (ex) {
5350  }
5351  },
5352 
5353  toggleOfflineStatus: function ()
5354  {
5355  var ioService = Components.classes["@mozilla.org/network/io-service;1"].
5356  getService(Components.interfaces.nsIIOService2);
5357 
5358  // Stop automatic management of the offline status
5359  try {
5360  ioService.manageOfflineStatus = false;
5361  } catch (ex) {
5362  }
5363 
5364  if (!ioService.offline && !this._canGoOffline()) {
5365  this._updateOfflineUI(false);
5366  return;
5367  }
5368 
5369  ioService.offline = !ioService.offline;
5370 
5371  // Save the current state for later use as the initial state
5372  // (if there is no netLinkService)
5373  gPrefService.setBoolPref("browser.offline", ioService.offline);
5374  },
5375 
5377  // nsIObserver
5378  observe: function (aSubject, aTopic, aState)
5379  {
5380  if (aTopic != "network:offline-status-changed")
5381  return;
5382 
5383  this._updateOfflineUI(aState == "offline");
5384  },
5385 
5387  // BrowserOffline Implementation Methods
5388  _canGoOffline: function ()
5389  {
5390  var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
5391  if (os) {
5392  try {
5393  var cancelGoOffline = Components.classes["@mozilla.org/supports-PRBool;1"].createInstance(Components.interfaces.nsISupportsPRBool);
5394  os.notifyObservers(cancelGoOffline, "offline-requested", null);
5395 
5396  // Something aborted the quit process.
5397  if (cancelGoOffline.data)
5398  return false;
5399  }
5400  catch (ex) {
5401  }
5402  }
5403  return true;
5404  },
5405 
5406  _uiElement: null,
5407  _updateOfflineUI: function (aOffline)
5408  {
5409  var offlineLocked = gPrefService.prefIsLocked("network.online");
5410  if (offlineLocked)
5411  this._uiElement.setAttribute("disabled", "true");
5412 
5413  this._uiElement.setAttribute("checked", aOffline);
5414  }
5415 };
5416 
5419  // OfflineApps Public Methods
5420  init: function ()
5421  {
5422  var obs = Cc["@mozilla.org/observer-service;1"].
5423  getService(Ci.nsIObserverService);
5424  obs.addObserver(this, "dom-storage-warn-quota-exceeded", false);
5425  obs.addObserver(this, "offline-cache-update-completed", false);
5426  },
5427 
5428  uninit: function ()
5429  {
5430  var obs = Cc["@mozilla.org/observer-service;1"].
5431  getService(Ci.nsIObserverService);
5432  obs.removeObserver(this, "dom-storage-warn-quota-exceeded");
5433  obs.removeObserver(this, "offline-cache-update-completed");
5434  },
5435 
5436  handleEvent: function(event) {
5437  if (event.type == "MozApplicationManifest") {
5438  this.offlineAppRequested(event.originalTarget.defaultView);
5439  }
5440  },
5441 
5443  // OfflineApps Implementation Methods
5444 
5445  // XXX: _getBrowserWindowForContentWindow and _getBrowserForContentWindow
5446  // were taken from browser/components/feeds/src/WebContentConverter.
5447  _getBrowserWindowForContentWindow: function(aContentWindow) {
5448  return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
5449  .getInterface(Ci.nsIWebNavigation)
5450  .QueryInterface(Ci.nsIDocShellTreeItem)
5451  .rootTreeItem
5452  .QueryInterface(Ci.nsIInterfaceRequestor)
5453  .getInterface(Ci.nsIDOMWindow)
5454  .wrappedJSObject;
5455  },
5456 
5457  _getBrowserForContentWindow: function(aBrowserWindow, aContentWindow) {
5458  // This depends on pseudo APIs of browser.js and tabbrowser.xml
5459  aContentWindow = aContentWindow.top;
5460  var browsers = aBrowserWindow.getBrowser().browsers;
5461  for (var i = 0; i < browsers.length; ++i) {
5462  if (browsers[i].contentWindow == aContentWindow)
5463  return browsers[i];
5464  }
5465  },
5466 
5467  _getManifestURI: function(aWindow) {
5468  if (!aWindow.document.documentElement) return null;
5469  var attr = aWindow.document.documentElement.getAttribute("manifest");
5470  if (!attr) return null;
5471 
5472  try {
5473  var contentURI = makeURI(aWindow.location.href, null, null);
5474  return makeURI(attr, aWindow.document.characterSet, contentURI);
5475  } catch (e) {
5476  return null;
5477  }
5478  },
5479 
5480  // A cache update isn't tied to a specific window. Try to find
5481  // the best browser in which to warn the user about space usage
5482  _getBrowserForCacheUpdate: function(aCacheUpdate) {
5483  // Prefer the current browser
5484  var uri = this._getManifestURI(gBrowser.mCurrentBrowser.contentWindow);
5485  if (uri && uri.equals(aCacheUpdate.manifestURI)) {
5486  return gBrowser.mCurrentBrowser;
5487  }
5488 
5489  var browsers = gBrowser.browsers;
5490  for (var i = 0; i < browsers.length; ++i) {
5491  uri = this._getManifestURI(browsers[i].contentWindow);
5492  if (uri && uri.equals(aCacheUpdate.manifestURI)) {
5493  return browsers[i];
5494  }
5495  }
5496 
5497  return null;
5498  },
5499 
5500  _warnUsage: function(aBrowser, aURI) {
5501  if (!aBrowser)
5502  return;
5503 
5504  var notificationBox = gBrowser.getNotificationBox(aBrowser);
5505  var notification = notificationBox.getNotificationWithValue("offline-app-usage");
5506  if (!notification) {
5507  var buttons = [{
5508  label: gNavigatorBundle.getString("offlineApps.manageUsage"),
5509  accessKey: gNavigatorBundle.getString("offlineApps.manageUsageAccessKey"),
5510  callback: OfflineApps.manage
5511  }];
5512 
5513  var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
5514  const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
5515  var message = gNavigatorBundle.getFormattedString("offlineApps.usage",
5516  [ aURI.host,
5517  warnQuota / 1024 ]);
5518 
5519  notificationBox.appendNotification(message, "offline-app-usage",
5520  "chrome://browser/skin/Info.png",
5521  priority, buttons);
5522  }
5523 
5524  // Now that we've warned once, prevent the warning from showing up
5525  // again.
5526  var pm = Cc["@mozilla.org/permissionmanager;1"].
5527  getService(Ci.nsIPermissionManager);
5528  pm.add(aURI, "offline-app",
5529  Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
5530  },
5531 
5532  // XXX: duplicated in preferences/advanced.js
5533  _getOfflineAppUsage: function (host, groups)
5534  {
5535  var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
5536  getService(Components.interfaces.nsIApplicationCacheService);
5537  if (!groups) {
5538  groups = cacheService.getGroups({});
5539  }
5540  var ios = Components.classes["@mozilla.org/network/io-service;1"].
5541  getService(Components.interfaces.nsIIOService);
5542 
5543  var usage = 0;
5544  for (var i = 0; i < groups.length; i++) {
5545  var uri = ios.newURI(groups[i], null, null);
5546  if (uri.asciiHost == host) {
5547  var cache = cacheService.getActiveCache(groups[i]);
5548  usage += cache.usage;
5549  }
5550  }
5551 
5552  var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
5553  getService(Components.interfaces.nsIDOMStorageManager);
5554  usage += storageManager.getUsage(host);
5555 
5556  return usage;
5557  },
5558 
5559  _checkUsage: function(aURI) {
5560  var pm = Cc["@mozilla.org/permissionmanager;1"].
5561  getService(Ci.nsIPermissionManager);
5562 
5563  // if the user has already allowed excessive usage, don't bother checking
5564  if (pm.testExactPermission(aURI, "offline-app") !=
5565  Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN) {
5566  var usage = this._getOfflineAppUsage(aURI.asciiHost);
5567  var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
5568  if (usage >= warnQuota * 1024) {
5569  return true;
5570  }
5571  }
5572 
5573  return false;
5574  },
5575 
5576  offlineAppRequested: function(aContentWindow) {
5577  if (!gPrefService.getBoolPref("browser.offline-apps.notify")) {
5578  return;
5579  }
5580 
5581  var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
5582  var browser = this._getBrowserForContentWindow(browserWindow,
5583  aContentWindow);
5584 
5585  var currentURI = aContentWindow.document.documentURIObject;
5586  var pm = Cc["@mozilla.org/permissionmanager;1"].
5587  getService(Ci.nsIPermissionManager);
5588 
5589  // don't bother showing UI if the user has already made a decision
5590  if (pm.testExactPermission(currentURI, "offline-app") !=
5591  Ci.nsIPermissionManager.UNKNOWN_ACTION)
5592  return;
5593 
5594  try {
5595  if (gPrefService.getBoolPref("offline-apps.allow_by_default")) {
5596  // all pages can use offline capabilities, no need to ask the user
5597  return;
5598  }
5599  } catch(e) {
5600  // this pref isn't set by default, ignore failures
5601  }
5602 
5603  var host = currentURI.asciiHost;
5604  var notificationBox = gBrowser.getNotificationBox(browser);
5605  var notificationID = "offline-app-requested-" + host;
5606  var notification = notificationBox.getNotificationWithValue(notificationID);
5607 
5608  if (notification) {
5609  notification.documents.push(aContentWindow.document);
5610  } else {
5611  var buttons = [{
5612  label: gNavigatorBundle.getString("offlineApps.allow"),
5613  accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"),
5614  callback: function() {
5615  for (var i = 0; i < notification.documents.length; i++) {
5616  OfflineApps.allowSite(notification.documents[i]);
5617  }
5618  }
5619  },{
5620  label: gNavigatorBundle.getString("offlineApps.never"),
5621  accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"),
5622  callback: function() {
5623  for (var i = 0; i < notification.documents.length; i++) {
5624  OfflineApps.disallowSite(notification.documents[i]);
5625  }
5626  }
5627  },{
5628  label: gNavigatorBundle.getString("offlineApps.notNow"),
5629  accessKey: gNavigatorBundle.getString("offlineApps.notNowAccessKey"),
5630  callback: function() { /* noop */ }
5631  }];
5632 
5633  const priority = notificationBox.PRIORITY_INFO_LOW;
5634  var message = gNavigatorBundle.getFormattedString("offlineApps.available",
5635  [ host ]);
5636  notification =
5637  notificationBox.appendNotification(message, notificationID,
5638  "chrome://browser/skin/Info.png",
5639  priority, buttons);
5640  notification.documents = [ aContentWindow.document ];
5641  }
5642  },
5643 
5644  allowSite: function(aDocument) {
5645  var pm = Cc["@mozilla.org/permissionmanager;1"].
5646  getService(Ci.nsIPermissionManager);
5647  pm.add(aDocument.documentURIObject, "offline-app",
5648  Ci.nsIPermissionManager.ALLOW_ACTION);
5649 
5650  // When a site is enabled while loading, manifest resources will
5651  // start fetching immediately. This one time we need to do it
5652  // ourselves.
5653  this._startFetching(aDocument);
5654  },
5655 
5656  disallowSite: function(aDocument) {
5657  var pm = Cc["@mozilla.org/permissionmanager;1"].
5658  getService(Ci.nsIPermissionManager);
5659  pm.add(aDocument.documentURIObject, "offline-app",
5660  Ci.nsIPermissionManager.DENY_ACTION);
5661  },
5662 
5663  manage: function() {
5664  openAdvancedPreferences("networkTab");
5665  },
5666 
5667  _startFetching: function(aDocument) {
5668  if (!aDocument.documentElement)
5669  return;
5670 
5671  var manifest = aDocument.documentElement.getAttribute("manifest");
5672  if (!manifest)
5673  return;
5674 
5675  var manifestURI = makeURI(manifest, aDocument.characterSet,
5676  aDocument.documentURIObject);
5677 
5678  var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
5679  getService(Ci.nsIOfflineCacheUpdateService);
5680  updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject);
5681  },
5682 
5684  // nsIObserver
5685  observe: function (aSubject, aTopic, aState)
5686  {
5687  if (aTopic == "dom-storage-warn-quota-exceeded") {
5688  if (aSubject) {
5689  var uri = makeURI(aSubject.location.href);
5690 
5691  if (OfflineApps._checkUsage(uri)) {
5692  var browserWindow =
5693  this._getBrowserWindowForContentWindow(aSubject);
5694  var browser = this._getBrowserForContentWindow(browserWindow,
5695  aSubject);
5696  OfflineApps._warnUsage(browser, uri);
5697  }
5698  }
5699  } else if (aTopic == "offline-cache-update-completed") {
5700  var cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
5701 
5702  var uri = cacheUpdate.manifestURI;
5703  if (OfflineApps._checkUsage(uri)) {
5704  var browser = this._getBrowserForCacheUpdate(cacheUpdate);
5705  if (browser) {
5706  OfflineApps._warnUsage(browser, cacheUpdate.manifestURI);
5707  }
5708  }
5709  }
5710  }
5711 };
5712 
5714 {
5715  var reallyClose = closeWindow(false, warnAboutClosingWindow);
5716  if (!reallyClose)
5717  return false;
5718 
5719  var numBrowsers = gBrowser.browsers.length;
5720  for (let i = 0; reallyClose && i < numBrowsers; ++i) {
5721  let ds = gBrowser.browsers[i].docShell;
5722 
5723  if (ds.contentViewer && !ds.contentViewer.permitUnload())
5724  reallyClose = false;
5725  }
5726 
5727  return reallyClose;
5728 }
5729 
5736  // Popups aren't considered full browser windows.
5737  if (!toolbar.visible)
5738  return gBrowser.warnAboutClosingTabs(true);
5739 
5740  // Figure out if there's at least one other browser window around.
5741  let foundOtherBrowserWindow = false;
5742  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
5743  let e = wm.getEnumerator("navigator:browser");
5744  while (e.hasMoreElements() && !foundOtherBrowserWindow) {
5745  let win = e.getNext();
5746  if (win != window && win.toolbar.visible)
5747  foundOtherBrowserWindow = true;
5748  }
5749  if (foundOtherBrowserWindow)
5750  return gBrowser.warnAboutClosingTabs(true);
5751 
5752  let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
5753 
5754  let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].
5755  createInstance(Ci.nsISupportsPRBool);
5756  os.notifyObservers(closingCanceled,
5757  "browser-lastwindow-close-requested", null);
5758  if (closingCanceled.data)
5759  return false;
5760 
5761  os.notifyObservers(null, "browser-lastwindow-close-granted", null);
5762 
5763 #ifdef XP_MACOSX
5764  // OS X doesn't quit the application when the last window is closed, but keeps
5765  // the session alive. Hence don't prompt users to save tabs, but warn about
5766  // closing multiple tabs.
5767  return gBrowser.warnAboutClosingTabs(true);
5768 #else
5769  return true;
5770 #endif
5771 }
5772 
5774  sendLinkForWindow: function (aWindow) {
5775  this.sendMessage(aWindow.location.href,
5776  aWindow.document.title);
5777  },
5778 
5779  sendMessage: function (aBody, aSubject) {
5780  // generate a mailto url based on the url and the url's title
5781  var mailtoUrl = "mailto:";
5782  if (aBody) {
5783  mailtoUrl += "?body=" + encodeURIComponent(aBody);
5784  mailtoUrl += "&subject=" + encodeURIComponent(aSubject);
5785  }
5786 
5787  var uri = makeURI(mailtoUrl);
5788 
5789  // now pass this uri to the operating system
5790  this._launchExternalUrl(uri);
5791  },
5792 
5793  // a generic method which can be used to pass arbitrary urls to the operating
5794  // system.
5795  // aURL --> a nsIURI which represents the url to launch
5796  _launchExternalUrl: function (aURL) {
5797  var extProtocolSvc =
5798  Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
5799  .getService(Components.interfaces.nsIExternalProtocolService);
5800  if (extProtocolSvc)
5801  extProtocolSvc.loadUrl(aURL);
5802  }
5803 };
5804 
5805 function BrowserOpenAddonsMgr(aPane)
5806 {
5807  const EMTYPE = "Extension:Manager";
5808  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
5809  .getService(Components.interfaces.nsIWindowMediator);
5810  var theEM = wm.getMostRecentWindow(EMTYPE);
5811  if (theEM) {
5812  theEM.focus();
5813  if (aPane)
5814  theEM.showView(aPane);
5815  return;
5816  }
5817 
5818  const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
5819  const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
5820  if (aPane)
5821  window.openDialog(EMURL, "", EMFEATURES, aPane);
5822  else
5823  window.openDialog(EMURL, "", EMFEATURES);
5824 }
5825 
5826 function escapeNameValuePair(aName, aValue, aIsFormUrlEncoded)
5827 {
5828  if (aIsFormUrlEncoded)
5829  return escape(aName + "=" + aValue);
5830  else
5831  return escape(aName) + "=" + escape(aValue);
5832 }
5833 
5835 {
5836  var node = document.popupNode;
5837 
5838  var charset = node.ownerDocument.characterSet;
5839 
5840  var docURI = makeURI(node.ownerDocument.URL,
5841  charset);
5842 
5843  var formURI = makeURI(node.form.getAttribute("action"),
5844  charset,
5845  docURI);
5846 
5847  var spec = formURI.spec;
5848 
5849  var isURLEncoded =
5850  (node.form.method.toUpperCase() == "POST"
5851  && (node.form.enctype == "application/x-www-form-urlencoded" ||
5852  node.form.enctype == ""));
5853 
5854  var title = gNavigatorBundle.getFormattedString("addKeywordTitleAutoFill",
5855  [node.ownerDocument.title]);
5856  var description = PlacesUIUtils.getDescriptionFromDocument(node.ownerDocument);
5857 
5858  var el, type;
5859  var formData = [];
5860 
5861  for (var i=0; i < node.form.elements.length; i++) {
5862  el = node.form.elements[i];
5863 
5864  if (!el.type) // happens with fieldsets
5865  continue;
5866 
5867  if (el == node) {
5868  formData.push((isURLEncoded) ? escapeNameValuePair(el.name, "%s", true) :
5869  // Don't escape "%s", just append
5870  escapeNameValuePair(el.name, "", false) + "%s");
5871  continue;
5872  }
5873 
5874  type = el.type.toLowerCase();
5875 
5876  if ((type == "text" || type == "hidden" || type == "textarea") ||
5877  ((type == "checkbox" || type == "radio") && el.checked)) {
5878  formData.push(escapeNameValuePair(el.name, el.value, isURLEncoded));
5879  } else if (el instanceof HTMLSelectElement && el.selectedIndex >= 0) {
5880  for (var j=0; j < el.options.length; j++) {
5881  if (el.options[j].selected)
5882  formData.push(escapeNameValuePair(el.name, el.options[j].value,
5883  isURLEncoded));
5884  }
5885  }
5886  }
5887 
5888  var postData;
5889 
5890  if (isURLEncoded)
5891  postData = formData.join("&");
5892  else
5893  spec += "?" + formData.join("&");
5894 
5895  PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(spec), title, description, null,
5896  null, null, "", postData, charset);
5897 }
5898 
5899 function SwitchDocumentDirection(aWindow) {
5900  aWindow.document.dir = (aWindow.document.dir == "ltr" ? "rtl" : "ltr");
5901  for (var run = 0; run < aWindow.frames.length; run++)
5902  SwitchDocumentDirection(aWindow.frames[run]);
5903 }
5904 
5905 function getPluginInfo(pluginElement)
5906 {
5907  var tagMimetype;
5908  var pluginsPage;
5909  if (pluginElement instanceof HTMLAppletElement) {
5910  tagMimetype = "application/x-java-vm";
5911  } else {
5912  if (pluginElement instanceof HTMLObjectElement) {
5913  pluginsPage = pluginElement.getAttribute("codebase");
5914  } else {
5915  pluginsPage = pluginElement.getAttribute("pluginspage");
5916  }
5917 
5918  // only attempt if a pluginsPage is defined.
5919  if (pluginsPage) {
5920  var doc = pluginElement.ownerDocument;
5921  var docShell = findChildShell(doc, gBrowser.selectedBrowser.docShell, null);
5922  try {
5923  pluginsPage = makeURI(pluginsPage, doc.characterSet, docShell.currentURI).spec;
5924  } catch (ex) {
5925  pluginsPage = "";
5926  }
5927  }
5928 
5929  tagMimetype = pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
5930  .actualType;
5931 
5932  if (tagMimetype == "") {
5933  tagMimetype = pluginElement.type;
5934  }
5935  }
5936 
5937  return {mimetype: tagMimetype, pluginsPage: pluginsPage};
5938 }
5939 
5941 }
5942 
5943 missingPluginInstaller.prototype.installSinglePlugin = function(aEvent){
5944  var missingPluginsArray = {};
5945 
5946  var pluginInfo = getPluginInfo(aEvent.target);
5947  missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
5948 
5949  if (missingPluginsArray) {
5950  window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
5951  "PFSWindow", "chrome,centerscreen,resizable=yes",
5952  {plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
5953  }
5954 
5955  aEvent.stopPropagation();
5956 }
5957 
5958 missingPluginInstaller.prototype.managePlugins = function(aEvent){
5959  BrowserOpenAddonsMgr("plugins");
5960  aEvent.stopPropagation();
5961 }
5962 
5963 missingPluginInstaller.prototype.newMissingPlugin = function(aEvent){
5964  // Since we are expecting also untrusted events, make sure
5965  // that the target is a plugin
5966  if (!(aEvent.target instanceof Components.interfaces.nsIObjectLoadingContent))
5967  return;
5968 
5969  // For broken non-object plugin tags, register a click handler so
5970  // that the user can click the plugin replacement to get the new
5971  // plugin. Object tags can, and often do, deal with that themselves,
5972  // so don't stomp on the page developers toes.
5973 
5974  if (aEvent.type != "PluginBlocklisted" &&
5975  aEvent.type != "PluginOutdated" &&
5976  !(aEvent.target instanceof HTMLObjectElement)) {
5977  aEvent.target.addEventListener("click",
5978  gMissingPluginInstaller.installSinglePlugin,
5979  true);
5980  }
5981 
5982  let hideBarPrefName = aEvent.type == "PluginOutdated" ?
5983  "plugins.hide_infobar_for_outdated_plugin" :
5984  "plugins.hide_infobar_for_missing_plugin";
5985  try {
5986  if (gPrefService.getBoolPref(hideBarPrefName))
5987  return;
5988  } catch (ex) {} // if the pref is missing, treat it as false, which shows the infobar
5989 
5990  var browser = gBrowser.getBrowserForDocument(aEvent.target.ownerDocument
5991  .defaultView.top.document);
5992  if (!browser.missingPlugins)
5993  browser.missingPlugins = {};
5994 
5995  var pluginInfo = getPluginInfo(aEvent.target);
5996 
5997  browser.missingPlugins[pluginInfo.mimetype] = pluginInfo;
5998 
5999  var notificationBox = gBrowser.getNotificationBox(browser);
6000 
6001  // Should only display one of these warnings per page.
6002  // In order of priority, they are: outdated > missing > blocklisted
6003 
6004  // If there is already an outdated plugin notification then do nothing
6005  if (notificationBox.getNotificationWithValue("outdated-plugins"))
6006  return;
6007  var blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
6008  var missingNotification = notificationBox.getNotificationWithValue("missing-plugins");
6009  var priority = notificationBox.PRIORITY_WARNING_MEDIUM;
6010 
6011  function showBlocklistInfo() {
6012  var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
6013  getService(Ci.nsIURLFormatter);
6014  var url = formatter.formatURLPref("extensions.blocklist.detailsURL");
6015  gBrowser.loadOneTab(url, {inBackground: false});
6016  return true;
6017  }
6018 
6019  function showOutdatedPluginsInfo() {
6020  gPrefService.setBoolPref("plugins.update.notifyUser", false);
6021  var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
6022  getService(Ci.nsIURLFormatter);
6023  var url = formatter.formatURLPref("plugins.update.url");
6024  gBrowser.loadOneTab(url, {inBackground: false});
6025  return true;
6026  }
6027 
6028  function showPluginsMissing() {
6029  // get the urls of missing plugins
6030  var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
6031  if (missingPluginsArray) {
6032  window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
6033  "PFSWindow", "chrome,centerscreen,resizable=yes",
6034  {plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
6035  }
6036  }
6037 
6038  if (aEvent.type == "PluginBlocklisted") {
6039  if (blockedNotification || missingNotification)
6040  return;
6041 
6042  let iconURL = "chrome://mozapps/skin/plugins/pluginBlocked-16.png";
6043  let messageString = gNavigatorBundle.getString("blockedpluginsMessage.title");
6044  let buttons = [{
6045  label: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.label"),
6046  accessKey: gNavigatorBundle.getString("blockedpluginsMessage.infoButton.accesskey"),
6047  popup: null,
6048  callback: showBlocklistInfo
6049  }, {
6050  label: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.label"),
6051  accessKey: gNavigatorBundle.getString("blockedpluginsMessage.searchButton.accesskey"),
6052  popup: null,
6053  callback: showOutdatedPluginsInfo
6054  }];
6055 
6056  notificationBox.appendNotification(messageString, "blocked-plugins",
6057  iconURL, priority, buttons);
6058  }
6059  else if (aEvent.type == "PluginOutdated") {
6060  // Cancel any notification about blocklisting/missing plugins
6061  if (blockedNotification)
6062  blockedNotification.close();
6063  if (missingNotification)
6064  missingNotification.close();
6065 
6066  let iconURL = "chrome://mozapps/skin/plugins/pluginOutdated-16.png";
6067  let messageString = gNavigatorBundle.getString("outdatedpluginsMessage.title");
6068  let buttons = [{
6069  label: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.label"),
6070  accessKey: gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.accesskey"),
6071  popup: null,
6072  callback: showOutdatedPluginsInfo
6073  }];
6074 
6075  notificationBox.appendNotification(messageString, "outdated-plugins",
6076  iconURL, priority, buttons);
6077  }
6078  else if (aEvent.type == "PluginNotFound") {
6079  if (missingNotification)
6080  return;
6081 
6082  // Cancel any notification about blocklisting plugins
6083  if (blockedNotification)
6084  blockedNotification.close();
6085 
6086  let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
6087  let messageString = gNavigatorBundle.getString("missingpluginsMessage.title");
6088  let buttons = [{
6089  label: gNavigatorBundle.getString("missingpluginsMessage.button.label"),
6090  accessKey: gNavigatorBundle.getString("missingpluginsMessage.button.accesskey"),
6091  popup: null,
6092  callback: showPluginsMissing
6093  }];
6094 
6095  notificationBox.appendNotification(messageString, "missing-plugins",
6096  iconURL, priority, buttons);
6097  }
6098 }
6099 
6100 missingPluginInstaller.prototype.newDisabledPlugin = function(aEvent){
6101  // Since we are expecting also untrusted events, make sure
6102  // that the target is a plugin
6103  if (!(aEvent.target instanceof Components.interfaces.nsIObjectLoadingContent))
6104  return;
6105 
6106  aEvent.target.addEventListener("click",
6107  gMissingPluginInstaller.managePlugins,
6108  true);
6109 }
6110 
6111 missingPluginInstaller.prototype.refreshBrowser = function(aEvent) {
6112  // browser elements are anonymous so we can't just use target.
6113  var browser = aEvent.originalTarget;
6114  var notificationBox = gBrowser.getNotificationBox(browser);
6115  var notification = notificationBox.getNotificationWithValue("missing-plugins");
6116 
6117  // clear the plugin list, now that at least one plugin has been installed
6118  browser.missingPlugins = null;
6119  if (notification) {
6120  // reset UI
6121  notificationBox.removeNotification(notification);
6122  }
6123  // reload the browser to make the new plugin show.
6124  browser.reload();
6125 }
6126 
6127 var gMissingPluginInstaller = new missingPluginInstaller();
6128 
6130 {
6131  try {
6132  var unicodeConverter = Components
6133  .classes["@mozilla.org/intl/scriptableunicodeconverter"]
6134  .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
6135  unicodeConverter.charset = charset;
6136  str = unicodeConverter.ConvertFromUnicode(str);
6137  return str + unicodeConverter.Finish();
6138  } catch(ex) {
6139  return null;
6140  }
6141 }
6142 
6154  onFeedButtonClick: function(event) {
6155  event.stopPropagation();
6156 
6157  if (event.target.hasAttribute("feed") &&
6158  event.eventPhase == Event.AT_TARGET &&
6159  (event.button == 0 || event.button == 1)) {
6160  this.subscribeToFeed(null, event);
6161  }
6162  },
6163 
6174  buildFeedList: function(menuPopup) {
6175  var feeds = gBrowser.selectedBrowser.feeds;
6176  if (feeds == null) {
6177  // XXX hack -- menu opening depends on setting of an "open"
6178  // attribute, and the menu refuses to open if that attribute is
6179  // set (because it thinks it's already open). onpopupshowing gets
6180  // called after the attribute is unset, and it doesn't get unset
6181  // if we return false. so we unset it here; otherwise, the menu
6182  // refuses to work past this point.
6183  menuPopup.parentNode.removeAttribute("open");
6184  return false;
6185  }
6186 
6187  while (menuPopup.firstChild)
6188  menuPopup.removeChild(menuPopup.firstChild);
6189 
6190  if (feeds.length == 1) {
6191  var feedButton = document.getElementById("feed-button");
6192  if (feedButton)
6193  feedButton.setAttribute("feed", feeds[0].href);
6194  return false;
6195  }
6196 
6197  // Build the menu showing the available feed choices for viewing.
6198  for (var i = 0; i < feeds.length; ++i) {
6199  var feedInfo = feeds[i];
6200  var menuItem = document.createElement("menuitem");
6201  var baseTitle = feedInfo.title || feedInfo.href;
6202  var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
6203  menuItem.setAttribute("class", "feed-menuitem");
6204  menuItem.setAttribute("label", labelStr);
6205  menuItem.setAttribute("feed", feedInfo.href);
6206  menuItem.setAttribute("tooltiptext", feedInfo.href);
6207  menuItem.setAttribute("crop", "center");
6208  menuPopup.appendChild(menuItem);
6209  }
6210  return true;
6211  },
6212 
6226  subscribeToFeed: function(href, event) {
6227  // Just load the feed in the content area to either subscribe or show the
6228  // preview UI
6229  if (!href)
6230  href = event.target.getAttribute("feed");
6231  urlSecurityCheck(href, gBrowser.contentPrincipal,
6232  Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
6233  var feedURI = makeURI(href, document.characterSet);
6234  // Use the feed scheme so X-Moz-Is-Feed will be set
6235  // The value doesn't matter
6236  if (/^https?/.test(feedURI.scheme))
6237  href = "feed:" + href;
6238  this.loadFeed(href, event);
6239  },
6240 
6241  loadFeed: function(href, event) {
6242  var feeds = gBrowser.selectedBrowser.feeds;
6243  try {
6244  openUILink(href, event, false, true, false, null);
6245  }
6246  finally {
6247  // We might default to a livebookmarks modal dialog,
6248  // so reset that if the user happens to click it again
6249  gBrowser.selectedBrowser.feeds = feeds;
6250  }
6251  },
6252 
6257  updateFeeds: function() {
6258  var feedButton = document.getElementById("feed-button");
6259  if (!this._feedMenuitem)
6260  this._feedMenuitem = document.getElementById("subscribeToPageMenuitem");
6261  if (!this._feedMenupopup)
6262  this._feedMenupopup = document.getElementById("subscribeToPageMenupopup");
6263 
6264  var feeds = gBrowser.mCurrentBrowser.feeds;
6265  if (!feeds || feeds.length == 0) {
6266  if (feedButton) {
6267  feedButton.collapsed = true;
6268  feedButton.removeAttribute("feed");
6269  }
6270  this._feedMenuitem.setAttribute("disabled", "true");
6271  this._feedMenupopup.setAttribute("hidden", "true");
6272  this._feedMenuitem.removeAttribute("hidden");
6273  } else {
6274  if (feedButton)
6275  feedButton.collapsed = false;
6276 
6277  if (feeds.length > 1) {
6278  this._feedMenuitem.setAttribute("hidden", "true");
6279  this._feedMenupopup.removeAttribute("hidden");
6280  if (feedButton)
6281  feedButton.removeAttribute("feed");
6282  } else {
6283  if (feedButton)
6284  feedButton.setAttribute("feed", feeds[0].href);
6285 
6286  this._feedMenuitem.setAttribute("feed", feeds[0].href);
6287  this._feedMenuitem.removeAttribute("disabled");
6288  this._feedMenuitem.removeAttribute("hidden");
6289  this._feedMenupopup.setAttribute("hidden", "true");
6290  }
6291  }
6292  },
6293 
6294  addFeed: function(link, targetDoc) {
6295  // find which tab this is for, and set the attribute on the browser
6296  var browserForLink = gBrowser.getBrowserForDocument(targetDoc);
6297  if (!browserForLink) {
6298  // ignore feeds loaded in subframes (see bug 305472)
6299  return;
6300  }
6301 
6302  if (!browserForLink.feeds)
6303  browserForLink.feeds = [];
6304 
6305  browserForLink.feeds.push({ href: link.href, title: link.title });
6306 
6307  if (browserForLink == gBrowser.mCurrentBrowser) {
6308  var feedButton = document.getElementById("feed-button");
6309  if (feedButton)
6310  feedButton.collapsed = false;
6311  }
6312  }
6313 };
6314 
6315 #include browser-places.js
6316 
6317 #include browser-textZoom.js
6318 
6319 #include browser-tabPreviews.js
6320 
6321 XPCOMUtils.defineLazyGetter(this, "Win7Features", function () {
6322 #ifdef XP_WIN
6323 #ifndef WINCE
6324  const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
6325  if (WINTASKBAR_CONTRACTID in Cc &&
6326  Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
6327  let temp = {};
6328  Cu.import("resource://gre/modules/WindowsPreviewPerTab.jsm", temp);
6329  let AeroPeek = temp.AeroPeek;
6330  return {
6331  onOpenWindow: function () {
6332  AeroPeek.onOpenWindow(window);
6333  },
6334  onCloseWindow: function () {
6335  AeroPeek.onCloseWindow(window);
6336  }
6337  };
6338  }
6339 #endif
6340 #endif
6341  return null;
6342 });
6343 
6350 function undoCloseTab(aIndex) {
6351  // wallpaper patch to prevent an unnecessary blank tab (bug 343895)
6352  var blankTabToRemove = null;
6353  if (gBrowser.tabContainer.childNodes.length == 1 &&
6354  !gPrefService.getBoolPref("browser.tabs.autoHide") &&
6355  gBrowser.selectedBrowser.sessionHistory.count < 2 &&
6356  gBrowser.selectedBrowser.currentURI.spec == "about:blank" &&
6357  !gBrowser.selectedBrowser.contentDocument.body.hasChildNodes() &&
6358  !gBrowser.selectedTab.hasAttribute("busy"))
6359  blankTabToRemove = gBrowser.selectedTab;
6360 
6361  var tab = null;
6362  var ss = Cc["@mozilla.org/browser/sessionstore;1"].
6363  getService(Ci.nsISessionStore);
6364  if (ss.getClosedTabCount(window) > (aIndex || 0)) {
6365  tab = ss.undoCloseTab(window, aIndex || 0);
6366 
6367  if (blankTabToRemove)
6368  gBrowser.removeTab(blankTabToRemove);
6369  }
6370 
6371  return tab;
6372 }
6373 
6380 function undoCloseWindow(aIndex) {
6381  let ss = Cc["@mozilla.org/browser/sessionstore;1"].
6382  getService(Ci.nsISessionStore);
6383  let window = null;
6384  if (ss.getClosedWindowCount() > (aIndex || 0))
6385  window = ss.undoCloseWindow(aIndex || 0);
6386 
6387  return window;
6388 }
6389 
6398 function formatURL(aFormat, aIsPref) {
6399  var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
6400  return aIsPref ? formatter.formatURLPref(aFormat) : formatter.formatURL(aFormat);
6401 }
6402 
6408  this._command = document.getElementById("Browser:BookmarkAllTabs");
6409  gBrowser.addEventListener("TabOpen", this, true);
6410  gBrowser.addEventListener("TabClose", this, true);
6411  this._updateCommandState();
6412 }
6413 
6414 BookmarkAllTabsHandler.prototype = {
6415  QueryInterface: function BATH_QueryInterface(aIID) {
6416  if (aIID.equals(Ci.nsIDOMEventListener) ||
6417  aIID.equals(Ci.nsISupports))
6418  return this;
6419 
6420  throw Cr.NS_NOINTERFACE;
6421  },
6422 
6423  _updateCommandState: function BATH__updateCommandState(aTabClose) {
6424  var numTabs = gBrowser.tabContainer.childNodes.length;
6425 
6426  // The TabClose event is fired before the tab is removed from the DOM
6427  if (aTabClose)
6428  numTabs--;
6429 
6430  if (numTabs > 1)
6431  this._command.removeAttribute("disabled");
6432  else
6433  this._command.setAttribute("disabled", "true");
6434  },
6435 
6436  doCommand: function BATH_doCommand() {
6437  PlacesCommandHook.bookmarkCurrentPages();
6438  },
6439 
6440  // nsIDOMEventListener
6441  handleEvent: function(aEvent) {
6442  this._updateCommandState(aEvent.type == "TabClose");
6443  }
6444 };
6445 
6450  // Mode strings used to control CSS display
6451  IDENTITY_MODE_IDENTIFIED : "verifiedIdentity", // High-quality identity information
6452  IDENTITY_MODE_DOMAIN_VERIFIED : "verifiedDomain", // Minimal SSL CA-signed domain verification
6453  IDENTITY_MODE_UNKNOWN : "unknownIdentity", // No trusted identity information
6454  IDENTITY_MODE_MIXED_CONTENT : "unknownIdentity mixedContent", // SSL with unauthenticated content
6455 
6456  // Cache the most recent SSLStatus and Location seen in checkIdentity
6457  _lastStatus : null,
6458  _lastLocation : null,
6459 
6460  // smart getters
6461  get _encryptionLabel () {
6462  delete this._encryptionLabel;
6463  this._encryptionLabel = {};
6464  this._encryptionLabel[this.IDENTITY_MODE_DOMAIN_VERIFIED] =
6465  gNavigatorBundle.getString("identity.encrypted");
6466  this._encryptionLabel[this.IDENTITY_MODE_IDENTIFIED] =
6467  gNavigatorBundle.getString("identity.encrypted");
6468  this._encryptionLabel[this.IDENTITY_MODE_UNKNOWN] =
6469  gNavigatorBundle.getString("identity.unencrypted");
6470  this._encryptionLabel[this.IDENTITY_MODE_MIXED_CONTENT] =
6471  gNavigatorBundle.getString("identity.mixed_content");
6472  return this._encryptionLabel;
6473  },
6474  get _identityPopup () {
6475  delete this._identityPopup;
6476  return this._identityPopup = document.getElementById("identity-popup");
6477  },
6478  get _identityBox () {
6479  delete this._identityBox;
6480  return this._identityBox = document.getElementById("identity-box");
6481  },
6482  get _identityPopupContentBox () {
6483  delete this._identityPopupContentBox;
6484  return this._identityPopupContentBox =
6485  document.getElementById("identity-popup-content-box");
6486  },
6487  get _identityPopupContentHost () {
6488  delete this._identityPopupContentHost;
6489  return this._identityPopupContentHost =
6490  document.getElementById("identity-popup-content-host");
6491  },
6492  get _identityPopupContentOwner () {
6493  delete this._identityPopupContentOwner;
6494  return this._identityPopupContentOwner =
6495  document.getElementById("identity-popup-content-owner");
6496  },
6497  get _identityPopupContentSupp () {
6498  delete this._identityPopupContentSupp;
6499  return this._identityPopupContentSupp =
6500  document.getElementById("identity-popup-content-supplemental");
6501  },
6502  get _identityPopupContentVerif () {
6503  delete this._identityPopupContentVerif;
6504  return this._identityPopupContentVerif =
6505  document.getElementById("identity-popup-content-verifier");
6506  },
6507  get _identityPopupEncLabel () {
6508  delete this._identityPopupEncLabel;
6509  return this._identityPopupEncLabel =
6510  document.getElementById("identity-popup-encryption-label");
6511  },
6512  get _identityIconLabel () {
6513  delete this._identityIconLabel;
6514  return this._identityIconLabel = document.getElementById("identity-icon-label");
6515  },
6516  get _overrideService () {
6517  delete this._overrideService;
6518  return this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
6519  .getService(Ci.nsICertOverrideService);
6520  },
6521 
6526  _cacheElements : function() {
6527  delete this._identityBox;
6528  delete this._identityIconLabel;
6529  this._identityBox = document.getElementById("identity-box");
6530  this._identityIconLabel = document.getElementById("identity-icon-label");
6531  },
6532 
6537  handleMoreInfoClick : function(event) {
6538  displaySecurityInfo();
6539  event.stopPropagation();
6540  },
6541 
6546  getIdentityData : function() {
6547  var result = {};
6548  var status = this._lastStatus.QueryInterface(Components.interfaces.nsISSLStatus);
6549  var cert = status.serverCert;
6550 
6551  // Human readable name of Subject
6552  result.subjectOrg = cert.organization;
6553 
6554  // SubjectName fields, broken up for individual access
6555  if (cert.subjectName) {
6556  result.subjectNameFields = {};
6557  cert.subjectName.split(",").forEach(function(v) {
6558  var field = v.split("=");
6559  this[field[0]] = field[1];
6560  }, result.subjectNameFields);
6561 
6562  // Call out city, state, and country specifically
6563  result.city = result.subjectNameFields.L;
6564  result.state = result.subjectNameFields.ST;
6565  result.country = result.subjectNameFields.C;
6566  }
6567 
6568  // Human readable name of Certificate Authority
6569  result.caOrg = cert.issuerOrganization || cert.issuerCommonName;
6570  result.cert = cert;
6571 
6572  return result;
6573  },
6574 
6584  checkIdentity : function(state, location) {
6585  var currentStatus = gBrowser.securityUI
6586  .QueryInterface(Components.interfaces.nsISSLStatusProvider)
6587  .SSLStatus;
6588  this._lastStatus = currentStatus;
6589  this._lastLocation = location;
6590 
6591  let nsIWebProgressListener = Ci.nsIWebProgressListener;
6592  if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL)
6593  this.setMode(this.IDENTITY_MODE_IDENTIFIED);
6594  else if (state & nsIWebProgressListener.STATE_SECURE_HIGH)
6595  this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
6596  else if (state & nsIWebProgressListener.STATE_IS_BROKEN)
6597  this.setMode(this.IDENTITY_MODE_MIXED_CONTENT);
6598  else
6599  this.setMode(this.IDENTITY_MODE_UNKNOWN);
6600  },
6601 
6605  getEffectiveHost : function() {
6606  // Cache the eTLDService if this is our first time through
6607  if (!this._eTLDService)
6608  this._eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]
6609  .getService(Ci.nsIEffectiveTLDService);
6610  try {
6611  return this._eTLDService.getBaseDomainFromHost(this._lastLocation.hostname);
6612  } catch (e) {
6613  // If something goes wrong (e.g. hostname is an IP address) just fail back
6614  // to the full domain.
6615  return this._lastLocation.hostname;
6616  }
6617  },
6618 
6623  setMode : function(newMode) {
6624  if (!this._identityBox) {
6625  // No identity box means the identity box is not visible, in which
6626  // case there's nothing to do.
6627  return;
6628  }
6629 
6630  this._identityBox.className = newMode;
6631  this.setIdentityMessages(newMode);
6632 
6633  // Update the popup too, if it's open
6634  if (this._identityPopup.state == "open")
6635  this.setPopupMessages(newMode);
6636  },
6637 
6644  setIdentityMessages : function(newMode) {
6645  if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
6646  var iData = this.getIdentityData();
6647 
6648  // It would be sort of nice to use the CN= field in the cert, since that's
6649  // typically what we want here, but thanks to x509 certs being extensible,
6650  // it's not the only place you have to check, there can be more than one domain,
6651  // et cetera, ad nauseum. We know the cert is valid for location.host, so
6652  // let's just use that. Check the pref to determine how much of the verified
6653  // hostname to show
6654  var icon_label = "";
6655  switch (gPrefService.getIntPref("browser.identity.ssl_domain_display")) {
6656  case 2 : // Show full domain
6657  icon_label = this._lastLocation.hostname;
6658  break;
6659  case 1 : // Show eTLD.
6660  icon_label = this.getEffectiveHost();
6661  }
6662 
6663  // We need a port number for all lookups. If one hasn't been specified, use
6664  // the https default
6665  var lookupHost = this._lastLocation.host;
6666  if (lookupHost.indexOf(':') < 0)
6667  lookupHost += ":443";
6668 
6669  // Verifier is either the CA Org, for a normal cert, or a special string
6670  // for certs that are trusted because of a security exception.
6671  var tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
6672  [iData.caOrg]);
6673 
6674  // Check whether this site is a security exception. XPConnect does the right
6675  // thing here in terms of converting _lastLocation.port from string to int, but
6676  // the overrideService doesn't like undefined ports, so make sure we have
6677  // something in the default case (bug 432241).
6678  if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
6679  (this._lastLocation.port || 443),
6680  iData.cert, {}, {}))
6681  tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you");
6682  }
6683  else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
6684  // If it's identified, then we can populate the dialog with credentials
6685  iData = this.getIdentityData();
6686  tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
6687  [iData.caOrg]);
6688  if (iData.country)
6689  icon_label = gNavigatorBundle.getFormattedString("identity.identified.title_with_country",
6690  [iData.subjectOrg, iData.country]);
6691  else
6692  icon_label = iData.subjectOrg;
6693  }
6694  else {
6695  tooltip = gNavigatorBundle.getString("identity.unknown.tooltip");
6696  icon_label = "";
6697  }
6698 
6699  // Push the appropriate strings out to the UI
6700  this._identityBox.tooltipText = tooltip;
6701  this._identityIconLabel.value = icon_label;
6702  },
6703 
6711  setPopupMessages : function(newMode) {
6712 
6713  this._identityPopup.className = newMode;
6714  this._identityPopupContentBox.className = newMode;
6715 
6716  // Set the static strings up front
6717  this._identityPopupEncLabel.textContent = this._encryptionLabel[newMode];
6718 
6719  // Initialize the optional strings to empty values
6720  var supplemental = "";
6721  var verifier = "";
6722 
6723  if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
6724  var iData = this.getIdentityData();
6725  var host = this.getEffectiveHost();
6726  var owner = gNavigatorBundle.getString("identity.ownerUnknown2");
6727  verifier = this._identityBox.tooltipText;
6728  supplemental = "";
6729  }
6730  else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
6731  // If it's identified, then we can populate the dialog with credentials
6732  iData = this.getIdentityData();
6733  host = this.getEffectiveHost();
6734  owner = iData.subjectOrg;
6735  verifier = this._identityBox.tooltipText;
6736 
6737  // Build an appropriate supplemental block out of whatever location data we have
6738  if (iData.city)
6739  supplemental += iData.city + "\n";
6740  if (iData.state && iData.country)
6741  supplemental += gNavigatorBundle.getFormattedString("identity.identified.state_and_country",
6742  [iData.state, iData.country]);
6743  else if (iData.state) // State only
6744  supplemental += iData.state;
6745  else if (iData.country) // Country only
6746  supplemental += iData.country;
6747  }
6748  else {
6749  // These strings will be hidden in CSS anyhow
6750  host = "";
6751  owner = "";
6752  }
6753 
6754  // Push the appropriate strings out to the UI
6755  this._identityPopupContentHost.textContent = host;
6756  this._identityPopupContentOwner.textContent = owner;
6757  this._identityPopupContentSupp.textContent = supplemental;
6758  this._identityPopupContentVerif.textContent = verifier;
6759  },
6760 
6761  hideIdentityPopup : function() {
6762  this._identityPopup.hidePopup();
6763  },
6764 
6768  handleIdentityButtonEvent : function(event) {
6769 
6770  event.stopPropagation();
6771 
6772  if ((event.type == "click" && event.button != 0) ||
6773  (event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
6774  event.keyCode != KeyEvent.DOM_VK_RETURN))
6775  return; // Left click, space or enter only
6776 
6777  // Revert the contents of the location bar, see bug 406779
6778  gURLBar.handleRevert();
6779 
6780  // Make sure that the display:none style we set in xul is removed now that
6781  // the popup is actually needed
6782  this._identityPopup.hidden = false;
6783 
6784  // Tell the popup to consume dismiss clicks, to avoid bug 395314
6785  this._identityPopup.popupBoxObject
6786  .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
6787 
6788  // Update the popup strings
6789  this.setPopupMessages(this._identityBox.className);
6790 
6791  // Make sure the identity popup hangs toward the middle of the location bar
6792  // in RTL builds
6793  var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_end' : 'after_start';
6794 
6795  // Add the "open" attribute to the identity box for styling
6796  this._identityBox.setAttribute("open", "true");
6797  var self = this;
6798  this._identityPopup.addEventListener("popuphidden", function (e) {
6799  e.currentTarget.removeEventListener("popuphidden", arguments.callee, false);
6800  self._identityBox.removeAttribute("open");
6801  }, false);
6802 
6803  // Now open the popup, anchored off the primary chrome element
6804  this._identityPopup.openPopup(this._identityBox, position);
6805  }
6806 };
6807 
6811 
6812  _panel: null,
6813  _activeStr: null,
6814  _pausedStr: null,
6815  _lastTime: Infinity,
6816  _listening: false,
6817 
6818  get DownloadUtils() {
6819  delete this.DownloadUtils;
6820  Cu.import("resource://gre/modules/DownloadUtils.jsm", this);
6821  return this.DownloadUtils;
6822  },
6823 
6826 
6830  init: function DMP_init() {
6831  // Initialize "private" member variables
6832  this._panel = document.getElementById("download-monitor");
6833 
6834  // Cache the status strings
6835  this._activeStr = gNavigatorBundle.getString("activeDownloads");
6836  this._pausedStr = gNavigatorBundle.getString("pausedDownloads");
6837 
6838  gDownloadMgr.addListener(this);
6839  this._listening = true;
6840 
6841  this.updateStatus();
6842  },
6843 
6844  uninit: function DMP_uninit() {
6845  if (this._listening)
6846  gDownloadMgr.removeListener(this);
6847  },
6848 
6849  inited: function DMP_inited() {
6850  return this._panel != null;
6851  },
6852 
6856  updateStatus: function DMP_updateStatus() {
6857  if (!this.inited())
6858  return;
6859 
6860  let numActive = gDownloadMgr.activeDownloadCount;
6861 
6862  // Hide the panel and reset the "last time" if there's no downloads
6863  if (numActive == 0) {
6864  this._panel.hidden = true;
6865  this._lastTime = Infinity;
6866 
6867  return;
6868  }
6869 
6870  // Find the download with the longest remaining time
6871  let numPaused = 0;
6872  let maxTime = -Infinity;
6873  let dls = gDownloadMgr.activeDownloads;
6874  while (dls.hasMoreElements()) {
6875  let dl = dls.getNext().QueryInterface(Ci.nsIDownload);
6876  if (dl.state == gDownloadMgr.DOWNLOAD_DOWNLOADING) {
6877  // Figure out if this download takes longer
6878  if (dl.speed > 0 && dl.size > 0)
6879  maxTime = Math.max(maxTime, (dl.size - dl.amountTransferred) / dl.speed);
6880  else
6881  maxTime = -1;
6882  }
6883  else if (dl.state == gDownloadMgr.DOWNLOAD_PAUSED)
6884  numPaused++;
6885  }
6886 
6887  // Get the remaining time string and last sec for time estimation
6888  let timeLeft;
6889  [timeLeft, this._lastTime] =
6890  this.DownloadUtils.getTimeLeft(maxTime, this._lastTime);
6891 
6892  // Figure out how many downloads are currently downloading
6893  let numDls = numActive - numPaused;
6894  let status = this._activeStr;
6895 
6896  // If all downloads are paused, show the paused message instead
6897  if (numDls == 0) {
6898  numDls = numPaused;
6899  status = this._pausedStr;
6900  }
6901 
6902  // Get the correct plural form and insert the number of downloads and time
6903  // left message if necessary
6904  status = PluralForm.get(numDls, status);
6905  status = status.replace("#1", numDls);
6906  status = status.replace("#2", timeLeft);
6907 
6908  // Update the panel and show it
6909  this._panel.label = status;
6910  this._panel.hidden = false;
6911  },
6912 
6915 
6919  onProgressChange: function() {
6920  this.updateStatus();
6921  },
6922 
6926  onDownloadStateChange: function() {
6927  this.updateStatus();
6928  },
6929 
6930  onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload) {
6931  },
6932 
6933  onSecurityChange: function(aWebProgress, aRequest, aState, aDownload) {
6934  },
6935 
6938 
6939  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadProgressListener]),
6940 };
6941 
6942 function getNotificationBox(aWindow) {
6943  var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
6944  if (foundBrowser)
6945  return gBrowser.getNotificationBox(foundBrowser)
6946  return null;
6947 };
6948 
6949 /* DEPRECATED */
6950 function getBrowser() gBrowser;
6951 function getNavToolbox() gNavToolbox;
6952 
6954  _observerService: null,
6955  _privateBrowsingService: null,
6956  _searchBarValue: null,
6957  _findBarValue: null,
6958 
6959  init: function PBUI_init() {
6960  this._observerService = Cc["@mozilla.org/observer-service;1"].
6961  getService(Ci.nsIObserverService);
6962  this._observerService.addObserver(this, "private-browsing", false);
6963  this._observerService.addObserver(this, "private-browsing-transition-complete", false);
6964 
6965  this._privateBrowsingService = Cc["@mozilla.org/privatebrowsing;1"].
6966  getService(Ci.nsIPrivateBrowsingService);
6967 
6968  if (this.privateBrowsingEnabled)
6969  this.onEnterPrivateBrowsing(true);
6970  },
6971 
6972  uninit: function PBUI_unint() {
6973  this._observerService.removeObserver(this, "private-browsing");
6974  this._observerService.removeObserver(this, "private-browsing-transition-complete");
6975  },
6976 
6977  get _disableUIOnToggle PBUI__disableUIOnTogle() {
6978  if (this._privateBrowsingService.autoStarted)
6979  return false;
6980 
6981  try {
6982  return !gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session");
6983  }
6984  catch (e) {
6985  return true;
6986  }
6987  },
6988 
6989  observe: function PBUI_observe(aSubject, aTopic, aData) {
6990  if (aTopic == "private-browsing") {
6991  if (aData == "enter")
6992  this.onEnterPrivateBrowsing();
6993  else if (aData == "exit")
6994  this.onExitPrivateBrowsing();
6995  }
6996  else if (aTopic == "private-browsing-transition-complete") {
6997  if (this._disableUIOnToggle) {
6998  // use setTimeout here in order to make the code testable
6999  setTimeout(function() {
7000  document.getElementById("Tools:PrivateBrowsing")
7001  .removeAttribute("disabled");
7002  }, 0);
7003  }
7004  }
7005  },
7006 
7007  _shouldEnter: function PBUI__shouldEnter() {
7008  try {
7009  // Never prompt if the session is not going to be closed, or if user has
7010  // already requested not to be prompted.
7011  if (gPrefService.getBoolPref("browser.privatebrowsing.dont_prompt_on_enter") ||
7012  gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session"))
7013  return true;
7014  }
7015  catch (ex) { }
7016 
7017  var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
7018  getService(Ci.nsIStringBundleService);
7019  var pbBundle = bundleService.createBundle("chrome://browser/locale/browser.properties");
7020  var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
7021 
7022  var appName = brandBundle.GetStringFromName("brandShortName");
7023 # On Mac, use the header as the title.
7024 #ifdef XP_MACOSX
7025  var dialogTitle = pbBundle.GetStringFromName("privateBrowsingMessageHeader");
7026  var header = "";
7027 #else
7028  var dialogTitle = pbBundle.GetStringFromName("privateBrowsingDialogTitle");
7029  var header = pbBundle.GetStringFromName("privateBrowsingMessageHeader") + "\n\n";
7030 #endif
7031  var message = pbBundle.formatStringFromName("privateBrowsingMessage", [appName], 1);
7032 
7033  var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
7034  getService(Ci.nsIPromptService);
7035 
7036  var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
7037  promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
7038  promptService.BUTTON_POS_0_DEFAULT;
7039 
7040  var neverAsk = {value:false};
7041  var button0Title = pbBundle.GetStringFromName("privateBrowsingYesTitle");
7042  var button1Title = pbBundle.GetStringFromName("privateBrowsingNoTitle");
7043  var neverAskText = pbBundle.GetStringFromName("privateBrowsingNeverAsk");
7044 
7045  var result;
7046  var choice = promptService.confirmEx(null, dialogTitle, header + message,
7047  flags, button0Title, button1Title, null,
7048  neverAskText, neverAsk);
7049 
7050  switch (choice) {
7051  case 0: // Start Private Browsing
7052  result = true;
7053  if (neverAsk.value)
7054  gPrefService.setBoolPref("browser.privatebrowsing.dont_prompt_on_enter", true);
7055  break;
7056  case 1: // Keep
7057  result = false;
7058  break;
7059  }
7060 
7061  return result;
7062  },
7063 
7064  onEnterPrivateBrowsing: function PBUI_onEnterPrivateBrowsing(aOnWindowOpen) {
7065  if (BrowserSearch.searchBar)
7066  this._searchBarValue = BrowserSearch.searchBar.textbox.value;
7067 
7068  if (gFindBar)
7069  this._findBarValue = gFindBar.getElement("findbar-textbox").value;
7070 
7071  this._setPBMenuTitle("stop");
7072 
7073  document.getElementById("menu_import").setAttribute("disabled", "true");
7074 
7075  // Disable the Clear Recent History... menu item when in PB mode
7076  // temporary fix until bug 463607 is fixed
7077  document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
7078 
7079  if (this._privateBrowsingService.autoStarted) {
7080  // Disable the menu item in auto-start mode
7081  document.getElementById("privateBrowsingItem")
7082  .setAttribute("disabled", "true");
7083  document.getElementById("Tools:PrivateBrowsing")
7084  .setAttribute("disabled", "true");
7085  }
7086  else if (window.location.href == getBrowserURL()) {
7087  // Adjust the window's title
7088  let docElement = document.documentElement;
7089  docElement.setAttribute("title",
7090  docElement.getAttribute("title_privatebrowsing"));
7091  docElement.setAttribute("titlemodifier",
7092  docElement.getAttribute("titlemodifier_privatebrowsing"));
7093  docElement.setAttribute("browsingmode", "private");
7094  gBrowser.updateTitlebar();
7095  }
7096 
7097  setTimeout(function () {
7098  DownloadMonitorPanel.updateStatus();
7099  }, 0);
7100 
7101  if (!aOnWindowOpen && this._disableUIOnToggle)
7102  document.getElementById("Tools:PrivateBrowsing")
7103  .setAttribute("disabled", "true");
7104  },
7105 
7106  onExitPrivateBrowsing: function PBUI_onExitPrivateBrowsing() {
7107  if (BrowserSearch.searchBar) {
7108  let searchBox = BrowserSearch.searchBar.textbox;
7109  searchBox.reset();
7110  if (this._searchBarValue) {
7111  searchBox.value = this._searchBarValue;
7112  this._searchBarValue = null;
7113  }
7114  }
7115 
7116  document.getElementById("menu_import").removeAttribute("disabled");
7117 
7118  // Re-enable the Clear Recent History... menu item on exit of PB mode
7119  // temporary fix until bug 463607 is fixed
7120  document.getElementById("Tools:Sanitize").removeAttribute("disabled");
7121 
7122  if (gFindBar) {
7123  let findbox = gFindBar.getElement("findbar-textbox");
7124  findbox.reset();
7125  if (this._findBarValue) {
7126  findbox.value = this._findBarValue;
7127  this._findBarValue = null;
7128  }
7129  }
7130 
7131  this._setPBMenuTitle("start");
7132 
7133  if (window.location.href == getBrowserURL()) {
7134  // Adjust the window's title
7135  let docElement = document.documentElement;
7136  docElement.setAttribute("title",
7137  docElement.getAttribute("title_normal"));
7138  docElement.setAttribute("titlemodifier",
7139  docElement.getAttribute("titlemodifier_normal"));
7140  docElement.setAttribute("browsingmode", "normal");
7141  }
7142 
7143  // Enable the menu item in after exiting the auto-start mode
7144  document.getElementById("privateBrowsingItem")
7145  .removeAttribute("disabled");
7146  document.getElementById("Tools:PrivateBrowsing")
7147  .removeAttribute("disabled");
7148 
7149  gLastOpenDirectory.reset();
7150 
7151  setTimeout(function () {
7152  DownloadMonitorPanel.updateStatus();
7153  }, 0);
7154 
7155  if (this._disableUIOnToggle)
7156  document.getElementById("Tools:PrivateBrowsing")
7157  .setAttribute("disabled", "true");
7158  },
7159 
7160  _setPBMenuTitle: function PBUI__setPBMenuTitle(aMode) {
7161  let pbMenuItem = document.getElementById("privateBrowsingItem");
7162  pbMenuItem.setAttribute("label", pbMenuItem.getAttribute(aMode + "label"));
7163  pbMenuItem.setAttribute("accesskey", pbMenuItem.getAttribute(aMode + "accesskey"));
7164  },
7165 
7166  toggleMode: function PBUI_toggleMode() {
7167  // prompt the users on entering the private mode, if needed
7168  if (!this.privateBrowsingEnabled)
7169  if (!this._shouldEnter())
7170  return;
7171 
7172  this._privateBrowsingService.privateBrowsingEnabled =
7173  !this.privateBrowsingEnabled;
7174  },
7175 
7176  get privateBrowsingEnabled PBUI_get_privateBrowsingEnabled() {
7177  return this._privateBrowsingService.privateBrowsingEnabled;
7178  }
7179 };
7180 
7182  domain: "browser.urlbar.",
7183 
7184  observe: function UBET_observe(aSubject, aTopic, aPrefName) {
7185  if (aTopic == "nsPref:changed") {
7186  switch (aPrefName) {
7187  case "browser.urlbar.autocomplete.enabled":
7188  case "browser.urlbar.default.behavior":
7189  gURLBar.emptyText = this.value;
7190  break;
7191  }
7192  }
7193  },
7194 
7195  get value UBET_get_value() {
7196  let type = "none";
7197  if (gPrefService.getBoolPref("browser.urlbar.autocomplete.enabled")) {
7198  // Bottom 2 bits of default.behavior specify history/bookmark
7199  switch (gPrefService.getIntPref("browser.urlbar.default.behavior") & 3) {
7200  case 0:
7201  type = "bookmarkhistory";
7202  break;
7203  case 1:
7204  type = "history";
7205  break;
7206  case 2:
7207  type = "bookmark";
7208  break;
7209  }
7210  }
7211  return gURLBar.getAttribute(type + "emptytext");
7212  }
7213 };
7214 
7215 var LightWeightThemeWebInstaller = {
7216  handleEvent: function (event) {
7217  switch (event.type) {
7218  case "InstallBrowserTheme":
7219  case "PreviewBrowserTheme":
7220  case "ResetBrowserThemePreview":
7221  // ignore requests from background tabs
7222  if (event.target.ownerDocument.defaultView.top != content)
7223  return;
7224  }
7225  switch (event.type) {
7226  case "InstallBrowserTheme":
7227  this._installRequest(event);
7228  break;
7229  case "PreviewBrowserTheme":
7230  this._preview(event);
7231  break;
7232  case "ResetBrowserThemePreview":
7233  this._resetPreview(event);
7234  break;
7235  case "pagehide":
7236  case "TabSelect":
7237  this._resetPreview();
7238  break;
7239  }
7240  },
7241 
7242  get _manager () {
7243  var temp = {};
7244  Cu.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
7245  delete this._manager;
7246  return this._manager = temp.LightweightThemeManager;
7247  },
7248 
7249  _installRequest: function (event) {
7250  var node = event.target;
7251  var data = this._getThemeFromNode(node);
7252  if (!data)
7253  return;
7254 
7255  if (this._isAllowed(node)) {
7256  this._install(data);
7257  return;
7258  }
7259 
7260  var allowButtonText =
7261  gNavigatorBundle.getString("lwthemeInstallRequest.allowButton");
7262  var allowButtonAccesskey =
7263  gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey");
7264  var message =
7265  gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message",
7266  [node.ownerDocument.location.host]);
7267  var buttons = [{
7268  label: allowButtonText,
7269  accessKey: allowButtonAccesskey,
7270  callback: function () {
7271  LightWeightThemeWebInstaller._install(data);
7272  }
7273  }];
7274 
7275  this._removePreviousNotifications();
7276 
7277  var notificationBox = gBrowser.getNotificationBox();
7278  var notificationBar =
7279  notificationBox.appendNotification(message, "lwtheme-install-request", "",
7280  notificationBox.PRIORITY_INFO_MEDIUM,
7281  buttons);
7282  notificationBar.persistence = 1;
7283  },
7284 
7285  _install: function (newTheme) {
7286  var previousTheme = this._manager.currentTheme;
7287  this._manager.currentTheme = newTheme;
7288  if (this._manager.currentTheme &&
7289  this._manager.currentTheme.id == newTheme.id)
7290  this._postInstallNotification(newTheme, previousTheme);
7291  },
7292 
7293  _postInstallNotification: function (newTheme, previousTheme) {
7294  function text(id) {
7295  return gNavigatorBundle.getString("lwthemePostInstallNotification." + id);
7296  }
7297 
7298  var buttons = [{
7299  label: text("undoButton"),
7300  accessKey: text("undoButton.accesskey"),
7301  callback: function () {
7302  LightWeightThemeWebInstaller._manager.forgetUsedTheme(newTheme.id);
7303  LightWeightThemeWebInstaller._manager.currentTheme = previousTheme;
7304  }
7305  }, {
7306  label: text("manageButton"),
7307  accessKey: text("manageButton.accesskey"),
7308  callback: function () {
7309  BrowserOpenAddonsMgr("themes");
7310  }
7311  }];
7312 
7313  this._removePreviousNotifications();
7314 
7315  var notificationBox = gBrowser.getNotificationBox();
7316  var notificationBar =
7317  notificationBox.appendNotification(text("message"),
7318  "lwtheme-install-notification", "",
7319  notificationBox.PRIORITY_INFO_MEDIUM,
7320  buttons);
7321  notificationBar.persistence = 1;
7322  notificationBar.timeout = Date.now() + 20000; // 20 seconds
7323  },
7324 
7325  _removePreviousNotifications: function () {
7326  var box = gBrowser.getNotificationBox();
7327 
7328  ["lwtheme-install-request",
7329  "lwtheme-install-notification"].forEach(function (value) {
7330  var notification = box.getNotificationWithValue(value);
7331  if (notification)
7332  box.removeNotification(notification);
7333  });
7334  },
7335 
7336  _previewWindow: null,
7337  _preview: function (event) {
7338  if (!this._isAllowed(event.target))
7339  return;
7340 
7341  var data = this._getThemeFromNode(event.target);
7342  if (!data)
7343  return;
7344 
7345  this._resetPreview();
7346 
7347  this._previewWindow = event.target.ownerDocument.defaultView;
7348  this._previewWindow.addEventListener("pagehide", this, true);
7349  gBrowser.tabContainer.addEventListener("TabSelect", this, false);
7350 
7351  this._manager.previewTheme(data);
7352  },
7353 
7354  _resetPreview: function (event) {
7355  if (!this._previewWindow ||
7356  event && !this._isAllowed(event.target))
7357  return;
7358 
7359  this._previewWindow.removeEventListener("pagehide", this, true);
7360  this._previewWindow = null;
7361  gBrowser.tabContainer.removeEventListener("TabSelect", this, false);
7362 
7363  this._manager.resetPreview();
7364  },
7365 
7366  _isAllowed: function (node) {
7367  var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
7368 
7369  var prefs = [["xpinstall.whitelist.add", pm.ALLOW_ACTION],
7370  ["xpinstall.whitelist.add.36", pm.ALLOW_ACTION],
7371  ["xpinstall.blacklist.add", pm.DENY_ACTION]];
7372  prefs.forEach(function ([pref, permission]) {
7373  try {
7374  var hosts = gPrefService.getCharPref(pref);
7375  } catch (e) {}
7376 
7377  if (hosts) {
7378  hosts.split(",").forEach(function (host) {
7379  pm.add(makeURI("http://" + host), "install", permission);
7380  });
7381 
7382  gPrefService.setCharPref(pref, "");
7383  }
7384  });
7385 
7386  var uri = node.ownerDocument.documentURIObject;
7387  return pm.testPermission(uri, "install") == pm.ALLOW_ACTION;
7388  },
7389 
7390  _getThemeFromNode: function (node) {
7391  return this._manager.parseTheme(node.getAttribute("data-browsertheme"),
7392  node.baseURI);
7393  }
7394 }
function start(ch)
var D
var PlacesUIUtils
Definition: utils.js:85
function A
function CreateMenu(node)
Definition: browser.js:5197
function UpdateBackForwardCommands(aWebNavigation)
Definition: browser.js:172
function BrowserCustomizeToolbar()
Definition: browser.js:3357
classDescription entry
Definition: FeedWriter.js:1427
function PageProxySetIcon(aURL)
Definition: browser.js:2332
function BrowserTryToCloseWindow()
Definition: browser.js:1924
let gInitialPages
Definition: browser.js:141
const Cc
var args
Definition: alert.js:8
function onFullScreen()
Definition: browser.js:2525
var FullScreen
Definition: browser.js:3534
function openNewTabWith(aURL, aDocument, aPostData, aEvent, aAllowThirdPartyFixup, aReferrer)
function isBidiEnabled()
function PageProxyClickHandler(aEvent)
Definition: browser.js:2348
function warnAboutClosingWindow()
Definition: browser.js:5735
nsString encodeURIComponent(const nsString &c)
const WINTASKBAR_CONTRACTID
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
function MultiplexHandler(event)
Definition: browser.js:5072
function getShortcutOrURI(aURL, aPostDataRef)
Definition: browser.js:1960
browser docShell
function UpdatePageProxyState()
Definition: browser.js:2302
function BrowserReload()
function mimeTypeIsTextBased(aMimeType)
Definition: browser.js:3839
function gatherTextUnder(root)
function getAllStyleSheets(frameset)
Definition: browser.js:5217
var FullZoom
var FeedHandler
Definition: browser.js:6147
function openUILinkIn(url, where, allowThirdPartyFixup, postData, referrerUrl)
var menuItem
Definition: FeedWriter.js:970
menuItem id
Definition: FeedWriter.js:971
onPageChanged aValue
Definition: FeedWriter.js:1395
var windows
function BrowserShutdown()
Definition: browser.js:1382
const gSessionHistoryObserver
Definition: browser.js:276
function BrowserFullScreen()
Definition: browser.js:2520
function missingPluginInstaller()
Definition: browser.js:5940
var pref
Definition: openLocation.js:44
var PlacesStarButton
var _
function asyncOpenWebPanel(event)
Definition: browser.js:4801
var gChromeState
Definition: browser.js:86
function doc() browser.contentDocument
saveStateDelayed aDelay
function BrowserReloadSkipCache()
function getTopWin()
sbDeviceFirmwareAutoCheckForUpdate prototype flags
var gEditUIVisible
Definition: browser.js:92
function BrowserBack(aEvent, aIgnoreAlt)
function BrowserHandleShiftBackspace()
dndDefaultHandler_module onDragOver
var MailIntegration
Definition: browser.js:5773
#define F(a)
function getMarkupDocumentViewer()
Definition: browser.js:2635
var event
__defineSetter__("PluralForm", function(val){delete this.PluralForm;return this.PluralForm=val;})
function BrowserCloseTabOrWindow()
Definition: browser.js:1911
var browserDragAndDrop
Definition: browser.js:2703
function makeURLAbsolute(aBase, aUrl)
var gProgressCollapseTimer
Definition: browser.js:78
function UpdateUrlbarSearchSplitterState()
Definition: browser.js:2253
function undoCloseWindow(aIndex)
Definition: browser.js:6380
function formatURL(aFormat, aIsPref)
Definition: browser.js:6398
function getBoolPref(prefname, def)
function stylesheetFillPopup(menuPopup)
Definition: browser.js:5226
var gSidebarCommand
Definition: browser.js:79
function getPPBrowser()
Definition: browser.js:2630
function stylesheetSwitchFrame(frame, title)
Definition: browser.js:5285
sidebarFactory createInstance
Definition: nsSidebar.js:351
sbOSDControlService prototype QueryInterface
function stylesheetInFrame(frame, title)
Definition: browser.js:5280
function getBrowserSelection(aCharLen)
Definition: browser.js:4749
function updateEditUIVisibility()
Definition: browser.js:3493
var gBidiUI
const char * types
var header
Definition: FeedWriter.js:953
var ioService
function BrowserOpenAddonsMgr(aPane)
Definition: browser.js:5805
let gURLBarEmptyText
Definition: browser.js:7181
__defineGetter__("gPrefService", function(){delete this.gPrefService;return this.gPrefService=Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch2).QueryInterface(Ci.nsIPrefService);})
function convertFromUnicode(charset, str)
Definition: browser.js:6129
function openTopWin(url)
var Event
function getBrowser() gBrowser
function contentAreaClick(event, fieldNormalClicks)
Definition: browser.js:4819
function HandleAppCommandEvent(evt)
Definition: browser.js:1071
function getContentAreaFrameCount()
Definition: browser.js:163
function BrowserPageInfo(doc, initialTab, imageElement)
Definition: browser.js:2128
var tab
getService(Ci.sbIFaceplateManager)
function pageShowEventHandlers(event)
Definition: browser.js:151
let window
function C(H)
var BrowserOffline
Definition: browser.js:5313
function SelectDetector(event, doReload)
Definition: browser.js:5092
SessionStoreService aDocShell
var firstTime
function BrowserViewSourceOfDocument(aDocument)
Definition: browser.js:2080
function BrowserOnCommand(event)
Definition: browser.js:2375
Sanitizer prefDomain
Definition: sanitize.js:388
function onExitPrintPreview()
Definition: browser.js:2623
_window init
Definition: FeedWriter.js:1144
PRUint32 & offset
function getNotificationBox(aWindow)
Definition: browser.js:6942
function UpdateMenus(event)
Definition: browser.js:5186
this _contentSandbox label
Definition: FeedWriter.js:814
var t
function BookmarkThisTab()
Definition: browser.js:271
function loadOneOrMoreURIs(aURIString)
var count
Definition: test_bug7406.js:32
_collectFormDataForFrame aDocument
function setStyleDisabled(disabled)
Definition: browser.js:5308
let Cu
Definition: browser.js:68
const nsIWebNavigation
Definition: browser.js:71
var ctrlTab
function BrowserOpenFileWindow()
Definition: browser.js:1891
function onEnterPrintPreview()
Definition: browser.js:2617
function makeURI(aURLSpec, aCharset)
Definition: FeedWriter.js:71
function isElementVisible(aElement)
return e ctrlKey(chr<' '||!chars||chars.indexOf(chr)>-1)
var gAutoHideTabbarPrefListener
Definition: browser.js:88
function UpdateCurrentCharset()
Definition: browser.js:5142
let gDownloadMgr
Definition: browser.js:81
var gBookmarkAllTabsHandler
Definition: browser.js:89
function escapeNameValuePair(aName, aValue, aIsFormUrlEncoded)
Definition: browser.js:5826
Element Properties href
const nsIChannel
function num(elem, prop)
const nsIFilePicker
function BrowserForward(aEvent, aIgnoreAlt)
function handleLinkClick(event, href, linkNode)
Definition: browser.js:4944
function openUILink(url, e, ignoreButton, ignoreAlt, allowKeywordFixup, postData, referrerUrl)
var LocationBarHelpers
Definition: browser.js:2280
function getBrowserURL()
this _dialogInput val(dateText)
var contentAreaDNDObserver
Definition: browser.js:5029
function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType)
Definition: browser.js:2031
var gInPrintPreviewMode
Definition: browser.js:80
aWindow setTimeout(function(){_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap);}, 0)
function FillInHTMLTooltip(tipElement)
Definition: browser.js:2653
function isValidFeed(aLink, aPrincipal, aIsFeed)
const gXPInstallObserver
Definition: browser.js:571
function stylesheetSwitchAll(frameset, title)
Definition: browser.js:5300
function B
function SetForcedDetector(doReload)
Definition: browser.js:5116
grep callback
function BrowserReloadWithFlags(reloadFlags)
Definition: browser.js:2539
function openWebPanel(aTitle, aURI)
Definition: browser.js:4776
function BrowserSetForcedDetector(doReload)
Definition: browser.js:5135
let gPrivateBrowsingUI
Definition: browser.js:6953
function BookmarkAllTabsHandler()
Definition: browser.js:6407
function BrowserImport()
Definition: browser.js:2354
const gPopupBlockerObserver
Definition: browser.js:324
GstMessage * message
function WindowIsClosing()
Definition: browser.js:5713
return null
Definition: FeedWriter.js:1143
var safebrowsing
Definition: sb-loader.js:37
function openAdvancedPreferences(tabID)
function whereToOpenLink(e, ignoreButton, ignoreAlt)
BogusChannel prototype owner
let node
return!aWindow arguments!aWindow arguments[0]
var gPrefService
Definition: overlay.js:34
var os
var gPrevCharset
Definition: browser.js:75
function BrowserHandleBackspace()
let DownloadMonitorPanel
Definition: browser.js:6808
var tabPreviews
let gGestureSupport
Definition: browser.js:675
_updateCookies aName
const cacheService
Definition: pageInfo.js:195
function loadURI(uri, referrer, postData, allowThirdPartyFixup)
Definition: browser.js:1946
function url(spec)
var uri
Definition: FeedWriter.js:1135
_updateTextAndScrollDataForTab aBrowser
let Ci
Definition: browser.js:67
var prefs
Definition: FeedWriter.js:1169
countRef value
Definition: FeedWriter.js:1423
const XLinkNS
Definition: pageInfo.js:219
var gProxyFavIcon
Definition: browser.js:76
function BrowserSetForcedCharacterSet(aCharset)
Definition: browser.js:5126
function middleMousePaste(event)
Definition: browser.js:4994
return aWindow document documentElement getAttribute(aAttribute)||dimension
var OfflineApps
Definition: browser.js:5417
this _dialogInput this _pos[1] px
function BrowserToolboxCustomizeDone(aToolboxChanged)
Definition: browser.js:3403
function toggle(toShow, toHide, data, clickedActive, down)
const Cr
let promptService
function SetPageProxyState(aState)
Definition: browser.js:2308
function AutoHideTabbarPrefListener()
Definition: browser.js:1513
function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer)
if(DEBUG_DATAREMOTES)
observe topic
Definition: FeedWriter.js:1326
var gLastValidURLStr
Definition: browser.js:77
var gWebPanelURI
Definition: browser.js:4775
function BrowserToolboxCustomizeChange()
Definition: browser.js:3469
function URLBarSetURI(aURI, aValid)
Definition: browser.js:2201
ContinuingWebProgressListener prototype onStateChange
var gNavigatorBundle
function AddKeywordForSearchField()
Definition: browser.js:5834
var gCharsetMenu
Definition: browser.js:73
function getShellService()
var ios
Definition: head_feeds.js:5
var gContextMenu
Definition: browser.js:84
var hidden
function msg
var gIdentityHandler
Definition: browser.js:6449
var allTabs
function delayedStartup(isLoadingBlank, mustLoadSidebar)
Definition: browser.js:1182
function readFromClipboard()
Definition: browser.js:2045
var browser
Definition: openLocation.js:42
function BrowserStartup()
Definition: browser.js:913
restoreWindow aState
function SetForcedCharset(charset)
Definition: browser.js:5121
function losslessDecodeURI(aURI)
Definition: browser.js:2223
function getMeOutOfHere()
Definition: browser.js:2503
observe data
Definition: FeedWriter.js:1329
function SwitchDocumentDirection(aWindow)
Definition: browser.js:5899
function getPluginInfo(pluginElement)
Definition: browser.js:5905
function getNavToolbox() gNavToolbox
function uninit(aEvent)
Definition: aboutDialog.js:89
_getSelectedPageStyle s i
function getWebNavigation()
Definition: browser.js:2530
var brandBundle
Definition: xpInstallHat.js:37
function prepareForStartup()
Definition: browser.js:1100
GstMessage gpointer data sbGStreamerMessageHandler * handler
function PageProxyClearIcon()
Definition: browser.js:2343
function UpdateCharsetDetector()
Definition: browser.js:5161
_updateTextAndScrollDataForFrame aData
function clickHandler(event)
function next()
function toggleAffectedChrome(aHide)
Definition: browser.js:2560
var gLastBrowserCharset
Definition: browser.js:74
var file
sbDeviceFirmwareAutoCheckForUpdate prototype observe
converter charset
function undoCloseTab(aIndex)
Definition: browser.js:6350
function findChildShell(aDocument, aDocShell, aSoughtURI)
Definition: browser.js:306
function charsetLoadListener(event)
Definition: browser.js:5203
function toOpenWindowByType(inType, uri, features)
var XULBrowserWindow
Definition: browser.js:3848