diff options
author | Matt A. Tobin <email@mattatobin.com> | 2018-02-09 06:46:43 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2018-02-09 06:46:43 -0500 |
commit | ac46df8daea09899ce30dc8fd70986e258c746bf (patch) | |
tree | 2750d3125fc253fd5b0671e4bd268eff1fd97296 /toolkit/jetpack/sdk/tabs/tab-fennec.js | |
parent | 8cecf8d5208f3945b35f879bba3015bb1a11bec6 (diff) | |
download | UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.gz UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.lz UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.xz UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.zip |
Move Add-on SDK source to toolkit/jetpack
Diffstat (limited to 'toolkit/jetpack/sdk/tabs/tab-fennec.js')
-rw-r--r-- | toolkit/jetpack/sdk/tabs/tab-fennec.js | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/tabs/tab-fennec.js b/toolkit/jetpack/sdk/tabs/tab-fennec.js new file mode 100644 index 000000000..3927337f6 --- /dev/null +++ b/toolkit/jetpack/sdk/tabs/tab-fennec.js @@ -0,0 +1,249 @@ +/* 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; +}); |