// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @fileoverview This file contains the main code for the CEEE Firefox * add-on. This add-on mostly implements the Google Chrome extension APIs in * Firefox. * * The CEEE extension is loaded into a ChromeFrame object (see the * html:embed element in overlay.xul) and catches Chrome extension API requests * using the ChromeFrame postMessage support. * * This add-on runs with privilege in Firefox, but the extension running inside * the ChromeFrame is considered 'unsafe' code. Precautions are taken in the * code to make sure that unsafe code is never executed with the privilege * of the extension. In practice though, the extension running inside Chrome * Frame is trusted code since there are mechanisms outside of this file that * will ensure this. * * @supported Firefox 3.x */ // Commenting out anonymous function wrapper for this whole file to allow for // unit testing this code. // (function(){ /** * Imports the symbol CEEE_globals into this scope. */ Components.utils['import']('resource://modules/global.js', window); if (!CEEE_globals) Components.utils.reportError('CEEE: *** globals module not imported'); if (!CEEE_mozilla_windows) Components.utils.reportError('CEEE: *** mozilla windows module not imported'); if (!CEEE_mozilla_tabs) Components.utils.reportError('CEEE: *** mozilla tabs module not imported'); // Log from where we are running. var ffCeeeLoc = Components.classes['@mozilla.org/extensions/manager;1'] .getService(Components.interfaces.nsIExtensionManager) .getInstallLocation(CEEE_globals.ADDON_ID) .getItemLocation(CEEE_globals.ADDON_ID); Application.console.log('CEEE: running from ' + ffCeeeLoc.path); /** * Constructor for the object that implements the CEEE API. * @constructor */ function CEEE_Class() { /** @const */ this.TAB_STATUS_LOADING = 'loading'; /** @const */ this.TAB_STATUS_COMPLETE = 'complete'; // Internal constants used by implementation. /** @const */ this.API_EVENT_NAME_ = 'ceee-dom-api'; /** @const */ this.API_ELEMENT_NAME_ = 'ceee-api-element'; /** @const */ this.DATA_ATTRIBUTE_NAME_ = 'ceee-event-data'; /** @const */ this.RETURN_ATTRIBUTE_NAME_ = 'ceee-event-return'; /** @const */ this.ORIGIN_EXTENSION_ = '__priv_xtapi'; /** * When true, this allows content scripts to be debugged using Firebug. */ this.contentScriptDebugging = CEEE_globals.getBoolPreference('debug'); /** * The dispatch table for the UI/user context API. * @type {Object} * @private */ this.dispatch_ = {}; /** * The dispatch table for the DOM context API. * @type {Object} * @private */ this.dom_dispatch_ = {}; /** * Reference to the API module implementing the CEEE windows API. * @type {Object} * @private */ this.windowModule_ = null; /** * Reference to the API module implementing the CEEE tabs API. * @type {Object} * @private */ this.tabsModule_ = null; /** * Reference to the API module implementing the CEEE cookies API. * @type {Object} * @private */ this.cookiesModule_ = null; /** * Reference to the API module implementing the CEEE sidebar API. * @type {Object} * @private */ this.sidebarModule_ = null; /** * Reference to the API module implementing the CEEE user scripts API. * @type {Object} * @private */ this.userscriptsModule_ = null; /** * Collection of functions to run once the extensions have been fully * initialized. Maps a content window to a map of description-to-function. * @type {Object} * @private */ this.runWhenExtensionsInited_ = {}; }; /** * Log an informational message to the Firefox error console. * @public */ CEEE_Class.prototype.logInfo = function(msg) { dump('[CEEE] ' + msg + '\n'); Application.console.log('CEEE: ' + msg); }; /** * Log an error message to the Firefox error console. * @public */ CEEE_Class.prototype.logError = function(msg) { var functionName = CEEE_Class.prototype.logError.caller.name + ':: '; dump('[CEEE] *** ' + functionName + msg + '\n'); Components.utils.reportError('CEEE: *** ' + functionName + msg); }; /** * Called once the CEEE host document is fully loaded in a top-level * firefox window. This will be called for each top-level window. * @private */ CEEE_Class.prototype.onLoad_ = function() { // Initialize all of the imported API modules. this.windowModule_ = CEEE_initialize_windows(this); this.tabsModule_ = CEEE_initialize_tabs(this); this.cookiesModule_ = CEEE_initialize_cookies(this); // TODO(twiz@chromium.org) : Re-enable bookmarks support once the // Chrome Frame message passing system is more stable when a pop-up // is present. bb2279154. //CEEE_initialize_bookmarks(this); this.userscriptsModule_ = new CEEE_UserScriptManager(this); this.infobarsModule_ = CEEE_initialize_infobars(this, (/**@type {!Object}*/this.windowModule_)); this.createChromeFrame_(); // NOTE: this function must be called after createChromeFrame_() in order to // make sure that the chrome process started uses the correct command line // arguments. this.sidebarModule_ = CEEE_initialize_sidebar(this); // TODO(joi@chromium.org) We used to have functionality here to show // an error in case no extension was specified; this needs to be // done by putting some HTML into CF now. // Make a list of all registered functions - those are the ones we // wish to overtake in case our CF becomes the new "master" CF, the others // we will leave with Chrome. var functions = []; for (var key in this.dispatch_) { functions.push(key); } var csFunctions = functions.join(','); CEEE_globals.masterCf.init(csFunctions, this.logInfo); var impl = this; window.addEventListener('focus', function() {impl.onFocus_();}, false); window.addEventListener('unload', function() {impl.onUnload_();}, false); // TODO(rogerta@chromium.org): after setting the src property of // ChromeFrame, it was asked in a code review whether the "load" // event could race with the javascript below which sets the // onCfReady_ function, or any functions that it calls directly or // indirectly. For example, is it possible for ChromeFrame to fire // the "load" event before userscripts_api.js runs, which sets the // openPendingChannels property? // // From my experience with Firefox 3.0.x, this has not happened. The xul // file loads the javascript files in the order specified, and // userscripts_api.js always loads after this file. If this does end up // being a problem, the solution would be create a new javascript file that // is called *after* all the other javascript files that set all properties, // that simply adds onLoad_ as a listener to the chrome window (i.e. the // last executable line in this file). // Listen for DOMContentLoaded in order to hook the windows when needed. // No need to listen for DOMFrameContentLoaded, because this is generated // for the