new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-captivePortal.js
@@ -0,0 +1,253 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+XPCOMUtils.defineLazyServiceGetter(this, "cps",
+ "@mozilla.org/network/captive-portal-service;1",
+ "nsICaptivePortalService");
+
+var CaptivePortalWatcher = {
+ /**
+ * This constant is chosen to be large enough for a portal recheck to complete,
+ * and small enough that the delay in opening a tab isn't too noticeable.
+ * Please see comments for _delayedCaptivePortalDetected for more details.
+ */
+ PORTAL_RECHECK_DELAY_MS: 150,
+
+ // This is the value used to identify the captive portal notification.
+ PORTAL_NOTIFICATION_VALUE: "captive-portal-detected",
+
+ // This holds a weak reference to the captive portal tab so that we
+ // don't leak it if the user closes it.
+ _captivePortalTab: null,
+
+ _initialized: false,
+
+ /**
+ * If a portal is detected when we don't have focus, we first wait for focus
+ * and then add the tab if, after a recheck, the portal is still active. This
+ * is set to true while we wait so that in the unlikely event that we receive
+ * another notification while waiting, we don't do things twice.
+ */
+ _delayedCaptivePortalDetectedInProgress: false,
+
+ // In the situation above, this is set to true while we wait for the recheck.
+ // This flag exists so that tests can appropriately simulate a recheck.
+ _waitingForRecheck: false,
+
+ get canonicalURL() {
+ return Services.prefs.getCharPref("captivedetect.canonicalURL");
+ },
+
+ init() {
+ Services.obs.addObserver(this, "captive-portal-login", false);
+ Services.obs.addObserver(this, "captive-portal-login-abort", false);
+ Services.obs.addObserver(this, "captive-portal-login-success", false);
+ this._initialized = true;
+
+ if (cps.state == cps.LOCKED_PORTAL) {
+ // A captive portal has already been detected.
+ this._captivePortalDetected();
+ return;
+ }
+
+ cps.recheckCaptivePortal();
+ },
+
+ uninit() {
+ if (!this._initialized) {
+ return;
+ }
+ Services.obs.removeObserver(this, "captive-portal-login");
+ Services.obs.removeObserver(this, "captive-portal-login-abort");
+ Services.obs.removeObserver(this, "captive-portal-login-success");
+ },
+
+ observe(subject, topic, data) {
+ switch (topic) {
+ case "captive-portal-login":
+ this._captivePortalDetected();
+ break;
+ case "captive-portal-login-abort":
+ case "captive-portal-login-success":
+ this._captivePortalGone();
+ break;
+ case "xul-window-visible":
+ this._delayedCaptivePortalDetected();
+ break;
+ }
+ },
+
+ _captivePortalDetected() {
+ if (this._delayedCaptivePortalDetectedInProgress) {
+ return;
+ }
+
+ this._showNotification();
+
+ let win = RecentWindow.getMostRecentBrowserWindow();
+ // If there's no browser window or none have focus, open and show the
+ // tab when we regain focus. This is so that if a different application was
+ // focused, when the user (re-)focuses a browser window, we open the tab
+ // immediately in that window so they can login before continuing to browse.
+ if (!win || win != Services.ww.activeWindow) {
+ this._delayedCaptivePortalDetectedInProgress = true;
+ Services.obs.addObserver(this, "xul-window-visible", false);
+ return;
+ }
+ },
+
+ _ensureCaptivePortalTab() {
+ let tab;
+ if (this._captivePortalTab) {
+ tab = this._captivePortalTab.get();
+ }
+
+ // If the tab is gone or going, we need to open a new one.
+ if (!tab || tab.closing || !tab.parentNode) {
+ tab = gBrowser.addTab(this.canonicalURL,
+ { ownerTab: gBrowser.selectedTab });
+ this._captivePortalTab = Cu.getWeakReference(tab);
+ }
+
+ gBrowser.selectedTab = tab;
+ },
+
+ /**
+ * Called after we regain focus if we detect a portal while a browser window
+ * doesn't have focus. Triggers a portal recheck to reaffirm state, and adds
+ * the tab if needed after a short delay to allow the recheck to complete.
+ */
+ _delayedCaptivePortalDetected() {
+ if (!this._delayedCaptivePortalDetectedInProgress) {
+ return;
+ }
+
+ let win = RecentWindow.getMostRecentBrowserWindow();
+ if (win != Services.ww.activeWindow) {
+ // The window that got focused was not a browser window.
+ return;
+ }
+ Services.obs.removeObserver(this, "xul-window-visible");
+
+ if (win != window) {
+ // Another browser window got focus, we can stop worrying.
+ return;
+ }
+
+ // Trigger a portal recheck. The user may have logged into the portal via
+ // another client, or changed networks.
+ cps.recheckCaptivePortal();
+ this._waitingForRecheck = true;
+ let requestTime = Date.now();
+
+ let self = this;
+ Services.obs.addObserver(function observer() {
+ let time = Date.now() - requestTime;
+ Services.obs.removeObserver(observer, "captive-portal-check-complete");
+ self._waitingForRecheck = false;
+ self._delayedCaptivePortalDetectedInProgress = false;
+ if (cps.state != cps.LOCKED_PORTAL) {
+ // We're free of the portal!
+ return;
+ }
+
+ self._showNotification(win);
+ if (time <= self.PORTAL_RECHECK_DELAY_MS) {
+ // The amount of time elapsed since we requested a recheck (i.e. since
+ // the browser window was focused) was small enough that we can add and
+ // focus a tab with the login page with no noticeable delay.
+ self._ensureCaptivePortalTab(win);
+ }
+ }, "captive-portal-check-complete", false);
+ },
+
+ _captivePortalGone() {
+ if (this._delayedCaptivePortalDetectedInProgress) {
+ Services.obs.removeObserver(this, "xul-window-visible");
+ this._delayedCaptivePortalDetectedInProgress = false;
+ }
+
+ this._removeNotification();
+
+ let tab = this._captivePortalTab.get();
+ this._captivePortalTab = null;
+
+ let canonicalURI = makeURI(this.canonicalURL);
+ if (!tab || tab.closing || !tab.parentNode || !tab.linkedBrowser ||
+ !tab.linkedBrowser.currentURI.equalsExceptRef(canonicalURI)) {
+ return;
+ }
+ gBrowser.removeTab(tab);
+ },
+
+ get _browserBundle() {
+ delete this._browserBundle;
+ return this._browserBundle =
+ Services.strings.createBundle("chrome://browser/locale/browser.properties");
+ },
+
+ handleEvent(aEvent) {
+ if (aEvent.type != "TabSelect" || !this._captivePortalTab) {
+ return;
+ }
+
+ let tab = this._captivePortalTab.get();
+ let n = this.captivePortalNotification;
+ if (!tab || !n) {
+ return;
+ }
+
+ let button = n.querySelector("button.notification-button");
+ if (gBrowser.selectedTab == tab) {
+ button.style.visibility = "hidden";
+ } else {
+ button.style.visibility = "visible";
+ }
+ },
+
+ get captivePortalNotification() {
+ let nb = document.getElementById("high-priority-global-notificationbox");
+ return nb.getNotificationWithValue(this.PORTAL_NOTIFICATION_VALUE);
+ },
+
+ _showNotification() {
+ let buttons = [
+ {
+ label: this._browserBundle.GetStringFromName("captivePortal.showLoginPage"),
+ callback: () => {
+ this._ensureCaptivePortalTab();
+
+ // Returning true prevents the notification from closing.
+ return true;
+ },
+ isDefault: true,
+ },
+ ];
+
+ let message = this._browserBundle.GetStringFromName("captivePortal.infoMessage2");
+
+ let closeHandler = (aEventName) => {
+ if (aEventName != "removed") {
+ return;
+ }
+ gBrowser.tabContainer.removeEventListener("TabSelect", this);
+ };
+
+ let nb = document.getElementById("high-priority-global-notificationbox");
+ nb.appendNotification(message, this.PORTAL_NOTIFICATION_VALUE, "",
+ nb.PRIORITY_INFO_MEDIUM, buttons, closeHandler);
+
+ gBrowser.tabContainer.addEventListener("TabSelect", this);
+ },
+
+ _removeNotification() {
+ let n = this.captivePortalNotification;
+ if (!n || !n.parentNode) {
+ return;
+ }
+ n.close();
+ },
+};
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -974,16 +974,17 @@ var gBrowserInit = {
gPageStyleMenu.init();
LanguageDetectionListener.init();
BrowserOnClick.init();
FeedHandler.init();
DevEdition.init();
AboutPrivateBrowsingListener.init();
TrackingProtection.init();
RefreshBlocker.init();
+ CaptivePortalWatcher.init();
let mm = window.getGroupMessageManager("browsers");
mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
mm.loadFrameScript("chrome://browser/content/content.js", true);
mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
// initialize observers and listeners
@@ -1503,16 +1504,18 @@ var gBrowserInit = {
TrackingProtection.uninit();
RefreshBlocker.uninit();
gMenuButtonUpdateBadge.uninit();
gMenuButtonBadgeManager.uninit();
+ CaptivePortalWatcher.uninit();
+
SidebarUI.uninit();
// Now either cancel delayedStartup, or clean up the services initialized from
// it.
if (this._boundDelayedStartup) {
this._cancelDelayedStartup();
} else {
if (Win7Features)
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -6,16 +6,17 @@
<script type="application/javascript" src="chrome://global/content/printUtils.js"/>
<script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/customizableui/panelUI.js"/>
<script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-addons.js"/>
+<script type="application/javascript" src="chrome://browser/content/browser-captivePortal.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-ctrlTab.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-customization.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-devedition.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-feeds.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-fullScreenAndPointerLock.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-fullZoom.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-gestureSupport.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-media.js"/>
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -67,16 +67,17 @@ browser.jar:
content/browser/aboutProviderDirectory.xhtml (content/aboutProviderDirectory.xhtml)
content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
* content/browser/browser.css (content/browser.css)
content/browser/browser.js (content/browser.js)
* content/browser/browser.xul (content/browser.xul)
content/browser/browser-addons.js (content/browser-addons.js)
+ content/browser/browser-captivePortal.js (content/browser-captivePortal.js)
content/browser/browser-ctrlTab.js (content/browser-ctrlTab.js)
content/browser/browser-customization.js (content/browser-customization.js)
content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
content/browser/browser-devedition.js (content/browser-devedition.js)
content/browser/browser-feeds.js (content/browser-feeds.js)
content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
content/browser/browser-fxaccounts.js (content/browser-fxaccounts.js)
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -24,17 +24,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
["AddonManager", "resource://gre/modules/AddonManager.jsm"],
["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
["AsyncShutdown", "resource://gre/modules/AsyncShutdown.jsm"],
["AutoCompletePopup", "resource://gre/modules/AutoCompletePopup.jsm"],
["BookmarkHTMLUtils", "resource://gre/modules/BookmarkHTMLUtils.jsm"],
["BookmarkJSONUtils", "resource://gre/modules/BookmarkJSONUtils.jsm"],
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
- ["CaptivePortalWatcher", "resource:///modules/CaptivePortalWatcher.jsm"],
["ContentClick", "resource:///modules/ContentClick.jsm"],
["ContentPrefServiceParent", "resource://gre/modules/ContentPrefServiceParent.jsm"],
["ContentSearch", "resource:///modules/ContentSearch.jsm"],
["DateTimePickerHelper", "resource://gre/modules/DateTimePickerHelper.jsm"],
["DirectoryLinksProvider", "resource:///modules/DirectoryLinksProvider.jsm"],
["Feeds", "resource:///modules/Feeds.jsm"],
["FileUtils", "resource://gre/modules/FileUtils.jsm"],
["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
@@ -1003,18 +1002,16 @@ BrowserGlue.prototype = {
if (removalSuccessful && uninstalledValue == "True") {
this._resetProfileNotification("uninstall");
}
}
}
this._checkForOldBuildUpdates();
- CaptivePortalWatcher.init();
-
AutoCompletePopup.init();
DateTimePickerHelper.init();
this._firstWindowTelemetry(aWindow);
this._firstWindowLoaded();
},
/**
@@ -1033,17 +1030,16 @@ BrowserGlue.prototype = {
appStartup.trackStartupCrashEnd();
} catch (e) {
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
}
BrowserUsageTelemetry.uninit();
SelfSupportBackend.uninit();
NewTabMessages.uninit();
- CaptivePortalWatcher.uninit();
AboutNewTab.uninit();
webrtcUI.uninit();
FormValidationHandler.uninit();
AutoCompletePopup.uninit();
DateTimePickerHelper.uninit();
if (AppConstants.NIGHTLY_BUILD) {
AddonWatcher.uninit();
}
deleted file mode 100644
--- a/browser/modules/CaptivePortalWatcher.jsm
+++ /dev/null
@@ -1,278 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = [ "CaptivePortalWatcher" ];
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/RecentWindow.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cps",
- "@mozilla.org/network/captive-portal-service;1",
- "nsICaptivePortalService");
-
-this.CaptivePortalWatcher = {
- /**
- * This constant is chosen to be large enough for a portal recheck to complete,
- * and small enough that the delay in opening a tab isn't too noticeable.
- * Please see comments for _delayedCaptivePortalDetected for more details.
- */
- PORTAL_RECHECK_DELAY_MS: 150,
-
- // This is the value used to identify the captive portal notification.
- PORTAL_NOTIFICATION_VALUE: "captive-portal-detected",
-
- // This holds a weak reference to the captive portal tab so that we
- // don't leak it if the user closes it.
- _captivePortalTab: null,
-
- // This holds a weak reference to the captive portal notification.
- _captivePortalNotification: null,
-
- _initialized: false,
-
- /**
- * If a portal is detected when we don't have focus, we first wait for focus
- * and then add the tab if, after a recheck, the portal is still active. This
- * is set to true while we wait so that in the unlikely event that we receive
- * another notification while waiting, we don't do things twice.
- */
- _delayedCaptivePortalDetectedInProgress: false,
-
- // In the situation above, this is set to true while we wait for the recheck.
- // This flag exists so that tests can appropriately simulate a recheck.
- _waitingForRecheck: false,
-
- get canonicalURL() {
- return Services.prefs.getCharPref("captivedetect.canonicalURL");
- },
-
- init() {
- Services.obs.addObserver(this, "captive-portal-login", false);
- Services.obs.addObserver(this, "captive-portal-login-abort", false);
- Services.obs.addObserver(this, "captive-portal-login-success", false);
- this._initialized = true;
-
- if (cps.state == cps.LOCKED_PORTAL) {
- // A captive portal has already been detected.
- this._captivePortalDetected();
- return;
- }
-
- cps.recheckCaptivePortal();
- },
-
- uninit() {
- if (!this._initialized) {
- return;
- }
- Services.obs.removeObserver(this, "captive-portal-login");
- Services.obs.removeObserver(this, "captive-portal-login-abort");
- Services.obs.removeObserver(this, "captive-portal-login-success");
- },
-
- observe(subject, topic, data) {
- switch (topic) {
- case "captive-portal-login":
- this._captivePortalDetected();
- break;
- case "captive-portal-login-abort":
- case "captive-portal-login-success":
- this._captivePortalGone();
- break;
- case "xul-window-visible":
- this._delayedCaptivePortalDetected();
- break;
- }
- },
-
- _captivePortalDetected() {
- if (this._delayedCaptivePortalDetectedInProgress) {
- return;
- }
-
- let win = RecentWindow.getMostRecentBrowserWindow();
- // If there's no browser window or none have focus, open and show the
- // tab when we regain focus. This is so that if a different application was
- // focused, when the user (re-)focuses a browser window, we open the tab
- // immediately in that window so they can login before continuing to browse.
- if (!win || win != Services.ww.activeWindow) {
- this._delayedCaptivePortalDetectedInProgress = true;
- Services.obs.addObserver(this, "xul-window-visible", false);
- return;
- }
-
- this._showNotification(win);
- },
-
- _ensureCaptivePortalTab(win) {
- let tab;
- if (this._captivePortalTab) {
- tab = this._captivePortalTab.get();
- }
-
- // If the tab is gone or going, we need to open a new one.
- if (!tab || tab.closing || !tab.parentNode) {
- tab = win.gBrowser.addTab(this.canonicalURL,
- { ownerTab: win.gBrowser.selectedTab });
- this._captivePortalTab = Cu.getWeakReference(tab);
- }
-
- win.gBrowser.selectedTab = tab;
- },
-
- /**
- * Called after we regain focus if we detect a portal while a browser window
- * doesn't have focus. Triggers a portal recheck to reaffirm state, and adds
- * the tab if needed after a short delay to allow the recheck to complete.
- */
- _delayedCaptivePortalDetected() {
- if (!this._delayedCaptivePortalDetectedInProgress) {
- return;
- }
-
- let win = RecentWindow.getMostRecentBrowserWindow();
- if (win != Services.ww.activeWindow) {
- // The window that got focused was not a browser window.
- return;
- }
- Services.obs.removeObserver(this, "xul-window-visible");
-
- // Trigger a portal recheck. The user may have logged into the portal via
- // another client, or changed networks.
- cps.recheckCaptivePortal();
- this._waitingForRecheck = true;
- let requestTime = Date.now();
-
- let self = this;
- Services.obs.addObserver(function observer() {
- let time = Date.now() - requestTime;
- Services.obs.removeObserver(observer, "captive-portal-check-complete");
- self._waitingForRecheck = false;
- self._delayedCaptivePortalDetectedInProgress = false;
- if (cps.state != cps.LOCKED_PORTAL) {
- // We're free of the portal!
- return;
- }
-
- self._showNotification(win);
- if (time <= self.PORTAL_RECHECK_DELAY_MS) {
- // The amount of time elapsed since we requested a recheck (i.e. since
- // the browser window was focused) was small enough that we can add and
- // focus a tab with the login page with no noticeable delay.
- self._ensureCaptivePortalTab(win);
- }
- }, "captive-portal-check-complete", false);
- },
-
- _captivePortalGone() {
- if (this._delayedCaptivePortalDetectedInProgress) {
- Services.obs.removeObserver(this, "xul-window-visible");
- this._delayedCaptivePortalDetectedInProgress = false;
- }
-
- this._removeNotification();
-
- if (!this._captivePortalTab) {
- return;
- }
-
- let tab = this._captivePortalTab.get();
- // In all the cases below, we want to stop treating the tab as a
- // captive portal tab.
- this._captivePortalTab = null;
-
- // Check parentNode in case the object hasn't been gc'd yet.
- if (!tab || tab.closing || !tab.parentNode) {
- // User has closed the tab already.
- return;
- }
-
- let tabbrowser = tab.ownerGlobal.gBrowser;
-
- // If after the login, the captive portal has redirected to some other page,
- // leave it open if the tab has focus.
- if (tab.linkedBrowser.currentURI.spec != this.canonicalURL &&
- tabbrowser.selectedTab == tab) {
- return;
- }
-
- // Remove the tab.
- tabbrowser.removeTab(tab);
- },
-
- get _browserBundle() {
- delete this._browserBundle;
- return this._browserBundle =
- Services.strings.createBundle("chrome://browser/locale/browser.properties");
- },
-
- handleEvent(aEvent) {
- if (aEvent.type != "TabSelect" || !this._captivePortalTab || !this._captivePortalNotification) {
- return;
- }
-
- let tab = this._captivePortalTab.get();
- let n = this._captivePortalNotification.get();
- if (!tab || !n) {
- return;
- }
-
- let doc = tab.ownerDocument;
- let button = n.querySelector("button.notification-button");
- if (doc.defaultView.gBrowser.selectedTab == tab) {
- button.style.visibility = "hidden";
- } else {
- button.style.visibility = "visible";
- }
- },
-
- _showNotification(win) {
- let buttons = [
- {
- label: this._browserBundle.GetStringFromName("captivePortal.showLoginPage"),
- callback: () => {
- this._ensureCaptivePortalTab(win);
-
- // Returning true prevents the notification from closing.
- return true;
- },
- isDefault: true,
- },
- ];
-
- let message = this._browserBundle.GetStringFromName("captivePortal.infoMessage2");
-
- let closeHandler = (aEventName) => {
- if (aEventName != "removed") {
- return;
- }
- win.gBrowser.tabContainer.removeEventListener("TabSelect", this);
- };
-
- let nb = win.document.getElementById("high-priority-global-notificationbox");
- let n = nb.appendNotification(message, this.PORTAL_NOTIFICATION_VALUE, "",
- nb.PRIORITY_INFO_MEDIUM, buttons, closeHandler);
-
- this._captivePortalNotification = Cu.getWeakReference(n);
-
- win.gBrowser.tabContainer.addEventListener("TabSelect", this);
- },
-
- _removeNotification() {
- if (!this._captivePortalNotification)
- return;
- let n = this._captivePortalNotification.get();
- this._captivePortalNotification = null;
- if (!n || !n.parentNode) {
- return;
- }
- n.close();
- },
-};
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -11,17 +11,16 @@ XPCSHELL_TESTS_MANIFESTS += [
]
EXTRA_JS_MODULES += [
'AboutHome.jsm',
'AboutNewTab.jsm',
'AttributionCode.jsm',
'BrowserUITelemetry.jsm',
'BrowserUsageTelemetry.jsm',
- 'CaptivePortalWatcher.jsm',
'CastingApps.jsm',
'ContentClick.jsm',
'ContentCrashHandlers.jsm',
'ContentLinkHandler.jsm',
'ContentObservers.jsm',
'ContentSearch.jsm',
'ContentWebRTC.jsm',
'DirectoryLinksProvider.jsm',