Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: safari/ext/background.js

Issue 4937860104847360: Issue 2082 - Detect existing tabs when loading extension on Safari (Closed)
Patch Set: Added comments Created March 4, 2015, 11:03 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: safari/ext/background.js
===================================================================
--- a/safari/ext/background.js
+++ b/safari/ext/background.js
@@ -17,133 +17,65 @@
(function()
{
- /* Pages */
+ /* Context menus */
- var pages = Object.create(null);
- var pageCounter = 0;
+ var contextMenuItems = new ext.PageMap();
- var Page = function(id, tab, url)
+ var ContextMenus = function(page)
{
- this._id = id;
- this._tab = tab;
- this._frames = [{url: new URL(url), parent: null}];
+ this._page = page;
+ };
+ ContextMenus.prototype = {
+ create: function(item)
+ {
+ var items = contextMenuItems.get(this._page);
+ if (!items)
+ contextMenuItems.set(this._page, items = []);
- if (tab.page)
- this._messageProxy = new ext._MessageProxy(tab.page);
- else
- // while the new tab page is shown on Safari 7, the 'page' property
- // of the tab is undefined, and we can't send messages to that page
- this._messageProxy = {
- handleRequest: function() {},
- handleResponse: function() {},
- sendMessage: function() {}
- };
-
- this.browserAction = new BrowserAction(this);
- this.contextMenus = new ContextMenus(this);
- };
- Page.prototype = {
- get url()
+ items.push(item);
+ },
+ removeAll: function()
{
- return this._frames[0].url;
- },
- sendMessage: function(message, responseCallback)
- {
- this._messageProxy.sendMessage(message, responseCallback, {pageId: this._id});
+ contextMenuItems.delete(this._page);
}
};
- ext._getPage = function(id)
+ safari.application.addEventListener("contextmenu", function(event)
{
- return pages[id];
- };
-
- var isPageActive = function(page)
- {
- var tab = page._tab;
- var win = tab.browserWindow;
- return win && tab == win.activeTab && page == tab._visiblePage;
- };
-
- var forgetPage = function(id)
- {
- ext._removeFromAllPageMaps(id);
-
- delete pages[id]._tab._pages[id];
- delete pages[id];
- };
-
- var replacePage = function(page)
- {
- var tab = page._tab;
- tab._visiblePage = page;
-
- for (var id in tab._pages)
- {
- if (id != page._id)
- forgetPage(id);
- }
-
- if (isPageActive(page))
- updateToolbarItemForPage(page, tab.browserWindow);
- };
-
- ext.pages = {
- open: function(url, callback)
- {
- var tab = safari.application.activeBrowserWindow.openTab();
- tab.url = url;
-
- if (callback)
- {
- var onLoading = function(page)
- {
- if (page._tab == tab)
- {
- ext.pages.onLoading.removeListener(onLoading);
- callback(page);
- }
- };
- ext.pages.onLoading.addListener(onLoading);
- }
- },
- query: function(info, callback)
- {
- var matchedPages = [];
-
- for (var id in pages)
- {
- var page = pages[id];
- var win = page._tab.browserWindow;
-
- if ("active" in info && info.active != isPageActive(page))
- continue;
- if ("lastFocusedWindow" in info && info.lastFocusedWindow != (win == safari.application.activeBrowserWindow))
- continue;
-
- matchedPages.push(page);
- };
-
- callback(matchedPages);
- },
- onLoading: new ext._EventTarget()
- };
-
- safari.application.addEventListener("close", function(event)
- {
- // this event is dispatched on closing windows and tabs. However when a
- // window is closed, it is first dispatched on each tab in the window and
- // then on the window itself. But we are only interested in closed tabs.
- if (!(event.target instanceof SafariBrowserTab))
+ if (!event.userInfo)
return;
- // when a tab is closed, forget the previous page associated with that
- // tab. Note that it wouldn't be sufficient do that when the old page
- // is unloading, because Safari dispatches window.onunload only when
- // reloading the page or following links, but not when closing the tab.
- for (var id in event.target._pages)
- forgetPage(id);
- }, true);
+ var pageId = event.userInfo.pageId;
+ if (!pageId)
+ return;
+
+ var page = pages[event.userInfo.pageId];
+ var items = contextMenuItems.get(page);
+ if (!items)
+ return;
+
+ var context = event.userInfo.tagName;
+ if (context == "img")
+ context = "image";
+
+ for (var i = 0; i < items.length; i++)
+ {
+ // Supported contexts are: all, audio, image, video
+ var menuItem = items[i];
+ if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(context) == -1)
+ continue;
+
+ event.contextMenu.appendContextMenuItem(i, menuItem.title);
+ }
+ });
+
+ safari.application.addEventListener("command", function(event)
+ {
+ var page = pages[event.userInfo.pageId];
+ var items = contextMenuItems.get(page);
+
+ items[event.command].onclick(page);
+ });
/* Browser actions */
@@ -230,66 +162,173 @@
}, true);
- /* Context menus */
+ /* Pages */
- var contextMenuItems = new ext.PageMap();
+ var pages = Object.create(null);
+ var pageCounter = 0;
- var ContextMenus = function(page)
+ var Page = function(id, tab, url)
{
- this._page = page;
+ this._id = id;
+ this._tab = tab;
+ this._frames = [{url: new URL(url), parent: null}];
+
+ if (tab.page)
+ this._messageProxy = new ext._MessageProxy(tab.page);
+ else
+ // while the new tab page is shown on Safari 7, the 'page' property
+ // of the tab is undefined, and we can't send messages to that page
+ this._messageProxy = {
+ handleRequest: function() {},
+ handleResponse: function() {},
+ sendMessage: function() {}
+ };
+
+ this.browserAction = new BrowserAction(this);
+ this.contextMenus = new ContextMenus(this);
};
- ContextMenus.prototype = {
- create: function(item)
+ Page.prototype = {
+ get url()
{
- var items = contextMenuItems.get(this._page);
- if (!items)
- contextMenuItems.set(this._page, items = []);
-
- items.push(item);
+ return this._frames[0].url;
},
- removeAll: function()
+ sendMessage: function(message, responseCallback)
{
- contextMenuItems.delete(this._page);
+ this._messageProxy.sendMessage(message, responseCallback, {pageId: this._id});
}
};
- safari.application.addEventListener("contextmenu", function(event)
+ ext._getPage = function(id)
{
- if (!event.userInfo)
+ return pages[id];
+ };
+
+ var isPageActive = function(page)
+ {
+ var tab = page._tab;
+ var win = tab.browserWindow;
+ return win && tab == win.activeTab && page == tab._visiblePage;
+ };
+
+ var forgetPage = function(id)
+ {
+ ext._removeFromAllPageMaps(id);
+
+ delete pages[id]._tab._pages[id];
+ delete pages[id];
+ };
+
+ var replacePage = function(page)
+ {
+ var tab = page._tab;
+ tab._visiblePage = page;
+
+ for (var id in tab._pages)
+ {
+ if (id != page._id)
+ forgetPage(id);
+ }
+
+ if (isPageActive(page))
+ updateToolbarItemForPage(page, tab.browserWindow);
+ };
+
+ var addPage = function(tab, url, prerendered)
+ {
+ var pageId = ++pageCounter;
+
+ if (!('_pages' in tab))
+ tab._pages = Object.create(null);
+
+ var page = new Page(pageId, tab, url);
+ pages[pageId] = tab._pages[pageId] = page;
+
+ // When a new page is shown, forget the previous page associated
+ // with its tab, and reset the toolbar item if necessary.
+ // Note that it wouldn't be sufficient to do that when the old
+ // page is unloading, because Safari dispatches window.onunload
+ // only when reloading the page or following links, but not when
+ // you enter a new URL in the address bar.
+ if (!prerendered)
+ replacePage(page);
+
+ return pageId;
+ };
+
+ ext.pages = {
+ open: function(url, callback)
+ {
+ var tab = safari.application.activeBrowserWindow.openTab();
+ tab.url = url;
+
+ if (callback)
+ {
+ var onLoading = function(page)
+ {
+ if (page._tab == tab)
+ {
+ ext.pages.onLoading.removeListener(onLoading);
+ callback(page);
+ }
+ };
+ ext.pages.onLoading.addListener(onLoading);
+ }
+ },
+ query: function(info, callback)
+ {
+ var matchedPages = [];
+
+ for (var id in pages)
+ {
+ var page = pages[id];
+ var win = page._tab.browserWindow;
+
+ if ("active" in info && info.active != isPageActive(page))
+ continue;
+ if ("lastFocusedWindow" in info && info.lastFocusedWindow != (win == safari.application.activeBrowserWindow))
+ continue;
+
+ matchedPages.push(page);
+ };
+
+ callback(matchedPages);
+ },
+ onLoading: new ext._EventTarget()
+ };
+
+ safari.application.addEventListener("close", function(event)
+ {
+ // this event is dispatched on closing windows and tabs. However when a
+ // window is closed, it is first dispatched on each tab in the window and
+ // then on the window itself. But we are only interested in closed tabs.
+ if (!(event.target instanceof SafariBrowserTab))
return;
- var pageId = event.userInfo.pageId;
- if (!pageId)
- return;
+ // when a tab is closed, forget the previous page associated with that
+ // tab. Note that it wouldn't be sufficient do that when the old page
+ // is unloading, because Safari dispatches window.onunload only when
+ // reloading the page or following links, but not when closing the tab.
+ for (var id in event.target._pages)
+ forgetPage(id);
+ }, true);
- var page = pages[event.userInfo.pageId];
- var items = contextMenuItems.get(page);
- if (!items)
- return;
+ // We generally rely on content scripts to report new pages,
+ // since Safari's extension API doesn't consider pre-rendered
+ // pages. However, when the extension initializes we have to
+ // use Safari's extension API to detect existing tabs.
+ safari.application.browserWindows.forEach(function(win)
+ {
+ for (var i = 0; i < win.tabs.length; i++)
+ {
+ var tab = win.tabs[i];
+ var url = tab.url;
- var context = event.userInfo.tagName;
- if (context == "img")
- context = "image";
-
- for (var i = 0; i < items.length; i++)
- {
- // Supported contexts are: all, audio, image, video
- var menuItem = items[i];
- if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(context) == -1)
- continue;
-
- event.contextMenu.appendContextMenuItem(i, menuItem.title);
+ // For the new tab page the url property is undefined.
+ if (url)
+ addPage(tab, url, false);
}
});
- safari.application.addEventListener("command", function(event)
- {
- var page = pages[event.userInfo.pageId];
- var items = contextMenuItems.get(page);
-
- items[event.command].onclick(page);
- });
-
/* Web requests */
@@ -525,25 +564,10 @@
if (message.isTopLevel)
{
- pageId = ++pageCounter;
+ pageId = addPage(tab, message.url, message.isPrerendered);
frameId = 0;
- if (!('_pages' in tab))
- tab._pages = Object.create(null);
-
- var page = new Page(pageId, tab, message.url);
- pages[pageId] = tab._pages[pageId] = page;
-
- // when a new page is shown, forget the previous page associated
- // with its tab, and reset the toolbar item if necessary.
- // Note that it wouldn't be sufficient to do that when the old
- // page is unloading, because Safari dispatches window.onunload
- // only when reloading the page or following links, but not when
- // you enter a new URL in the address bar.
- if (!message.isPrerendered)
- replacePage(page);
-
- ext.pages.onLoading._dispatch(page);
+ ext.pages.onLoading._dispatch(pages[pageId]);
}
else
{
@@ -594,7 +618,6 @@
frameId = page._frames.length;
page._frames.push({url: new URL(message.url), parent: parentFrame});
}
-
event.message = {pageId: pageId, frameId: frameId};
break;
case "webRequest":
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld