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

Side by Side Diff: safari/ext/background.js

Issue 5359707120205824: Issue 654 - Attach pages to their tabs to improve performance on Safari (Closed)
Patch Set: Created June 7, 2014, 2:46 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 (function() 18 (function()
19 { 19 {
20 /* Pages */ 20 /* Pages */
21 21
22 var pages = {__proto__: null}; 22 var pages = {__proto__: null};
23 var pageCounter = 0; 23 var pageCounter = 0;
24 24
25 var Page = function(id, tab, url, prerendered) 25 var Page = function(id, tab, url)
26 { 26 {
27 this._id = id; 27 this._id = id;
28 this._tab = tab; 28 this._tab = tab;
29 this._frames = [{url: url, parent: null}]; 29 this._frames = [{url: url, parent: null}];
30 this._prerendered = prerendered;
31 30
32 if (tab.page) 31 if (tab.page)
33 this._messageProxy = new ext._MessageProxy(tab.page); 32 this._messageProxy = new ext._MessageProxy(tab.page);
34 else 33 else
35 // while the new tab page is shown on Safari 7, the 'page' property 34 // while the new tab page is shown on Safari 7, the 'page' property
36 // of the tab is undefined, and we can't send messages to that page 35 // of the tab is undefined, and we can't send messages to that page
37 this._messageProxy = { 36 this._messageProxy = {
38 handleRequest: function() {}, 37 handleRequest: function() {},
39 handleResponse: function() {}, 38 handleResponse: function() {},
40 sendMessage: function() {} 39 sendMessage: function() {}
(...skipping 16 matching lines...) Expand all
57 this._tab.close(); 56 this._tab.close();
58 }, 57 },
59 sendMessage: function(message, responseCallback) 58 sendMessage: function(message, responseCallback)
60 { 59 {
61 this._messageProxy.sendMessage(message, responseCallback, {pageId: this._i d}); 60 this._messageProxy.sendMessage(message, responseCallback, {pageId: this._i d});
62 } 61 }
63 }; 62 };
64 63
65 var isPageActive = function(page) 64 var isPageActive = function(page)
66 { 65 {
67 return page._tab == page._tab.browserWindow.activeTab && !page._prerendered; 66 var tab = page._tab;
67 return tab == tab.browserWindow.activeTab && page == tab._visiblePage;
68 }; 68 };
69 69
70 var forgetPage = function(id) 70 var forgetPage = function(id)
71 { 71 {
72 ext._removeFromAllPageMaps(id); 72 ext._removeFromAllPageMaps(id);
73
74 delete pages[id]._tab._pages[id];
73 delete pages[id]; 75 delete pages[id];
74 }; 76 };
75 77
76 var replacePage = function(page) 78 var replacePage = function(page)
77 { 79 {
78 for (var id in pages) 80 page._tab._visiblePage = page;
81
82 for (var id in page._tab._pages)
79 { 83 {
80 if (id != page._id && pages[id]._tab == page._tab) 84 if (id != page._id)
81 forgetPage(id); 85 forgetPage(id);
82 } 86 }
83 87
84 if (isPageActive(page)) 88 if (isPageActive(page))
85 updateToolbarItemForPage(page); 89 updateToolbarItemForPage(page);
86 }; 90 };
87 91
88 ext.pages = { 92 ext.pages = {
89 open: function(url, callback) 93 open: function(url, callback)
90 { 94 {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // this event is dispatched on closing windows and tabs. However when a 136 // this event is dispatched on closing windows and tabs. However when a
133 // window is closed, it is first dispatched on each tab in the window and 137 // window is closed, it is first dispatched on each tab in the window and
134 // then on the window itself. But we are only interested in closed tabs. 138 // then on the window itself. But we are only interested in closed tabs.
135 if (!(event.target instanceof SafariBrowserTab)) 139 if (!(event.target instanceof SafariBrowserTab))
136 return; 140 return;
137 141
138 // when a tab is closed, forget the previous page associated with that 142 // when a tab is closed, forget the previous page associated with that
139 // tab. Note that it wouldn't be sufficient do that when the old page 143 // tab. Note that it wouldn't be sufficient do that when the old page
140 // is unloading, because Safari dispatches window.onunload only when 144 // is unloading, because Safari dispatches window.onunload only when
141 // reloading the page or following links, but not when closing the tab. 145 // reloading the page or following links, but not when closing the tab.
142 for (var id in pages) 146 for (var id in event.target._pages)
143 { 147 forgetPage(id);
144 if (pages[id]._tab == event.target)
145 forgetPage(id);
146 }
147 }, true); 148 }, true);
148 149
149 150
150 /* Browser actions */ 151 /* Browser actions */
151 152
152 var toolbarItemProperties = {}; 153 var toolbarItemProperties = {};
153 154
154 var getToolbarItemForWindow = function(win) 155 var getToolbarItemForWindow = function(win)
155 { 156 {
156 for (var i = 0; i < safari.extension.toolbarItems.length; i++) 157 for (var i = 0; i < safari.extension.toolbarItems.length; i++)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 { 221 {
221 // this event is also dispatched on windows that got focused. But we 222 // this event is also dispatched on windows that got focused. But we
222 // are only interested in tabs, which became active in their window. 223 // are only interested in tabs, which became active in their window.
223 if (!(event.target instanceof SafariBrowserTab)) 224 if (!(event.target instanceof SafariBrowserTab))
224 return; 225 return;
225 226
226 // update the toolbar item for the page visible in the tab that just 227 // update the toolbar item for the page visible in the tab that just
227 // became active. If we can't find that page (e.g. when a page was 228 // became active. If we can't find that page (e.g. when a page was
228 // opened in a new tab, and our content script didn't run yet), the 229 // opened in a new tab, and our content script didn't run yet), the
229 // toolbar item of the window, is reset to its intial configuration. 230 // toolbar item of the window, is reset to its intial configuration.
230 var activePage = null; 231 updateToolbarItemForPage(event.target._visiblePage, event.target.browserWind ow);
231 for (var id in pages)
232 {
233 var page = pages[id];
234 if (page._tab == event.target && !page._prerendered)
235 {
236 activePage = page;
237 break;
238 }
239 }
240
241 updateToolbarItemForPage(activePage, event.target.browserWindow);
242 }, true); 232 }, true);
243 233
244 234
245 /* Context menus */ 235 /* Context menus */
246 236
247 var contextMenuItems = new ext.PageMap(); 237 var contextMenuItems = new ext.PageMap();
248 238
249 var ContextMenus = function(page) 239 var ContextMenus = function(page)
250 { 240 {
251 this._page = page; 241 this._page = page;
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 var page = null; 523 var page = null;
534 var frame = null; 524 var frame = null;
535 525
536 var lastPage; 526 var lastPage;
537 var lastPageTopLevelFrame; 527 var lastPageTopLevelFrame;
538 528
539 // find the parent frame and its page for this sub frame, 529 // find the parent frame and its page for this sub frame,
540 // by matching its referrer with the URL of frames previously 530 // by matching its referrer with the URL of frames previously
541 // loaded in the same tab. If there is more than one match, 531 // loaded in the same tab. If there is more than one match,
542 // the most recent loaded page and frame is preferred. 532 // the most recent loaded page and frame is preferred.
543 for (var curPageId in pages) 533 for (var curPageId in (tab ? tab._pages : pages))
544 { 534 {
545 var curPage = pages[curPageId]; 535 var curPage = pages[curPageId];
546 if (tab && curPage._tab != tab)
547 continue;
548 536
549 for (var i = 0; i < curPage._frames.length; i++) 537 for (var i = 0; i < curPage._frames.length; i++)
550 { 538 {
551 var curFrame = curPage._frames[i]; 539 var curFrame = curPage._frames[i];
552 540
553 if (curFrame.url == url) 541 if (curFrame.url == url)
554 { 542 {
555 page = curPage; 543 page = curPage;
556 frame = curFrame; 544 frame = curFrame;
557 } 545 }
(...skipping 15 matching lines...) Expand all
573 }; 561 };
574 562
575 safari.application.addEventListener("message", function(event) 563 safari.application.addEventListener("message", function(event)
576 { 564 {
577 switch (event.name) 565 switch (event.name)
578 { 566 {
579 case "canLoad": 567 case "canLoad":
580 switch (event.message.category) 568 switch (event.message.category)
581 { 569 {
582 case "loading": 570 case "loading":
571 var tab = event.target;
572 var message = event.message;
573
583 var pageId; 574 var pageId;
584 var frameId; 575 var frameId;
585 576
586 if (event.message.isTopLevel) 577 if (message.isTopLevel)
587 { 578 {
588 pageId = ++pageCounter; 579 pageId = ++pageCounter;
589 frameId = 0; 580 frameId = 0;
590 581
591 var isPrerendered = event.message.isPrerendered; 582 var page = new Page(pageId, tab, message.url);
592 var page = new Page(
593 pageId,
594 event.target,
595 event.message.url,
596 isPrerendered
597 );
598 583
599 if (event.message.isPopup && !event.target._popupLoaded) 584 if (message.isPopup && !tab._popupLoaded)
600 { 585 {
601 if (!("_opener" in event.target)) 586 if (!("_opener" in tab))
602 event.target._opener = findPageAndFrame(null, event.message.re ferrer); 587 tab._opener = findPageAndFrame(null, message.referrer);
603 588
604 if (page.url != "about:blank") 589 if (page.url != "about:blank")
605 event.target._popupLoaded = true; 590 tab._popupLoaded = true;
606 591
607 ext.pages.onPopup._dispatch(page, event.target._opener); 592 ext.pages.onPopup._dispatch(page, tab._opener);
608 } 593 }
609 594
610 if (event.target.browserWindow) 595 if (tab.browserWindow)
611 { 596 {
612 pages[pageId] = page; 597 pages[pageId] = (tab._pages || (tab._pages = {__proto__: null})) [pageId] = page;
Wladimir Palant 2014/06/11 08:17:10 Seriously, don't be too clever - go for readable c
613 598
614 // when a new page is shown, forget the previous page associated 599 // when a new page is shown, forget the previous page associated
615 // with its tab, and reset the toolbar item if necessary. 600 // with its tab, and reset the toolbar item if necessary.
616 // Note that it wouldn't be sufficient to do that when the old 601 // Note that it wouldn't be sufficient to do that when the old
617 // page is unloading, because Safari dispatches window.onunload 602 // page is unloading, because Safari dispatches window.onunload
618 // only when reloading the page or following links, but not when 603 // only when reloading the page or following links, but not when
619 // you enter a new URL in the address bar. 604 // you enter a new URL in the address bar.
620 if (!isPrerendered) 605 if (!message.isPrerendered)
621 replacePage(page); 606 replacePage(page);
622 607
623 ext.pages.onLoading._dispatch(page); 608 ext.pages.onLoading._dispatch(page);
624 } 609 }
625 } 610 }
626 else 611 else
627 { 612 {
628 var parent = findPageAndFrame(event.target, event.message.referrer ); 613 var parent = findPageAndFrame(tab, message.referrer);
629 614
630 pageId = parent.page._id; 615 pageId = parent.page._id;
631 frameId = parent.page._frames.length; 616 frameId = parent.page._frames.length;
632 617
633 parent.page._frames.push({ 618 parent.page._frames.push({url: message.url, parent: parent.frame}) ;
634 url: event.message.url,
635 parent: parent.frame
636 });
637 } 619 }
638 620
639 event.message = {pageId: pageId, frameId: frameId}; 621 event.message = {pageId: pageId, frameId: frameId};
640 break; 622 break;
641 case "webRequest": 623 case "webRequest":
642 var page = pages[event.message.pageId]; 624 var page = pages[event.message.pageId];
643 625
644 event.message = ext.webRequest.onBeforeRequest._dispatch( 626 event.message = ext.webRequest.onBeforeRequest._dispatch(
645 event.message.url, 627 event.message.url,
646 event.message.type, 628 event.message.type,
647 page, 629 page,
648 page._frames[event.message.frameId] 630 page._frames[event.message.frameId]
649 ); 631 );
650 break; 632 break;
651 case "proxy": 633 case "proxy":
652 event.message = backgroundPageProxy.handleMessage(event.message); 634 event.message = backgroundPageProxy.handleMessage(event.message);
653 break; 635 break;
654 } 636 }
655 break; 637 break;
656 case "request": 638 case "request":
657 var page = pages[event.message.pageId]; 639 var page = pages[event.message.pageId];
658 var sender = {page: page, frame: page._frames[event.message.frameId]}; 640 var sender = {page: page, frame: page._frames[event.message.frameId]};
659 page._messageProxy.handleRequest(event.message, sender); 641 page._messageProxy.handleRequest(event.message, sender);
660 break; 642 break;
661 case "response": 643 case "response":
662 pages[event.message.pageId]._messageProxy.handleResponse(event.message); 644 pages[event.message.pageId]._messageProxy.handleResponse(event.message);
663 break; 645 break;
664 case "replaced": 646 case "replaced":
665 var page = pages[event.message.pageId];
666 page._prerendered = false;
667
668 // when a prerendered page is shown, forget the previous page 647 // when a prerendered page is shown, forget the previous page
669 // associated with its tab, and reset the toolbar item if necessary. 648 // associated with its tab, and reset the toolbar item if necessary.
670 // Note that it wouldn't be sufficient to do that when the old 649 // Note that it wouldn't be sufficient to do that when the old
671 // page is unloading, because Safari dispatches window.onunload 650 // page is unloading, because Safari dispatches window.onunload
672 // only when reloading the page or following links, but not when 651 // only when reloading the page or following links, but not when
673 // the current page is replaced with a prerendered page. 652 // the current page is replaced with a prerendered page.
674 replacePage(page); 653 replacePage(pages[event.message.pageId]);
675 break; 654 break;
676 } 655 }
677 }); 656 });
678 657
679 658
680 /* Storage */ 659 /* Storage */
681 660
682 ext.storage = safari.extension.settings; 661 ext.storage = safari.extension.settings;
683 })(); 662 })();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld