addon-sdk/source/lib/sdk/tabs/tab-fennec.js

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:659dd40f4f1d
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 'use strict';
5
6 const { Cc, Ci } = require('chrome');
7 const { Class } = require('../core/heritage');
8 const { tabNS, rawTabNS } = require('./namespace');
9 const { EventTarget } = require('../event/target');
10 const { activateTab, getTabTitle, setTabTitle, closeTab, getTabURL, getTabContentWindow,
11 getTabForBrowser,
12 setTabURL, getOwnerWindow, getTabContentType, getTabId } = require('./utils');
13 const { emit } = require('../event/core');
14 const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
15 const { when: unload } = require('../system/unload');
16 const { viewFor } = require('../view/core');
17 const { EVENTS } = require('./events');
18
19 const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec';
20
21 const Tab = Class({
22 extends: EventTarget,
23 initialize: function initialize(options) {
24 options = options.tab ? options : { tab: options };
25 let tab = options.tab;
26
27 EventTarget.prototype.initialize.call(this, options);
28 let tabInternals = tabNS(this);
29 rawTabNS(tab).tab = this;
30
31 let window = tabInternals.window = options.window || getOwnerWindow(tab);
32 tabInternals.tab = tab;
33
34 // TabReady
35 let onReady = tabInternals.onReady = onTabReady.bind(this);
36 tab.browser.addEventListener(EVENTS.ready.dom, onReady, false);
37
38 // TabPageShow
39 let onPageShow = tabInternals.onPageShow = onTabPageShow.bind(this);
40 tab.browser.addEventListener(EVENTS.pageshow.dom, onPageShow, false);
41
42 // TabLoad
43 let onLoad = tabInternals.onLoad = onTabLoad.bind(this);
44 tab.browser.addEventListener(EVENTS.load.dom, onLoad, true);
45
46 // TabClose
47 let onClose = tabInternals.onClose = onTabClose.bind(this);
48 window.BrowserApp.deck.addEventListener(EVENTS.close.dom, onClose, false);
49
50 unload(cleanupTab.bind(null, this));
51 },
52
53 /**
54 * The title of the page currently loaded in the tab.
55 * Changing this property changes an actual title.
56 * @type {String}
57 */
58 get title() getTabTitle(tabNS(this).tab),
59 set title(title) setTabTitle(tabNS(this).tab, title),
60
61 /**
62 * Location of the page currently loaded in this tab.
63 * Changing this property will loads page under under the specified location.
64 * @type {String}
65 */
66 get url() {
67 return tabNS(this).closed ? undefined : getTabURL(tabNS(this).tab);
68 },
69 set url(url) setTabURL(tabNS(this).tab, url),
70
71 /**
72 * URI of the favicon for the page currently loaded in this tab.
73 * @type {String}
74 */
75 get favicon() {
76 /*
77 * Synchronous favicon services were never supported on Fennec,
78 * and as of FF22, are now deprecated. When/if favicon services
79 * are supported for Fennec, this getter should reference
80 * `require('sdk/places/favicon').getFavicon`
81 */
82 console.error(
83 'tab.favicon is deprecated, and currently ' +
84 'favicon helpers are not yet supported by Fennec'
85 );
86
87 // return 16x16 blank default
88 return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAEklEQVQ4jWNgGAWjYBSMAggAAAQQAAF/TXiOAAAAAElFTkSuQmCC';
89 },
90
91 getThumbnail: function() {
92 // TODO: implement!
93 console.error(ERR_FENNEC_MSG);
94
95 // return 80x45 blank default
96 return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAtCAYAAAA5reyyAAAAJElEQVRoge3BAQEAAACCIP+vbkhAAQAAAAAAAAAAAAAAAADXBjhtAAGQ0AF/AAAAAElFTkSuQmCC';
97 },
98
99 get id() {
100 return getTabId(tabNS(this).tab);
101 },
102
103 /**
104 * The index of the tab relative to other tabs in the application window.
105 * Changing this property will change order of the actual position of the tab.
106 * @type {Number}
107 */
108 get index() {
109 if (tabNS(this).closed) return undefined;
110
111 let tabs = tabNS(this).window.BrowserApp.tabs;
112 let tab = tabNS(this).tab;
113 for (var i = tabs.length; i >= 0; i--) {
114 if (tabs[i] === tab)
115 return i;
116 }
117 return null;
118 },
119 set index(value) {
120 console.error(ERR_FENNEC_MSG); // TODO
121 },
122
123 /**
124 * Whether or not tab is pinned (Is an app-tab).
125 * @type {Boolean}
126 */
127 get isPinned() {
128 console.error(ERR_FENNEC_MSG); // TODO
129 return false; // TODO
130 },
131 pin: function pin() {
132 console.error(ERR_FENNEC_MSG); // TODO
133 },
134 unpin: function unpin() {
135 console.error(ERR_FENNEC_MSG); // TODO
136 },
137
138 /**
139 * Returns the MIME type that the document loaded in the tab is being
140 * rendered as.
141 * @type {String}
142 */
143 get contentType() getTabContentType(tabNS(this).tab),
144
145 /**
146 * Create a worker for this tab, first argument is options given to Worker.
147 * @type {Worker}
148 */
149 attach: function attach(options) {
150 // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
151 // TODO: fix this circular dependency
152 let { Worker } = require('./worker');
153 return Worker(options, getTabContentWindow(tabNS(this).tab));
154 },
155
156 /**
157 * Make this tab active.
158 */
159 activate: function activate() {
160 activateTab(tabNS(this).tab, tabNS(this).window);
161 },
162
163 /**
164 * Close the tab
165 */
166 close: function close(callback) {
167 let tab = this;
168 this.once(EVENTS.close.name, function () {
169 tabNS(tab).closed = true;
170 if (callback) callback();
171 });
172
173 closeTab(tabNS(this).tab);
174 },
175
176 /**
177 * Reload the tab
178 */
179 reload: function reload() {
180 tabNS(this).tab.browser.reload();
181 }
182 });
183 exports.Tab = Tab;
184
185 // Implement `viewFor` polymorphic function for the Tab
186 // instances.
187 viewFor.define(Tab, x => tabNS(x).tab);
188
189 function cleanupTab(tab) {
190 let tabInternals = tabNS(tab);
191 if (!tabInternals.tab)
192 return;
193
194 if (tabInternals.tab.browser) {
195 tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady, false);
196 tabInternals.tab.browser.removeEventListener(EVENTS.pageshow.dom, tabInternals.onPageShow, false);
197 tabInternals.tab.browser.removeEventListener(EVENTS.load.dom, tabInternals.onLoad, true);
198 }
199 tabInternals.onReady = null;
200 tabInternals.onPageShow = null;
201 tabInternals.onLoad = null;
202 tabInternals.window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, tabInternals.onClose, false);
203 tabInternals.onClose = null;
204 rawTabNS(tabInternals.tab).tab = null;
205 tabInternals.tab = null;
206 tabInternals.window = null;
207 }
208
209 function onTabReady(event) {
210 let win = event.target.defaultView;
211
212 // ignore frames
213 if (win === win.top) {
214 emit(this, 'ready', this);
215 }
216 }
217
218 function onTabLoad (event) {
219 let win = event.target.defaultView;
220
221 // ignore frames
222 if (win === win.top) {
223 emit(this, 'load', this);
224 }
225 }
226
227 function onTabPageShow(event) {
228 let win = event.target.defaultView;
229 if (win === win.top)
230 emit(this, 'pageshow', this, event.persisted);
231 }
232
233 // TabClose
234 function onTabClose(event) {
235 let rawTab = getTabForBrowser(event.target);
236 if (tabNS(this).tab !== rawTab)
237 return;
238
239 emit(this, EVENTS.close.name, this);
240 cleanupTab(this);
241 };
242
243 getPBOwnerWindow.define(Tab, function(tab) {
244 return getTabContentWindow(tabNS(tab).tab);
245 });

mercurial