diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/tabs')
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/common.js | 34 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/events.js | 39 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/helpers.js | 22 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/namespace.js | 10 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/observer.js | 113 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/tab-fennec.js | 249 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/tab-firefox.js | 353 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/tab.js | 24 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/tabs-firefox.js | 135 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/utils.js | 370 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/tabs/worker.js | 17 |
11 files changed, 0 insertions, 1366 deletions
diff --git a/addon-sdk/source/lib/sdk/tabs/common.js b/addon-sdk/source/lib/sdk/tabs/common.js deleted file mode 100644 index 9ee512a7b..000000000 --- a/addon-sdk/source/lib/sdk/tabs/common.js +++ /dev/null @@ -1,34 +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 { validateOptions } = require("../deprecated/api-utils"); -const { data } = require("../self"); - -function Options(options) { - if ('string' === typeof options) - options = { url: options }; - - return validateOptions(options, { - url: { - is: ["string"], - map: (v) => v ? data.url(v) : v - }, - inBackground: { - map: Boolean, - is: ["undefined", "boolean"] - }, - isPinned: { is: ["undefined", "boolean"] }, - isPrivate: { is: ["undefined", "boolean"] }, - inNewWindow: { is: ["undefined", "boolean"] }, - onOpen: { is: ["undefined", "function"] }, - onClose: { is: ["undefined", "function"] }, - onReady: { is: ["undefined", "function"] }, - onLoad: { is: ["undefined", "function"] }, - onPageShow: { is: ["undefined", "function"] }, - onActivate: { is: ["undefined", "function"] }, - onDeactivate: { is: ["undefined", "function"] } - }); -} -exports.Options = Options; diff --git a/addon-sdk/source/lib/sdk/tabs/events.js b/addon-sdk/source/lib/sdk/tabs/events.js deleted file mode 100644 index 65650f9dc..000000000 --- a/addon-sdk/source/lib/sdk/tabs/events.js +++ /dev/null @@ -1,39 +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"; - -module.metadata = { - "stability": "unstable" -}; - -const ON_PREFIX = "on"; -const TAB_PREFIX = "Tab"; - -const EVENTS = { - ready: "DOMContentLoaded", - load: "load", // Used for non-HTML content - pageshow: "pageshow", // Used for cached content - open: "TabOpen", - close: "TabClose", - activate: "TabSelect", - deactivate: null, - pinned: "TabPinned", - unpinned: "TabUnpinned" -} -exports.EVENTS = EVENTS; - -Object.keys(EVENTS).forEach(function(name) { - EVENTS[name] = { - name: name, - listener: createListenerName(name), - dom: EVENTS[name] - } -}); - -function createListenerName (name) { - if (name === 'pageshow') - return 'onPageShow'; - else - return ON_PREFIX + name.charAt(0).toUpperCase() + name.substr(1); -} diff --git a/addon-sdk/source/lib/sdk/tabs/helpers.js b/addon-sdk/source/lib/sdk/tabs/helpers.js deleted file mode 100644 index b2c8aa013..000000000 --- a/addon-sdk/source/lib/sdk/tabs/helpers.js +++ /dev/null @@ -1,22 +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'; - -module.metadata = { - 'stability': 'unstable' -}; - - -// NOTE: This file should only export Tab instances - - -const { getTabForBrowser: getRawTabForBrowser } = require('./utils'); -const { modelFor } = require('../model/core'); - -exports.getTabForRawTab = modelFor; - -function getTabForBrowser(browser) { - return modelFor(getRawTabForBrowser(browser)) || null; -} -exports.getTabForBrowser = getTabForBrowser; diff --git a/addon-sdk/source/lib/sdk/tabs/namespace.js b/addon-sdk/source/lib/sdk/tabs/namespace.js deleted file mode 100644 index 3553b1a99..000000000 --- a/addon-sdk/source/lib/sdk/tabs/namespace.js +++ /dev/null @@ -1,10 +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'; - -var { ns } = require('../core/namespace'); - -exports.tabsNS = ns(); -exports.tabNS = ns(); -exports.rawTabNS = ns(); diff --git a/addon-sdk/source/lib/sdk/tabs/observer.js b/addon-sdk/source/lib/sdk/tabs/observer.js deleted file mode 100644 index 4e935cd62..000000000 --- a/addon-sdk/source/lib/sdk/tabs/observer.js +++ /dev/null @@ -1,113 +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'; - -module.metadata = { - "stability": "unstable" -}; - -const { EventTarget } = require("../event/target"); -const { emit } = require("../event/core"); -const { DOMEventAssembler } = require("../deprecated/events/assembler"); -const { Class } = require("../core/heritage"); -const { getActiveTab, getTabs } = require("./utils"); -const { browserWindowIterator } = require("../deprecated/window-utils"); -const { isBrowser, windows, getMostRecentBrowserWindow } = require("../window/utils"); -const { observer: windowObserver } = require("../windows/observer"); -const { when } = require("../system/unload"); - -const EVENTS = { - "TabOpen": "open", - "TabClose": "close", - "TabSelect": "select", - "TabMove": "move", - "TabPinned": "pinned", - "TabUnpinned": "unpinned" -}; - -const selectedTab = Symbol("observer/state/selectedTab"); - -// Event emitter objects used to register listeners and emit events on them -// when they occur. -const Observer = Class({ - implements: [EventTarget, DOMEventAssembler], - initialize() { - this[selectedTab] = null; - // Currently Gecko does not dispatch any event on the previously selected - // tab before / after "TabSelect" is dispatched. In order to work around this - // limitation we keep track of selected tab and emit "deactivate" event with - // that before emitting "activate" on selected tab. - this.on("select", tab => { - const selected = this[selectedTab]; - if (selected !== tab) { - if (selected) { - emit(this, 'deactivate', selected); - } - - if (tab) { - this[selectedTab] = tab; - emit(this, 'activate', this[selectedTab]); - } - } - }); - - - // We also observe opening / closing windows in order to add / remove it's - // containers to the observed list. - windowObserver.on("open", chromeWindow => { - if (isBrowser(chromeWindow)) { - this.observe(chromeWindow); - } - }); - - windowObserver.on("close", chromeWindow => { - if (isBrowser(chromeWindow)) { - // Bug 751546: Emit `deactivate` event on window close immediatly - // Otherwise we are going to face "dead object" exception on `select` event - if (getActiveTab(chromeWindow) === this[selectedTab]) { - emit(this, "deactivate", this[selectedTab]); - this[selectedTab] = null; - } - this.ignore(chromeWindow); - } - }); - - - // Currently gecko does not dispatches "TabSelect" events when different - // window gets activated. To work around this limitation we emulate "select" - // event for this case. - windowObserver.on("activate", chromeWindow => { - if (isBrowser(chromeWindow)) { - emit(this, "select", getActiveTab(chromeWindow)); - } - }); - - // We should synchronize state, since probably we already have at least one - // window open. - for (let chromeWindow of browserWindowIterator()) { - this.observe(chromeWindow); - } - - when(_ => { - // Don't dispatch a deactivate event during unload. - this[selectedTab] = null; - }); - }, - /** - * Events that are supported and emitted by the module. - */ - supportedEventsTypes: Object.keys(EVENTS), - /** - * Function handles all the supported events on all the windows that are - * observed. Method is used to proxy events to the listeners registered on - * this event emitter. - * @param {Event} event - * Keyboard event being emitted. - */ - handleEvent: function handleEvent(event) { - emit(this, EVENTS[event.type], event.target, event); - } -}); - -exports.observer = new Observer(); diff --git a/addon-sdk/source/lib/sdk/tabs/tab-fennec.js b/addon-sdk/source/lib/sdk/tabs/tab-fennec.js deleted file mode 100644 index 3927337f6..000000000 --- a/addon-sdk/source/lib/sdk/tabs/tab-fennec.js +++ /dev/null @@ -1,249 +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 { Cc, Ci } = require('chrome'); -const { Class } = require('../core/heritage'); -const { tabNS, rawTabNS } = require('./namespace'); -const { EventTarget } = require('../event/target'); -const { activateTab, getTabTitle, setTabTitle, closeTab, getTabURL, - getTabContentWindow, getTabForBrowser, setTabURL, getOwnerWindow, - getTabContentDocument, getTabContentType, getTabId, isTab } = require('./utils'); -const { emit } = require('../event/core'); -const { isPrivate } = require('../private-browsing/utils'); -const { isWindowPrivate } = require('../window/utils'); -const { when: unload } = require('../system/unload'); -const { BLANK } = require('../content/thumbnail'); -const { viewFor } = require('../view/core'); -const { EVENTS } = require('./events'); -const { modelFor } = require('../model/core'); - -const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec'; - -const Tab = Class({ - extends: EventTarget, - initialize: function initialize(options) { - options = options.tab ? options : { tab: options }; - let tab = options.tab; - - EventTarget.prototype.initialize.call(this, options); - let tabInternals = tabNS(this); - rawTabNS(tab).tab = this; - - let window = tabInternals.window = options.window || getOwnerWindow(tab); - tabInternals.tab = tab; - - // TabReady - let onReady = tabInternals.onReady = onTabReady.bind(this); - tab.browser.addEventListener(EVENTS.ready.dom, onReady, false); - - // TabPageShow - let onPageShow = tabInternals.onPageShow = onTabPageShow.bind(this); - tab.browser.addEventListener(EVENTS.pageshow.dom, onPageShow, false); - - // TabLoad - let onLoad = tabInternals.onLoad = onTabLoad.bind(this); - tab.browser.addEventListener(EVENTS.load.dom, onLoad, true); - - // TabClose - let onClose = tabInternals.onClose = onTabClose.bind(this); - window.BrowserApp.deck.addEventListener(EVENTS.close.dom, onClose, false); - - unload(cleanupTab.bind(null, this)); - }, - - /** - * The title of the page currently loaded in the tab. - * Changing this property changes an actual title. - * @type {String} - */ - get title() { - return getTabTitle(tabNS(this).tab); - }, - set title(title) { - setTabTitle(tabNS(this).tab, title); - }, - - /** - * Location of the page currently loaded in this tab. - * Changing this property will loads page under under the specified location. - * @type {String} - */ - get url() { - return tabNS(this).closed ? undefined : getTabURL(tabNS(this).tab); - }, - set url(url) { - setTabURL(tabNS(this).tab, url); - }, - - getThumbnail: function() { - // TODO: implement! - console.error(ERR_FENNEC_MSG); - - // return 80x45 blank default - return BLANK; - }, - - /** - * tab's document readyState, or 'uninitialized' if it doesn't even exist yet. - */ - get readyState() { - let doc = getTabContentDocument(tabNS(this).tab); - return doc && doc.readyState || 'uninitialized'; - }, - - get id() { - return getTabId(tabNS(this).tab); - }, - - /** - * The index of the tab relative to other tabs in the application window. - * Changing this property will change order of the actual position of the tab. - * @type {Number} - */ - get index() { - if (tabNS(this).closed) return undefined; - - let tabs = tabNS(this).window.BrowserApp.tabs; - let tab = tabNS(this).tab; - for (var i = tabs.length; i >= 0; i--) { - if (tabs[i] === tab) - return i; - } - return null; - }, - set index(value) { - console.error(ERR_FENNEC_MSG); // TODO - }, - - /** - * Whether or not tab is pinned (Is an app-tab). - * @type {Boolean} - */ - get isPinned() { - console.error(ERR_FENNEC_MSG); // TODO - return false; // TODO - }, - pin: function pin() { - console.error(ERR_FENNEC_MSG); // TODO - }, - unpin: function unpin() { - console.error(ERR_FENNEC_MSG); // TODO - }, - - /** - * Returns the MIME type that the document loaded in the tab is being - * rendered as. - * @type {String} - */ - get contentType() { - return getTabContentType(tabNS(this).tab); - }, - - /** - * Create a worker for this tab, first argument is options given to Worker. - * @type {Worker} - */ - attach: function attach(options) { - // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946 - // TODO: fix this circular dependency - let { Worker } = require('./worker'); - return Worker(options, getTabContentWindow(tabNS(this).tab)); - }, - - /** - * Make this tab active. - */ - activate: function activate() { - activateTab(tabNS(this).tab, tabNS(this).window); - }, - - /** - * Close the tab - */ - close: function close(callback) { - let tab = this; - this.once(EVENTS.close.name, function () { - tabNS(tab).closed = true; - if (callback) callback(); - }); - - closeTab(tabNS(this).tab); - }, - - /** - * Reload the tab - */ - reload: function reload() { - tabNS(this).tab.browser.reload(); - } -}); -exports.Tab = Tab; - -// Implement `viewFor` polymorphic function for the Tab -// instances. -viewFor.define(Tab, x => tabNS(x).tab); - -function cleanupTab(tab) { - let tabInternals = tabNS(tab); - if (!tabInternals.tab) - return; - - if (tabInternals.tab.browser) { - tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady, false); - tabInternals.tab.browser.removeEventListener(EVENTS.pageshow.dom, tabInternals.onPageShow, false); - tabInternals.tab.browser.removeEventListener(EVENTS.load.dom, tabInternals.onLoad, true); - } - tabInternals.onReady = null; - tabInternals.onPageShow = null; - tabInternals.onLoad = null; - tabInternals.window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, tabInternals.onClose, false); - tabInternals.onClose = null; - rawTabNS(tabInternals.tab).tab = null; - tabInternals.tab = null; - tabInternals.window = null; -} - -function onTabReady(event) { - let win = event.target.defaultView; - - // ignore frames - if (win === win.top) { - emit(this, 'ready', this); - } -} - -function onTabLoad (event) { - let win = event.target.defaultView; - - // ignore frames - if (win === win.top) { - emit(this, 'load', this); - } -} - -function onTabPageShow(event) { - let win = event.target.defaultView; - if (win === win.top) - emit(this, 'pageshow', this, event.persisted); -} - -// TabClose -function onTabClose(event) { - let rawTab = getTabForBrowser(event.target); - if (tabNS(this).tab !== rawTab) - return; - - emit(this, EVENTS.close.name, this); - cleanupTab(this); -}; - -isPrivate.implement(Tab, tab => { - return isWindowPrivate(getTabContentWindow(tabNS(tab).tab)); -}); - -// Implement `modelFor` function for the Tab instances. -modelFor.when(isTab, rawTab => { - return rawTabNS(rawTab).tab; -}); diff --git a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js b/addon-sdk/source/lib/sdk/tabs/tab-firefox.js deleted file mode 100644 index f1da92379..000000000 --- a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js +++ /dev/null @@ -1,353 +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 { Class } = require('../core/heritage'); -const { observer } = require('./observer'); -const { observer: windowObserver } = require('../windows/observer'); -const { addListItem, removeListItem } = require('../util/list'); -const { viewFor } = require('../view/core'); -const { modelFor } = require('../model/core'); -const { emit, setListeners } = require('../event/core'); -const { EventTarget } = require('../event/target'); -const { getBrowserForTab, setTabURL, getTabId, getTabURL, getTabForBrowser, - getTabs, getTabTitle, setTabTitle, getIndex, closeTab, reload, move, - activateTab, pin, unpin, isTab } = require('./utils'); -const { isBrowser, getInnerId, isWindowPrivate } = require('../window/utils'); -const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail"); -const { when } = require('../system/unload'); -const { ignoreWindow, isPrivate } = require('../private-browsing/utils') -const { defer } = require('../lang/functional'); -const { getURL } = require('../url/utils'); -const { frames, remoteRequire } = require('../remote/parent'); -remoteRequire('sdk/content/tab-events'); - -const modelsFor = new WeakMap(); -const viewsFor = new WeakMap(); -const destroyed = new WeakMap(); - -const tabEvents = {}; -exports.tabEvents = tabEvents; - -function browser(tab) { - return getBrowserForTab(viewsFor.get(tab)); -} - -function isDestroyed(tab) { - return destroyed.has(tab); -} - -function isClosed(tab) { - if (!viewsFor.has(tab)) - return true; - return viewsFor.get(tab).closing; -} - -// private tab attribute where the remote cached value is stored -const remoteReadyStateCached = Symbol("remoteReadyStateCached"); - -const Tab = Class({ - implements: [EventTarget], - initialize: function(tabElement, options = null) { - modelsFor.set(tabElement, this); - viewsFor.set(this, tabElement); - - if (options) { - EventTarget.prototype.initialize.call(this, options); - - if (options.isPinned) - this.pin(); - - // Note that activate is defered and so will run after any open event - // is sent out - if (!options.inBackground) - this.activate(); - } - - getURL.implement(this, tab => tab.url); - isPrivate.implement(this, tab => { - return isWindowPrivate(viewsFor.get(tab).ownerDocument.defaultView); - }); - }, - - get id() { - return isDestroyed(this) ? undefined : getTabId(viewsFor.get(this)); - }, - - get title() { - return isDestroyed(this) ? undefined : getTabTitle(viewsFor.get(this)); - }, - - set title(val) { - if (isDestroyed(this)) - return; - - setTabTitle(viewsFor.get(this), val); - }, - - get url() { - return isDestroyed(this) ? undefined : getTabURL(viewsFor.get(this)); - }, - - set url(val) { - if (isDestroyed(this)) - return; - - setTabURL(viewsFor.get(this), val); - }, - - get contentType() { - return isDestroyed(this) ? undefined : browser(this).documentContentType; - }, - - get index() { - return isDestroyed(this) ? undefined : getIndex(viewsFor.get(this)); - }, - - set index(val) { - if (isDestroyed(this)) - return; - - move(viewsFor.get(this), val); - }, - - get isPinned() { - return isDestroyed(this) ? undefined : viewsFor.get(this).pinned; - }, - - get window() { - if (isClosed(this)) - return undefined; - - // TODO: Remove the dependency on the windows module, see bug 792670 - require('../windows'); - let tabElement = viewsFor.get(this); - let domWindow = tabElement.ownerDocument.defaultView; - return modelFor(domWindow); - }, - - get readyState() { - return isDestroyed(this) ? undefined : this[remoteReadyStateCached] || "uninitialized"; - }, - - pin: function() { - if (isDestroyed(this)) - return; - - pin(viewsFor.get(this)); - }, - - unpin: function() { - if (isDestroyed(this)) - return; - - unpin(viewsFor.get(this)); - }, - - close: function(callback) { - let tabElement = viewsFor.get(this); - - if (isDestroyed(this) || !tabElement || !tabElement.parentNode) { - if (callback) - callback(); - return; - } - - this.once('close', () => { - this.destroy(); - if (callback) - callback(); - }); - - closeTab(tabElement); - }, - - reload: function() { - if (isDestroyed(this)) - return; - - reload(viewsFor.get(this)); - }, - - activate: defer(function() { - if (isDestroyed(this)) - return; - - activateTab(viewsFor.get(this)); - }), - - getThumbnail: function() { - if (isDestroyed(this)) - return BLANK; - - // TODO: This is unimplemented in e10s: bug 1148601 - if (browser(this).isRemoteBrowser) { - console.error('This method is not supported with E10S'); - return BLANK; - } - return getThumbnailURIForWindow(browser(this).contentWindow); - }, - - attach: function(options) { - if (isDestroyed(this)) - return; - - let { Worker } = require('../content/worker'); - let { connect, makeChildOptions } = require('../content/utils'); - - let worker = Worker(options); - worker.once("detach", () => { - worker.destroy(); - }); - - let attach = frame => { - let childOptions = makeChildOptions(options); - frame.port.emit("sdk/tab/attach", childOptions); - connect(worker, frame, { id: childOptions.id, url: this.url }); - }; - - // Do this synchronously if possible - let frame = frames.getFrameForBrowser(browser(this)); - if (frame) { - attach(frame); - } - else { - let listener = (frame) => { - if (frame.frameElement != browser(this)) - return; - - frames.off("attach", listener); - attach(frame); - }; - frames.on("attach", listener); - } - - return worker; - }, - - destroy: function() { - if (isDestroyed(this)) - return; - - destroyed.set(this, true); - } -}); -exports.Tab = Tab; - -viewFor.define(Tab, tab => viewsFor.get(tab)); - -// Returns the high-level window for this DOM window if the windows module has -// ever been loaded otherwise returns null -function maybeWindowFor(domWindow) { - try { - return modelFor(domWindow); - } - catch (e) { - return null; - } -} - -function tabEmit(tab, event, ...args) { - // Don't emit events for destroyed tabs - if (isDestroyed(tab)) - return; - - // If the windows module was never loaded this will return null. We don't need - // to emit to the window.tabs object in this case as nothing can be listening. - let tabElement = viewsFor.get(tab); - let window = maybeWindowFor(tabElement.ownerDocument.defaultView); - if (window) - emit(window.tabs, event, tab, ...args); - - emit(tabEvents, event, tab, ...args); - emit(tab, event, tab, ...args); -} - -function windowClosed(domWindow) { - if (!isBrowser(domWindow)) - return; - - for (let tabElement of getTabs(domWindow)) { - tabEventListener("close", tabElement); - } -} -windowObserver.on('close', windowClosed); - -// Don't want to send close events after unloaded -when(_ => { - windowObserver.off('close', windowClosed); -}); - -// Listen for tabbrowser events -function tabEventListener(event, tabElement, ...args) { - let domWindow = tabElement.ownerDocument.defaultView; - - if (ignoreWindow(domWindow)) - return; - - // Don't send events for tabs that are already closing - if (event != "close" && (tabElement.closing || !tabElement.parentNode)) - return; - - let tab = modelsFor.get(tabElement); - if (!tab) - tab = new Tab(tabElement); - - let window = maybeWindowFor(domWindow); - - if (event == "open") { - // Note, add to the window tabs first because if this is the first access to - // window.tabs it will be prefilling itself with everything from tabs - if (window) - addListItem(window.tabs, tab); - // The tabs module will take care of adding to its internal list - } - else if (event == "close") { - if (window) - removeListItem(window.tabs, tab); - // The tabs module will take care of removing from its internal list - } - else if (event == "init" || event == "create" || event == "ready" || event == "load") { - // Ignore load events from before browser windows have fully loaded, these - // are for about:blank in the initial tab - if (isBrowser(domWindow) && !domWindow.gBrowserInit.delayedStartupFinished) - return; - - // update the cached remote readyState value - let { readyState } = args[0] || {}; - tab[remoteReadyStateCached] = readyState; - } - - if (event == "init") { - // Do not emit events for the detected existent tabs, we only need to cache - // their current document.readyState value. - return; - } - - tabEmit(tab, event, ...args); - - // The tab object shouldn't be reachable after closed - if (event == "close") { - viewsFor.delete(tab); - modelsFor.delete(tabElement); - } -} -observer.on('*', tabEventListener); - -// Listen for tab events from content -frames.port.on('sdk/tab/event', (frame, event, ...args) => { - if (!frame.isTab) - return; - - let tabElement = getTabForBrowser(frame.frameElement); - if (!tabElement) - return; - - tabEventListener(event, tabElement, ...args); -}); - -// Implement `modelFor` function for the Tab instances.. -modelFor.when(isTab, view => { - return modelsFor.get(view); -}); diff --git a/addon-sdk/source/lib/sdk/tabs/tab.js b/addon-sdk/source/lib/sdk/tabs/tab.js deleted file mode 100644 index fa2272494..000000000 --- a/addon-sdk/source/lib/sdk/tabs/tab.js +++ /dev/null @@ -1,24 +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'; - -module.metadata = { - 'stability': 'unstable' -}; - -const { getTargetWindow } = require("../content/mod"); -const { getTabContentWindow, isTab } = require("./utils"); -const { viewFor } = require("../view/core"); - -if (require('../system/xul-app').name == 'Fennec') { - module.exports = require('./tab-fennec'); -} -else { - module.exports = require('./tab-firefox'); -} - -getTargetWindow.when(isTab, tab => getTabContentWindow(tab)); - -getTargetWindow.when(x => x instanceof module.exports.Tab, - tab => getTabContentWindow(viewFor(tab))); diff --git a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js b/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js deleted file mode 100644 index 1eefecb4c..000000000 --- a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js +++ /dev/null @@ -1,135 +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 { Class } = require('../core/heritage'); -const { Tab, tabEvents } = require('./tab'); -const { EventTarget } = require('../event/target'); -const { emit, setListeners } = require('../event/core'); -const { pipe } = require('../event/utils'); -const { observer: windowObserver } = require('../windows/observer'); -const { List, addListItem, removeListItem } = require('../util/list'); -const { modelFor } = require('../model/core'); -const { viewFor } = require('../view/core'); -const { getTabs, getSelectedTab } = require('./utils'); -const { getMostRecentBrowserWindow, isBrowser } = require('../window/utils'); -const { Options } = require('./common'); -const { isPrivate } = require('../private-browsing'); -const { ignoreWindow, isWindowPBSupported } = require('../private-browsing/utils') -const { isPrivateBrowsingSupported } = require('sdk/self'); - -const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported; - -const Tabs = Class({ - implements: [EventTarget], - extends: List, - initialize: function() { - List.prototype.initialize.call(this); - - // We must do the list manipulation here where the object is extensible - this.on("open", tab => { - addListItem(this, tab); - }); - - this.on("close", tab => { - removeListItem(this, tab); - }); - }, - - get activeTab() { - let activeDomWin = getMostRecentBrowserWindow(); - if (!activeDomWin) - return null; - return modelFor(getSelectedTab(activeDomWin)); - }, - - open: function(options) { - options = Options(options); - - // TODO: Remove the dependency on the windows module: bug 792670 - let windows = require('../windows').browserWindows; - let activeWindow = windows.activeWindow; - - let privateState = supportPrivateTabs && options.isPrivate; - // When no isPrivate option was passed use the private state of the active - // window - if (activeWindow && privateState === undefined) - privateState = isPrivate(activeWindow); - - function getWindow(privateState) { - for (let window of windows) { - if (privateState === isPrivate(window)) { - return window; - } - } - return null; - } - - function openNewWindowWithTab() { - windows.open({ - url: options.url, - isPrivate: privateState, - onOpen: function(newWindow) { - let tab = newWindow.tabs[0]; - setListeners(tab, options); - - if (options.isPinned) - tab.pin(); - - // We don't emit the open event for the first tab in a new window so - // do it now the listeners are attached - emit(tab, "open", tab); - } - }); - } - - if (options.inNewWindow) - return openNewWindowWithTab(); - - // if the active window is in the state that we need then use it - if (activeWindow && (privateState === isPrivate(activeWindow))) - return activeWindow.tabs.open(options); - - // find a window in the state that we need - let window = getWindow(privateState); - if (window) - return window.tabs.open(options); - - return openNewWindowWithTab(); - } -}); - -const allTabs = new Tabs(); -// Export a new object with allTabs as the prototype, otherwise allTabs becomes -// frozen and addListItem and removeListItem don't work correctly. -module.exports = Object.create(allTabs); -pipe(tabEvents, module.exports); - -function addWindowTab(window, tabElement) { - let tab = new Tab(tabElement); - if (window) - addListItem(window.tabs, tab); - addListItem(allTabs, tab); - emit(allTabs, "open", tab); -} - -// Find tabs in already open windows -for (let tabElement of getTabs()) - addWindowTab(null, tabElement); - -// Detect tabs in new windows -windowObserver.on('open', domWindow => { - if (!isBrowser(domWindow) || ignoreWindow(domWindow)) - return; - - let window = null; - try { - modelFor(domWindow); - } - catch (e) { } - - for (let tabElement of getTabs(domWindow)) { - addWindowTab(window, tabElement); - } -}); diff --git a/addon-sdk/source/lib/sdk/tabs/utils.js b/addon-sdk/source/lib/sdk/tabs/utils.js deleted file mode 100644 index eae3d41fe..000000000 --- a/addon-sdk/source/lib/sdk/tabs/utils.js +++ /dev/null @@ -1,370 +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'; - -module.metadata = { - 'stability': 'unstable' -}; - - -// NOTE: This file should only deal with xul/native tabs - - -const { Ci, Cu } = require('chrome'); -const { defer } = require("../lang/functional"); -const { windows, isBrowser } = require('../window/utils'); -const { isPrivateBrowsingSupported } = require('../self'); -const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm"); - -// Bug 834961: ignore private windows when they are not supported -function getWindows() { - return windows(null, { includePrivate: isPrivateBrowsingSupported }); -} - -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - -// Define predicate functions that can be used to detech weather -// we deal with fennec tabs or firefox tabs. - -// Predicate to detect whether tab is XUL "Tab" node. -const isXULTab = tab => - tab instanceof Ci.nsIDOMNode && - tab.nodeName === "tab" && - tab.namespaceURI === XUL_NS; -exports.isXULTab = isXULTab; - -// Predicate to detecet whether given tab is a fettec tab. -// Unfortunately we have to guess via duck typinng of: -// http://mxr.mozilla.org/mozilla-central/source/mobile/android/chrome/content/browser.js#2583 -const isFennecTab = tab => - tab && - tab.QueryInterface && - Ci.nsIBrowserTab && - tab.QueryInterface(Ci.nsIBrowserTab) === tab; -exports.isFennecTab = isFennecTab; - -const isTab = x => isXULTab(x) || isFennecTab(x); -exports.isTab = isTab; - -function activateTab(tab, window) { - let gBrowser = getTabBrowserForTab(tab); - - // normal case - if (gBrowser) { - gBrowser.selectedTab = tab; - } - // fennec ? - else if (window && window.BrowserApp) { - window.BrowserApp.selectTab(tab); - } - return null; -} -exports.activateTab = activateTab; - -function getTabBrowser(window) { - // bug 1009938 - may be null in SeaMonkey - return window.gBrowser || window.getBrowser(); -} -exports.getTabBrowser = getTabBrowser; - -function getTabContainer(window) { - return getTabBrowser(window).tabContainer; -} -exports.getTabContainer = getTabContainer; - -/** - * Returns the tabs for the `window` if given, or the tabs - * across all the browser's windows otherwise. - * - * @param {nsIWindow} [window] - * A reference to a window - * - * @returns {Array} an array of Tab objects - */ -function getTabs(window) { - if (arguments.length === 0) { - return getWindows(). - filter(isBrowser). - reduce((tabs, window) => tabs.concat(getTabs(window)), []); - } - - // fennec - if (window.BrowserApp) - return window.BrowserApp.tabs; - - // firefox - default - return Array.filter(getTabContainer(window).children, t => !t.closing); -} -exports.getTabs = getTabs; - -function getActiveTab(window) { - return getSelectedTab(window); -} -exports.getActiveTab = getActiveTab; - -function getOwnerWindow(tab) { - // normal case - if (tab.ownerDocument) - return tab.ownerDocument.defaultView; - - // try fennec case - return getWindowHoldingTab(tab); -} -exports.getOwnerWindow = getOwnerWindow; - -// fennec -function getWindowHoldingTab(rawTab) { - for (let window of getWindows()) { - // this function may be called when not using fennec, - // but BrowserApp is only defined on Fennec - if (!window.BrowserApp) - continue; - - for (let tab of window.BrowserApp.tabs) { - if (tab === rawTab) - return window; - } - } - - return null; -} - -function openTab(window, url, options) { - options = options || {}; - - // fennec? - if (window.BrowserApp) { - return window.BrowserApp.addTab(url, { - selected: options.inBackground ? false : true, - pinned: options.isPinned || false, - isPrivate: options.isPrivate || false, - parentId: window.BrowserApp.selectedTab.id - }); - } - - // firefox - let newTab = window.gBrowser.addTab(url); - if (!options.inBackground) { - activateTab(newTab); - } - return newTab; -}; -exports.openTab = openTab; - -function isTabOpen(tab) { - // try normal case then fennec case - return !!((tab.linkedBrowser) || getWindowHoldingTab(tab)); -} -exports.isTabOpen = isTabOpen; - -function closeTab(tab) { - let gBrowser = getTabBrowserForTab(tab); - // normal case? - if (gBrowser) { - // Bug 699450: the tab may already have been detached - if (!tab.parentNode) - return; - return gBrowser.removeTab(tab); - } - - let window = getWindowHoldingTab(tab); - // fennec? - if (window && window.BrowserApp) { - // Bug 699450: the tab may already have been detached - if (!tab.browser) - return; - return window.BrowserApp.closeTab(tab); - } - return null; -} -exports.closeTab = closeTab; - -function getURI(tab) { - if (tab.browser) // fennec - return tab.browser.currentURI.spec; - return tab.linkedBrowser.currentURI.spec; -} -exports.getURI = getURI; - -function getTabBrowserForTab(tab) { - let outerWin = getOwnerWindow(tab); - if (outerWin) - return getOwnerWindow(tab).gBrowser; - return null; -} -exports.getTabBrowserForTab = getTabBrowserForTab; - -function getBrowserForTab(tab) { - if (tab.browser) // fennec - return tab.browser; - - return tab.linkedBrowser; -} -exports.getBrowserForTab = getBrowserForTab; - -function getTabId(tab) { - if (tab.browser) // fennec - return tab.id - - return String.split(tab.linkedPanel, 'panel').pop(); -} -exports.getTabId = getTabId; - -function getTabForId(id) { - return getTabs().find(tab => getTabId(tab) === id) || null; -} -exports.getTabForId = getTabForId; - -function getTabTitle(tab) { - return getBrowserForTab(tab).contentTitle || tab.label || ""; -} -exports.getTabTitle = getTabTitle; - -function setTabTitle(tab, title) { - title = String(title); - if (tab.browser) { - // Fennec - tab.browser.contentDocument.title = title; - } - else { - let browser = getBrowserForTab(tab); - // Note that we aren't actually setting the document title in e10s, just - // the title the browser thinks the content has - if (browser.isRemoteBrowser) - browser._contentTitle = title; - else - browser.contentDocument.title = title; - } - tab.label = String(title); -} -exports.setTabTitle = setTabTitle; - -function getTabContentDocument(tab) { - return getBrowserForTab(tab).contentDocument; -} -exports.getTabContentDocument = getTabContentDocument; - -function getTabContentWindow(tab) { - return getBrowserForTab(tab).contentWindow; -} -exports.getTabContentWindow = getTabContentWindow; - -/** - * Returns all tabs' content windows across all the browsers' windows - */ -function getAllTabContentWindows() { - return getTabs().map(getTabContentWindow); -} -exports.getAllTabContentWindows = getAllTabContentWindows; - -// gets the tab containing the provided window -function getTabForContentWindow(window) { - return getTabs().find(tab => getTabContentWindow(tab) === window.top) || null; -} -exports.getTabForContentWindow = getTabForContentWindow; - -// only sdk/selection.js is relying on shims -function getTabForContentWindowNoShim(window) { - function getTabContentWindowNoShim(tab) { - let browser = getBrowserForTab(tab); - return ShimWaiver.getProperty(browser, "contentWindow"); - } - return getTabs().find(tab => getTabContentWindowNoShim(tab) === window.top) || null; -} -exports.getTabForContentWindowNoShim = getTabForContentWindowNoShim; - -function getTabURL(tab) { - return String(getBrowserForTab(tab).currentURI.spec); -} -exports.getTabURL = getTabURL; - -function setTabURL(tab, url) { - let browser = getBrowserForTab(tab); - browser.loadURI(String(url)); -} -// "TabOpen" event is fired when it's still "about:blank" is loaded in the -// changing `location` property of the `contentDocument` has no effect since -// seems to be either ignored or overridden by internal listener, there for -// location change is enqueued for the next turn of event loop. -exports.setTabURL = defer(setTabURL); - -function getTabContentType(tab) { - return getBrowserForTab(tab).contentDocument.contentType; -} -exports.getTabContentType = getTabContentType; - -function getSelectedTab(window) { - if (window.BrowserApp) // fennec? - return window.BrowserApp.selectedTab; - if (window.gBrowser) - return window.gBrowser.selectedTab; - return null; -} -exports.getSelectedTab = getSelectedTab; - - -function getTabForBrowser(browser) { - for (let window of getWindows()) { - // this function may be called when not using fennec - if (!window.BrowserApp) - continue; - - for (let tab of window.BrowserApp.tabs) { - if (tab.browser === browser) - return tab; - } - } - - let tabbrowser = browser.getTabBrowser && browser.getTabBrowser() - return !!tabbrowser && tabbrowser.getTabForBrowser(browser); -} -exports.getTabForBrowser = getTabForBrowser; - -function pin(tab) { - let gBrowser = getTabBrowserForTab(tab); - // TODO: Implement Fennec support - if (gBrowser) gBrowser.pinTab(tab); -} -exports.pin = pin; - -function unpin(tab) { - let gBrowser = getTabBrowserForTab(tab); - // TODO: Implement Fennec support - if (gBrowser) gBrowser.unpinTab(tab); -} -exports.unpin = unpin; - -function isPinned(tab) { - return !!tab.pinned; -} -exports.isPinned = isPinned; - -function reload(tab) { - getBrowserForTab(tab).reload(); -} -exports.reload = reload - -function getIndex(tab) { - let gBrowser = getTabBrowserForTab(tab); - // Firefox - if (gBrowser) { - return tab._tPos; - } - // Fennec - else { - let window = getWindowHoldingTab(tab) - let tabs = window.BrowserApp.tabs; - for (let i = tabs.length; i >= 0; i--) - if (tabs[i] === tab) return i; - } -} -exports.getIndex = getIndex; - -function move(tab, index) { - let gBrowser = getTabBrowserForTab(tab); - // Firefox - if (gBrowser) gBrowser.moveTabTo(tab, index); - // TODO: Implement fennec support -} -exports.move = move; diff --git a/addon-sdk/source/lib/sdk/tabs/worker.js b/addon-sdk/source/lib/sdk/tabs/worker.js deleted file mode 100644 index d2ba33696..000000000 --- a/addon-sdk/source/lib/sdk/tabs/worker.js +++ /dev/null @@ -1,17 +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 ContentWorker = require('../content/worker').Worker; - -function Worker(options, window) { - options.window = window; - - let worker = ContentWorker(options); - worker.once("detach", function detach() { - worker.destroy(); - }); - return worker; -} -exports.Worker = Worker;
\ No newline at end of file |