diff options
Diffstat (limited to 'tools/xo_bundle/components/nsBrowserGlue.js')
-rwxr-xr-x | tools/xo_bundle/components/nsBrowserGlue.js | 1072 |
1 files changed, 1072 insertions, 0 deletions
diff --git a/tools/xo_bundle/components/nsBrowserGlue.js b/tools/xo_bundle/components/nsBrowserGlue.js new file mode 100755 index 0000000..d938b13 --- /dev/null +++ b/tools/xo_bundle/components/nsBrowserGlue.js @@ -0,0 +1,1072 @@ +//@line 42 "/builds/moz2_slave/linux_build/build/browser/components/nsBrowserGlue.js" + +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; + +const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource:///modules/distribution.js"); + +const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons"; + +// Check to see if bookmarks need backing up once per +// day on 1 hour idle. +const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60; + +// Backup bookmarks once every 24 hours. +const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000; + +// Factory object +const BrowserGlueServiceFactory = { + _instance: null, + createInstance: function (outer, iid) + { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return this._instance == null ? + this._instance = new BrowserGlue() : this._instance; + } +}; + +// Constructor + +function BrowserGlue() { + + this.__defineGetter__("_prefs", function() { + delete this._prefs; + return this._prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + }); + + this.__defineGetter__("_bundleService", function() { + delete this._bundleService; + return this._bundleService = Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService); + }); + + this.__defineGetter__("_idleService", function() { + delete this._idleService; + return this._idleService = Cc["@mozilla.org/widget/idleservice;1"]. + getService(Ci.nsIIdleService); + }); + + this.__defineGetter__("_observerService", function() { + delete this._observerService; + return this._observerService = Cc['@mozilla.org/observer-service;1']. + getService(Ci.nsIObserverService); + }); + + this._init(); +} + +BrowserGlue.prototype = { + + _saveSession: false, + + _setPrefToSaveSession: function() + { + this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true); + + // This method can be called via [NSApplication terminate:] on Mac, which + // ends up causing prefs not to be flushed to disk, so we need to do that + // explicitly here. See bug 497652. + this._prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null); + }, + + // nsIObserver implementation + observe: function(subject, topic, data) + { + switch(topic) { + case "xpcom-shutdown": + this._dispose(); + break; + case "prefservice:after-app-defaults": + this._onAppDefaults(); + break; + case "final-ui-startup": + this._onProfileStartup(); + break; + case "sessionstore-windows-restored": + this._onBrowserStartup(); + break; + case "browser:purge-session-history": + // reset the console service's error buffer + const cs = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); + cs.logStringMessage(null); // clear the console (in case it's open) + cs.reset(); + break; + case "quit-application-requested": + this._onQuitRequest(subject, data); + break; + case "quit-application-granted": + if (this._saveSession) { + this._setPrefToSaveSession(); + } + // Everything that uses Places during shutdown should be here, since + // on quit-application Places database connection will be closed + // and history synchronization could fail. + this._onProfileShutdown(); + break; + case "session-save": + this._setPrefToSaveSession(); + subject.QueryInterface(Ci.nsISupportsPRBool); + subject.data = true; + break; + case "places-init-complete": + this._initPlaces(); + this._observerService.removeObserver(this, "places-init-complete"); + // no longer needed, since history was initialized completely. + this._observerService.removeObserver(this, "places-database-locked"); + break; + case "places-database-locked": + this._isPlacesDatabaseLocked = true; + // stop observing, so further attempts to load history service + // do not show the prompt. + this._observerService.removeObserver(this, "places-database-locked"); + break; + case "idle": + if (this._idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) { + // Back up bookmarks. + this._archiveBookmarks(); + } + break; + } + }, + + // initialization (called on application startup) + _init: function() + { + // observer registration + const osvr = this._observerService; + osvr.addObserver(this, "xpcom-shutdown", false); + osvr.addObserver(this, "prefservice:after-app-defaults", false); + osvr.addObserver(this, "final-ui-startup", false); + osvr.addObserver(this, "sessionstore-windows-restored", false); + osvr.addObserver(this, "browser:purge-session-history", false); + osvr.addObserver(this, "quit-application-requested", false); + osvr.addObserver(this, "quit-application-granted", false); + osvr.addObserver(this, "session-save", false); + osvr.addObserver(this, "places-init-complete", false); + osvr.addObserver(this, "places-database-locked", false); + }, + + // cleanup (called on application shutdown) + _dispose: function() + { + // observer removal + const osvr = this._observerService; + osvr.removeObserver(this, "xpcom-shutdown"); + osvr.removeObserver(this, "prefservice:after-app-defaults"); + osvr.removeObserver(this, "final-ui-startup"); + osvr.removeObserver(this, "sessionstore-windows-restored"); + osvr.removeObserver(this, "browser:purge-session-history"); + osvr.removeObserver(this, "quit-application-requested"); + osvr.removeObserver(this, "quit-application-granted"); + osvr.removeObserver(this, "session-save"); + }, + + _onAppDefaults: function() + { + // apply distribution customizations (prefs) + // other customizations are applied in _onProfileStartup() + var distro = new DistributionCustomizer(); + distro.applyPrefDefaults(); + }, + + // profile startup handler (contains profile initialization routines) + _onProfileStartup: function() + { + this.Sanitizer.onStartup(); + // check if we're in safe mode + var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo). + QueryInterface(Ci.nsIXULRuntime); + if (app.inSafeMode) { + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + ww.openWindow(null, "chrome://browser/content/safeMode.xul", + "_blank", "chrome,centerscreen,modal,resizable=no", null); + } + + // apply distribution customizations + // prefs are applied in _onAppDefaults() + var distro = new DistributionCustomizer(); + distro.applyCustomizations(); + + // handle any UI migration + this._migrateUI(); + + this._observerService.notifyObservers(null, "browser-ui-startup-complete", ""); + }, + + // profile shutdown handler (contains profile cleanup routines) + _onProfileShutdown: function() + { + this._shutdownPlaces(); + this._idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME); + this.Sanitizer.onShutdown(); + }, + + // Browser startup complete. All initial windows have opened. + _onBrowserStartup: function() + { + // Show about:rights notification, if needed. + if (this._shouldShowRights()) + this._showRightsNotification(); + + // If new add-ons were installed during startup open the add-ons manager. + if (this._prefs.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) { + var args = Cc["@mozilla.org/supports-array;1"]. + createInstance(Ci.nsISupportsArray); + var str = Cc["@mozilla.org/supports-string;1"]. + createInstance(Ci.nsISupportsString); + str.data = ""; + args.AppendElement(str); + var str = Cc["@mozilla.org/supports-string;1"]. + createInstance(Ci.nsISupportsString); + str.data = this._prefs.getCharPref(PREF_EM_NEW_ADDONS_LIST); + args.AppendElement(str); + const EMURL = "chrome://mozapps/content/extensions/extensions.xul"; + const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable"; + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + ww.openWindow(null, EMURL, "_blank", EMFEATURES, args); + this._prefs.clearUserPref(PREF_EM_NEW_ADDONS_LIST); + } + + // Load the "more info" page for a locked places.sqlite + // This property is set earlier in the startup process: + // nsPlacesDBFlush loads after profile-after-change and initializes + // the history service, which sends out places-database-locked + // which sets this property. + if (this._isPlacesDatabaseLocked) { + this._showPlacesLockedNotificationBox(); + } + }, + + _onQuitRequest: function(aCancelQuit, aQuitType) + { + // If user has already dismissed quit request, then do nothing + if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data) + return; + + var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. + getService(Ci.nsIWindowMediator); + + var windowcount = 0; + var pagecount = 0; + var browserEnum = wm.getEnumerator("navigator:browser"); + while (browserEnum.hasMoreElements()) { + windowcount++; + + var browser = browserEnum.getNext(); + var tabbrowser = browser.document.getElementById("content"); + if (tabbrowser) + pagecount += tabbrowser.browsers.length; + } + + this._saveSession = false; + if (pagecount < 2) + return; + + if (aQuitType != "restart") + aQuitType = "quit"; + + var showPrompt = true; + try { + // browser.warnOnQuit is a hidden global boolean to override all quit prompts + // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app + // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref + + var sessionWillBeSaved = this._prefs.getIntPref("browser.startup.page") == 3 || + this._prefs.getBoolPref("browser.sessionstore.resume_session_once"); + if (sessionWillBeSaved || !this._prefs.getBoolPref("browser.warnOnQuit")) + showPrompt = false; + else if (aQuitType == "restart") + showPrompt = this._prefs.getBoolPref("browser.warnOnRestart"); + else + showPrompt = this._prefs.getBoolPref("browser.tabs.warnOnClose"); + } catch (ex) {} + + // Never show a prompt inside the private browsing mode + var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"]. + getService(Ci.nsIPrivateBrowsingService). + privateBrowsingEnabled; + if (!showPrompt || inPrivateBrowsing) + return false; + + var buttonChoice = 0; + var quitBundle = this._bundleService.createBundle("chrome://browser/locale/quitDialog.properties"); + var brandBundle = this._bundleService.createBundle("chrome://branding/locale/brand.properties"); + + var appName = brandBundle.GetStringFromName("brandShortName"); + var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle", + [appName], 1); + + var message; + if (aQuitType == "restart") + message = quitBundle.formatStringFromName("messageRestart", + [appName], 1); + else if (windowcount == 1) + message = quitBundle.formatStringFromName("messageNoWindows", + [appName], 1); + else + message = quitBundle.formatStringFromName("message", + [appName], 1); + + var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]. + getService(Ci.nsIPromptService); + + var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 + + promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 + + promptService.BUTTON_POS_0_DEFAULT; + + var neverAsk = {value:false}; + var button0Title, button2Title; + var button1Title = quitBundle.GetStringFromName("cancelTitle"); + var neverAskText = quitBundle.GetStringFromName("neverAsk"); + + if (aQuitType == "restart") + button0Title = quitBundle.GetStringFromName("restartTitle"); + else { + flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2; + button0Title = quitBundle.GetStringFromName("saveTitle"); + button2Title = quitBundle.GetStringFromName("quitTitle"); + } + + buttonChoice = promptService.confirmEx(null, quitDialogTitle, message, + flags, button0Title, button1Title, button2Title, + neverAskText, neverAsk); + + switch (buttonChoice) { + case 2: // Quit + if (neverAsk.value) + this._prefs.setBoolPref("browser.tabs.warnOnClose", false); + break; + case 1: // Cancel + aCancelQuit.QueryInterface(Ci.nsISupportsPRBool); + aCancelQuit.data = true; + break; + case 0: // Save & Quit + this._saveSession = true; + if (neverAsk.value) { + if (aQuitType == "restart") + this._prefs.setBoolPref("browser.warnOnRestart", false); + else { + // always save state when shutting down + this._prefs.setIntPref("browser.startup.page", 3); + } + } + break; + } + }, + + /* + * _shouldShowRights - Determines if the user should be shown the + * about:rights notification. The notification should *not* be shown if + * we've already shown the current version, or if the override pref says to + * never show it. The notification *should* be shown if it's never been seen + * before, if a newer version is available, or if the override pref says to + * always show it. + */ + _shouldShowRights : function () { + // Look for an unconditional override pref. If set, do what it says. + // (true --> never show, false --> always show) + try { + return !this._prefs.getBoolPref("browser.rights.override"); + } catch (e) { } + // Ditto, for the legacy EULA pref. + try { + return !this._prefs.getBoolPref("browser.EULA.override"); + } catch (e) { } + +//@line 430 "/builds/moz2_slave/linux_build/build/browser/components/nsBrowserGlue.js" + + // Look to see if the user has seen the current version or not. + var currentVersion = this._prefs.getIntPref("browser.rights.version"); + try { + return !this._prefs.getBoolPref("browser.rights." + currentVersion + ".shown"); + } catch (e) { } + + // Legacy: If the user accepted a EULA, we won't annoy them with the + // equivalent about:rights page until the version changes. + try { + return !this._prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted"); + } catch (e) { } + + // We haven't shown the notification before, so do so now. + return true; + }, + + _showRightsNotification : function () { + // Stick the notification onto the selected tab of the active browser window. + var win = this.getMostRecentBrowserWindow(); + var browser = win.gBrowser; // for closure in notification bar callback + var notifyBox = browser.getNotificationBox(); + + var brandBundle = this._bundleService.createBundle("chrome://branding/locale/brand.properties"); + var rightsBundle = this._bundleService.createBundle("chrome://browser/locale/aboutRights.properties"); + + var buttonLabel = rightsBundle.GetStringFromName("buttonLabel"); + var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey"); + var productName = brandBundle.GetStringFromName("brandFullName"); + var notifyRightsText = rightsBundle.formatStringFromName("notifyRightsText", [productName], 1); + + var buttons = [ + { + label: buttonLabel, + accessKey: buttonAccessKey, + popup: null, + callback: function(aNotificationBar, aButton) { + browser.selectedTab = browser.addTab("about:rights"); + } + } + ]; + + // Set pref to indicate we've shown the notification. + var currentVersion = this._prefs.getIntPref("browser.rights.version"); + this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true); + + var box = notifyBox.appendNotification(notifyRightsText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons); + box.persistence = 3; // arbitrary number, just so bar sticks around for a bit + }, + + // returns the (cached) Sanitizer constructor + get Sanitizer() + { + if(typeof(Sanitizer) != "function") { // we should dynamically load the script + Cc["@mozilla.org/moz/jssubscript-loader;1"]. + getService(Ci.mozIJSSubScriptLoader). + loadSubScript("chrome://browser/content/sanitize.js", null); + } + return Sanitizer; + }, + + /** + * Initialize Places + * - imports the bookmarks html file if bookmarks database is empty, try to + * restore bookmarks from a JSON backup if the backend indicates that the + * database was corrupt. + * + * These prefs can be set up by the frontend: + * + * WARNING: setting these preferences to true will overwite existing bookmarks + * + * - browser.places.importBookmarksHTML + * Set to true will import the bookmarks.html file from the profile folder. + * - browser.places.smartBookmarksVersion + * Set during HTML import to indicate that Smart Bookmarks were created. + * Set to -1 to disable Smart Bookmarks creation. + * Set to 0 to restore current Smart Bookmarks. + * - browser.bookmarks.restore_default_bookmarks + * Set to true by safe-mode dialog to indicate we must restore default + * bookmarks. + */ + _initPlaces: function bg__initPlaces() { + // We must instantiate the history service since it will tell us if we + // need to import or restore bookmarks due to first-run, corruption or + // forced migration (due to a major schema change). + var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); + + // If the database is corrupt or has been newly created we should + // import bookmarks. + var databaseStatus = histsvc.databaseStatus; + var importBookmarks = databaseStatus == histsvc.DATABASE_STATUS_CREATE || + databaseStatus == histsvc.DATABASE_STATUS_CORRUPT; + + if (databaseStatus == histsvc.DATABASE_STATUS_CREATE) { + // If the database has just been created, but we already have any + // bookmark, this is not the initial import. This can happen after a + // migration from a different browser since migrators run before us. + // In such a case we should not import, unless some pref has been set. + var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); + if (bmsvc.getIdForItemAt(bmsvc.bookmarksMenuFolder, 0) != -1 || + bmsvc.getIdForItemAt(bmsvc.toolbarFolder, 0) != -1) + importBookmarks = false; + } + + // Check if user or an extension has required to import bookmarks.html + var importBookmarksHTML = false; + try { + importBookmarksHTML = + this._prefs.getBoolPref("browser.places.importBookmarksHTML"); + if (importBookmarksHTML) + importBookmarks = true; + } catch(ex) {} + + // Check if Safe Mode or the user has required to restore bookmarks from + // default profile's bookmarks.html + var restoreDefaultBookmarks = false; + try { + restoreDefaultBookmarks = + this._prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks"); + if (restoreDefaultBookmarks) { + // Ensure that we already have a bookmarks backup for today + this._archiveBookmarks(); + importBookmarks = true; + } + } catch(ex) {} + + // If the user did not require to restore default bookmarks, or import + // from bookmarks.html, we will try to restore from JSON + if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) { + // get latest JSON backup + Cu.import("resource://gre/modules/utils.js"); + var bookmarksBackupFile = PlacesUtils.getMostRecentBackup(); + if (bookmarksBackupFile && bookmarksBackupFile.leafName.match("\.json$")) { + // restore from JSON backup + PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile); + importBookmarks = false; + } + else { + // We have created a new database but we don't have any backup available + importBookmarks = true; + var dirService = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + var bookmarksHTMLFile = dirService.get("BMarks", Ci.nsILocalFile); + if (bookmarksHTMLFile.exists()) { + // If bookmarks.html is available in current profile import it... + importBookmarksHTML = true; + } + else { + // ...otherwise we will restore defaults + restoreDefaultBookmarks = true; + } + } + } + + if (!importBookmarks) { + // Call it here for Fx3 profiles created before the Places folder + // has been added, otherwise it's called during import. + this.ensurePlacesDefaultQueriesInitialized(); + } + else { + // ensurePlacesDefaultQueriesInitialized() is called by import. + // Don't try to recreate smart bookmarks if autoExportHTML is true or + // smart bookmarks are disabled. + var autoExportHTML = false; + try { + autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML"); + } catch(ex) {} + var smartBookmarksVersion = 0; + try { + smartBookmarksVersion = this._prefs.getIntPref("browser.places.smartBookmarksVersion"); + } catch(ex) {} + if (!autoExportHTML && smartBookmarksVersion != -1) + this._prefs.setIntPref("browser.places.smartBookmarksVersion", 0); + + // Get bookmarks.html file location + var dirService = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + + var bookmarksFile = null; + if (restoreDefaultBookmarks) { + // User wants to restore bookmarks.html file from default profile folder + bookmarksFile = dirService.get("profDef", Ci.nsILocalFile); + bookmarksFile.append("bookmarks.html"); + } + else + bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile); + + if (bookmarksFile.exists()) { + // import the file + try { + var importer = Cc["@mozilla.org/browser/places/import-export-service;1"]. + getService(Ci.nsIPlacesImportExportService); + importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */); + } catch (err) { + // Report the error, but ignore it. + Cu.reportError("Bookmarks.html file could be corrupt. " + err); + } + } + else + Cu.reportError("Unable to find bookmarks.html file."); + + // Reset preferences, so we won't try to import again at next run + if (importBookmarksHTML) + this._prefs.setBoolPref("browser.places.importBookmarksHTML", false); + if (restoreDefaultBookmarks) + this._prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks", + false); + } + + // Initialize bookmark archiving on idle. + // Once a day, either on idle or shutdown, bookmarks are backed up. + this._idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME); + }, + + /** + * Places shut-down tasks + * - back up and archive bookmarks + * - export bookmarks as HTML, if so configured + * + * Note: quit-application-granted notification is received twice + * so replace this method with a no-op when first called. + */ + _shutdownPlaces: function bg__shutdownPlaces() { + // Backup and archive Places bookmarks. + this._archiveBookmarks(); + + // Backup bookmarks to bookmarks.html to support apps that depend + // on the legacy format. + var autoExportHTML = false; + try { + autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML"); + } catch(ex) { + Components.utils.reportError(ex); + } + + if (autoExportHTML) { + Cc["@mozilla.org/browser/places/import-export-service;1"]. + getService(Ci.nsIPlacesImportExportService). + backupBookmarksFile(); + } + }, + + /** + * Back up and archive bookmarks + */ + _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() { + Cu.import("resource://gre/modules/utils.js"); + + var lastBackup = PlacesUtils.getMostRecentBackup(); + + // Backup bookmarks if there aren't any backups or + // they haven't been backed up in the last 24 hrs. + if (!lastBackup || + Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) { + var maxBackups = 5; + try { + maxBackups = this._prefs.getIntPref("browser.bookmarks.max_backups"); + } catch(ex) {} + + PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */); + } + }, + + /** + * Show the notificationBox for a locked places database. + */ + _showPlacesLockedNotificationBox: function nsBrowserGlue__showPlacesLockedNotificationBox() { + var brandBundle = this._bundleService.createBundle("chrome://branding/locale/brand.properties"); + var applicationName = brandBundle.GetStringFromName("brandShortName"); + var placesBundle = this._bundleService.createBundle("chrome://browser/locale/places/places.properties"); + var title = placesBundle.GetStringFromName("lockPrompt.title"); + var text = placesBundle.formatStringFromName("lockPrompt.text", [applicationName], 1); + var buttonText = placesBundle.GetStringFromName("lockPromptInfoButton.label"); + var accessKey = placesBundle.GetStringFromName("lockPromptInfoButton.accessKey"); + + var helpTopic = "places-locked"; + var url = Cc["@mozilla.org/toolkit/URLFormatterService;1"]. + getService(Components.interfaces.nsIURLFormatter). + formatURLPref("app.support.baseURL"); + url += helpTopic; + + var browser = this.getMostRecentBrowserWindow().gBrowser; + + var buttons = [ + { + label: buttonText, + accessKey: accessKey, + popup: null, + callback: function(aNotificationBar, aButton) { + browser.selectedTab = browser.addTab(url); + } + } + ]; + + var notifyBox = browser.getNotificationBox(); + var box = notifyBox.appendNotification(text, title, null, + notifyBox.PRIORITY_CRITICAL_MEDIUM, + buttons); + box.persistence = -1; // Until user closes it + }, + + _migrateUI: function bg__migrateUI() { + var migration = 0; + try { + migration = this._prefs.getIntPref("browser.migration.version"); + } catch(ex) {} + + if (migration == 0) { + // this code should always migrate pre-FF3 profiles to the current UI state + + // grab the localstore.rdf and make changes needed for new UI + this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService); + this._dataSource = this._rdf.GetDataSource("rdf:local-store"); + this._dirty = false; + + let currentsetResource = this._rdf.GetResource("currentset"); + let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"]; + for (let i = 0; i < toolbars.length; i++) { + let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]); + let currentset = this._getPersist(toolbar, currentsetResource); + if (!currentset) { + // toolbar isn't customized + if (i == 0) + // new button is in the defaultset, nothing to migrate + break; + continue; + } + if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset)) + // new button is already there, nothing to migrate + break; + if (/(?:^|,)back-button(?:$|,)/.test(currentset)) { + let newset = currentset.replace(/(^|,)back-button($|,)/, + "$1unified-back-forward-button,back-button$2") + this._setPersist(toolbar, currentsetResource, newset); + // done migrating + break; + } + } + + // force the RDF to be saved + if (this._dirty) + this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush(); + + // free up the RDF service + this._rdf = null; + this._dataSource = null; + + // update the migration version + this._prefs.setIntPref("browser.migration.version", 1); + } + }, + + _getPersist: function bg__getPersist(aSource, aProperty) { + var target = this._dataSource.GetTarget(aSource, aProperty, true); + if (target instanceof Ci.nsIRDFLiteral) + return target.Value; + return null; + }, + + _setPersist: function bg__setPersist(aSource, aProperty, aTarget) { + this._dirty = true; + try { + var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true); + if (oldTarget) { + if (aTarget) + this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget)); + else + this._dataSource.Unassert(aSource, aProperty, oldTarget); + } + else { + this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true); + } + } + catch(ex) {} + }, + + // ------------------------------ + // public nsIBrowserGlue members + // ------------------------------ + + sanitize: function(aParentWindow) + { + this.Sanitizer.sanitize(aParentWindow); + }, + + ensurePlacesDefaultQueriesInitialized: function() { + const SMART_BOOKMARKS_VERSION = 1; + const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark"; + const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion"; + + // XXX should this be a pref? see bug #399268 + const MAX_RESULTS = 10; + + // get current smart bookmarks version + // By default, if the pref is not set up, we must create Smart Bookmarks + var smartBookmarksCurrentVersion = 0; + try { + smartBookmarksCurrentVersion = this._prefs.getIntPref(SMART_BOOKMARKS_PREF); + } catch(ex) {} + + // bail out if we don't have to create or update Smart Bookmarks + if (smartBookmarksCurrentVersion == -1 || + smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION) + return; + + var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); + var annosvc = Cc["@mozilla.org/browser/annotation-service;1"]. + getService(Ci.nsIAnnotationService); + + var callback = { + _uri: function(aSpec) { + return Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService). + newURI(aSpec, null, null); + }, + + runBatched: function() { + var smartBookmarks = []; + var bookmarksMenuIndex = 0; + var bookmarksToolbarIndex = 0; + + var placesBundle = Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService). + createBundle("chrome://browser/locale/places/places.properties"); + + // MOST VISITED + var smart = {queryId: "MostVisited", // don't change this + itemId: null, + title: placesBundle.GetStringFromName("mostVisitedTitle"), + uri: this._uri("place:queryType=" + + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY + + "&sort=" + + Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + + "&maxResults=" + MAX_RESULTS), + parent: bmsvc.toolbarFolder, + position: bookmarksToolbarIndex++}; + smartBookmarks.push(smart); + + // RECENTLY BOOKMARKED + smart = {queryId: "RecentlyBookmarked", // don't change this + itemId: null, + title: placesBundle.GetStringFromName("recentlyBookmarkedTitle"), + uri: this._uri("place:folder=BOOKMARKS_MENU" + + "&folder=UNFILED_BOOKMARKS" + + "&folder=TOOLBAR" + + "&queryType=" + + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS + + "&sort=" + + Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING + + "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" + + "&maxResults=" + MAX_RESULTS + + "&excludeQueries=1"), + parent: bmsvc.bookmarksMenuFolder, + position: bookmarksMenuIndex++}; + smartBookmarks.push(smart); + + // RECENT TAGS + smart = {queryId: "RecentTags", // don't change this + itemId: null, + title: placesBundle.GetStringFromName("recentTagsTitle"), + uri: this._uri("place:"+ + "type=" + + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY + + "&sort=" + + Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING + + "&maxResults=" + MAX_RESULTS), + parent: bmsvc.bookmarksMenuFolder, + position: bookmarksMenuIndex++}; + smartBookmarks.push(smart); + + var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {}); + // set current itemId, parent and position if Smart Bookmark exists + for each(var itemId in smartBookmarkItemIds) { + var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO); + for (var i = 0; i < smartBookmarks.length; i++){ + if (smartBookmarks[i].queryId == queryId) { + smartBookmarks[i].itemId = itemId; + smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId); + smartBookmarks[i].position = bmsvc.getItemIndex(itemId); + // remove current item, since it will be replaced + bmsvc.removeItem(itemId); + break; + } + // We don't remove old Smart Bookmarks because user could still + // find them useful, or could have personalized them. + // Instead we remove the Smart Bookmark annotation. + if (i == smartBookmarks.length - 1) + annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO); + } + } + + // create smart bookmarks + for each(var smartBookmark in smartBookmarks) { + smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent, + smartBookmark.uri, + smartBookmark.position, + smartBookmark.title); + annosvc.setItemAnnotation(smartBookmark.itemId, + SMART_BOOKMARKS_ANNO, smartBookmark.queryId, + 0, annosvc.EXPIRE_NEVER); + } + + // If we are creating all Smart Bookmarks from ground up, add a + // separator below them in the bookmarks menu. + if (smartBookmarkItemIds.length == 0) + bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex); + } + }; + + try { + bmsvc.runInBatchMode(callback, null); + } + catch(ex) { + Components.utils.reportError(ex); + } + finally { + this._prefs.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION); + this._prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null); + } + }, + +//@line 957 "/builds/moz2_slave/linux_build/build/browser/components/nsBrowserGlue.js" + + // this returns the most recent non-popup browser window + getMostRecentBrowserWindow : function () + { + var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. + getService(Components.interfaces.nsIWindowMediator); + +//@line 965 "/builds/moz2_slave/linux_build/build/browser/components/nsBrowserGlue.js" + var win = wm.getMostRecentWindow("navigator:browser", true); + + // if we're lucky, this isn't a popup, and we can just return this + if (win && win.document.documentElement.getAttribute("chromehidden")) { + win = null; + var windowList = wm.getEnumerator("navigator:browser", true); + // this is oldest to newest, so this gets a bit ugly + while (windowList.hasMoreElements()) { + var nextWin = windowList.getNext(); + if (!nextWin.document.documentElement.getAttribute("chromehidden")) + win = nextWin; + } + } +//@line 991 "/builds/moz2_slave/linux_build/build/browser/components/nsBrowserGlue.js" + + return win; + }, + + + // for XPCOM + classDescription: "Firefox Browser Glue Service", + classID: Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"), + contractID: "@mozilla.org/browser/browserglue;1", + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference, + Ci.nsIBrowserGlue]), + + // redefine the default factory for XPCOMUtils + _xpcom_factory: BrowserGlueServiceFactory, + + // get this contractID registered for certain categories via XPCOMUtils + _xpcom_categories: [ + // make BrowserGlue a startup observer + { category: "app-startup", service: true } + ] +} + +function GeolocationPrompt() {} + +GeolocationPrompt.prototype = { + classDescription: "Geolocation Prompting Component", + classID: Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"), + contractID: "@mozilla.org/geolocation/prompt;1", + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationPrompt]), + + prompt: function(request) { + var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager); + + var result = pm.testExactPermission(request.requestingURI, "geo"); + + if (result == Ci.nsIPermissionManager.ALLOW_ACTION) { + request.allow(); + return; + } + + if (result == Ci.nsIPermissionManager.DENY_ACTION) { + request.cancel(); + return; + } + + function setPagePermission(uri, allow) { + if (allow == true) + pm.add(uri, "geo", Ci.nsIPermissionManager.ALLOW_ACTION); + else + pm.add(uri, "geo", Ci.nsIPermissionManager.DENY_ACTION); + } + + function getChromeWindow(aWindow) { + var chromeWin = aWindow + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow) + .QueryInterface(Ci.nsIDOMChromeWindow); + return chromeWin; + } + + var requestingWindow = request.requestingWindow.top; + var chromeWindowObject = getChromeWindow(requestingWindow).wrappedJSObject; + var tabbrowser = chromeWindowObject.gBrowser; + var browser = tabbrowser.getBrowserForDocument(requestingWindow.document); + var notificationBox = tabbrowser.getNotificationBox(browser); + + var notification = notificationBox.getNotificationWithValue("geolocation"); + if (!notification) { + var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService); + var browserBundle = bundleService.createBundle("chrome://browser/locale/browser.properties"); + + var buttons = [{ + label: browserBundle.GetStringFromName("geolocation.shareLocation"), + accessKey: browserBundle.GetStringFromName("geolocation.shareLocation.accesskey"), + callback: function(notification) { + if (notification.getElementsByClassName("rememberChoice")[0].checked) + setPagePermission(request.requestingURI, true); + request.allow(); + }, + }, + { + label: browserBundle.GetStringFromName("geolocation.dontShareLocation"), + accessKey: browserBundle.GetStringFromName("geolocation.dontShareLocation.accesskey"), + callback: function(notification) { + if (notification.getElementsByClassName("rememberChoice")[0].checked) + setPagePermission(request.requestingURI, false); + request.cancel(); + }, + }]; + + var message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow", + [request.requestingURI.host], 1); + + var newBar = notificationBox.appendNotification(message, + "geolocation", + "chrome://browser/skin/Geo.png", + notificationBox.PRIORITY_INFO_HIGH, + buttons); + + // For whatever reason, if we do this immediately + // (eg, without the setTimeout), the "link" + // element does not show up in the notification + // bar. + function geolocation_hacks_to_notification () { + + var checkbox = newBar.ownerDocument.createElementNS(XULNS, "checkbox"); + checkbox.className = "rememberChoice"; + checkbox.setAttribute("label", browserBundle.GetStringFromName("geolocation.remember")); + newBar.appendChild(checkbox); + + var link = newBar.ownerDocument.createElementNS(XULNS, "label"); + link.className = "text-link"; + link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore")); + + var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); + link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL"); + + var description = newBar.ownerDocument.getAnonymousElementByAttribute(newBar, "anonid", "messageText"); + description.appendChild(link); + }; + + chromeWindowObject.setTimeout(geolocation_hacks_to_notification, 0); + + } + }, +}; + + +//module initialization +function NSGetModule(aCompMgr, aFileSpec) { + return XPCOMUtils.generateModule([BrowserGlue, GeolocationPrompt]); +} |