| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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; |
| 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 })(); |
| OLD | NEW |