123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /* 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, getTabContentType, getTabId } = require('./utils');
- const { emit } = require('../event/core');
- const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
- const { when: unload } = require('../system/unload');
- const { viewFor } = require('../view/core');
- const { EVENTS } = require('./events');
- 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);
- let onPageShow = tabInternals.onPageShow = onTabPageShow.bind(this);
- tab.browser.addEventListener(EVENTS.pageshow.dom, onPageShow, false);
- // 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() 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),
- /**
- * URI of the favicon for the page currently loaded in this tab.
- * @type {String}
- */
- get favicon() {
- /*
- * Synchronous favicon services were never supported on Fennec,
- * and as of FF22, are now deprecated. When/if favicon services
- * are supported for Fennec, this getter should reference
- * `require('sdk/places/favicon').getFavicon`
- */
- console.error(
- 'tab.favicon is deprecated, and currently ' +
- 'favicon helpers are not yet supported by Fennec'
- );
- // return 16x16 blank default
- return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAEklEQVQ4jWNgGAWjYBSMAggAAAQQAAF/TXiOAAAAAElFTkSuQmCC';
- },
- getThumbnail: function() {
- // TODO: implement!
- console.error(ERR_FENNEC_MSG);
- // return 80x45 blank default
- return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAtCAYAAAA5reyyAAAAJElEQVRoge3BAQEAAACCIP+vbkhAAQAAAAAAAAAAAAAAAADXBjhtAAGQ0AF/AAAAAElFTkSuQmCC';
- },
- 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() 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.onReady = null;
- tabInternals.onPageShow = 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 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);
- };
- getPBOwnerWindow.define(Tab, function(tab) {
- return getTabContentWindow(tabNS(tab).tab);
- });
|