| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 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 /* Context menus */ | |
| 21 | |
| 22 var contextMenuItems = new ext.PageMap(); | |
| 23 | |
| 24 var ContextMenus = function(page) | |
| 25 { | |
| 26 this._page = page; | |
| 27 }; | |
| 28 ContextMenus.prototype = { | |
| 29 create: function(item) | |
| 30 { | |
| 31 var items = contextMenuItems.get(this._page); | |
| 32 if (!items) | |
| 33 contextMenuItems.set(this._page, items = []); | |
| 34 | |
| 35 items.push(item); | |
| 36 }, | |
| 37 removeAll: function() | |
| 38 { | |
| 39 contextMenuItems.delete(this._page); | |
| 40 } | |
| 41 }; | |
| 42 | |
| 43 safari.application.addEventListener("contextmenu", function(event) | |
| 44 { | |
| 45 if (!event.userInfo) | |
| 46 return; | |
| 47 | |
| 48 var pageId = event.userInfo.pageId; | |
| 49 if (!pageId) | |
| 50 return; | |
| 51 | |
| 52 var page = pages[event.userInfo.pageId]; | |
| 53 var items = contextMenuItems.get(page); | |
| 54 if (!items) | |
| 55 return; | |
| 56 | |
| 57 var context = event.userInfo.tagName; | |
| 58 if (context == "img") | |
| 59 context = "image"; | |
| 60 | |
| 61 for (var i = 0; i < items.length; i++) | |
| 62 { | |
| 63 // Supported contexts are: all, audio, image, video | |
| 64 var menuItem = items[i]; | |
| 65 if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(co ntext) == -1) | |
| 66 continue; | |
| 67 | |
| 68 event.contextMenu.appendContextMenuItem(i, menuItem.title); | |
| 69 } | |
| 70 }); | |
| 71 | |
| 72 safari.application.addEventListener("command", function(event) | |
| 73 { | |
| 74 var page = pages[event.userInfo.pageId]; | |
| 75 var items = contextMenuItems.get(page); | |
| 76 | |
| 77 items[event.command].onclick(page); | |
| 78 }); | |
| 79 | |
| 80 | |
| 81 /* Browser actions */ | |
| 82 | |
| 83 var toolbarItemProperties = {}; | |
| 84 | |
| 85 var getToolbarItemForWindow = function(win) | |
| 86 { | |
| 87 for (var i = 0; i < safari.extension.toolbarItems.length; i++) | |
| 88 { | |
| 89 var toolbarItem = safari.extension.toolbarItems[i]; | |
| 90 | |
| 91 if (toolbarItem.browserWindow == win) | |
| 92 return toolbarItem; | |
| 93 } | |
| 94 | |
| 95 return null; | |
| 96 }; | |
| 97 | |
| 98 var updateToolbarItemForPage = function(page, win) { | |
| 99 var toolbarItem = getToolbarItemForWindow(win); | |
| 100 if (!toolbarItem) | |
| 101 return; | |
| 102 | |
| 103 for (var name in toolbarItemProperties) | |
| 104 { | |
| 105 var property = toolbarItemProperties[name]; | |
| 106 | |
| 107 if (page && property.pages.has(page)) | |
| 108 toolbarItem[name] = property.pages.get(page); | |
| 109 else | |
| 110 toolbarItem[name] = property.global; | |
| 111 } | |
| 112 }; | |
| 113 | |
| 114 var BrowserAction = function(page) | |
| 115 { | |
| 116 this._page = page; | |
| 117 }; | |
| 118 BrowserAction.prototype = { | |
| 119 _set: function(name, value) | |
| 120 { | |
| 121 var toolbarItem = getToolbarItemForWindow(this._page._tab.browserWindow); | |
| 122 if (!toolbarItem) | |
| 123 return; | |
| 124 | |
| 125 var property = toolbarItemProperties[name]; | |
| 126 if (!property) | |
| 127 property = toolbarItemProperties[name] = { | |
| 128 pages: new ext.PageMap(), | |
| 129 global: toolbarItem[name] | |
| 130 }; | |
| 131 | |
| 132 property.pages.set(this._page, value); | |
| 133 | |
| 134 if (isPageActive(this._page)) | |
| 135 toolbarItem[name] = value; | |
| 136 }, | |
| 137 setIcon: function(path) | |
| 138 { | |
| 139 this._set("image", safari.extension.baseURI + path.replace("$size", "16")) ; | |
| 140 }, | |
| 141 setBadge: function(badge) | |
| 142 { | |
| 143 if (!badge) | |
| 144 this._set("badge", 0); | |
| 145 else if ("number" in badge) | |
| 146 this._set("badge", badge.number); | |
| 147 } | |
| 148 }; | |
| 149 | |
| 150 safari.application.addEventListener("activate", function(event) | |
| 151 { | |
| 152 // this event is also dispatched on windows that got focused. But we | |
| 153 // are only interested in tabs, which became active in their window. | |
| 154 if (!(event.target instanceof SafariBrowserTab)) | |
| 155 return; | |
| 156 | |
| 157 // update the toolbar item for the page visible in the tab that just | |
| 158 // became active. If we can't find that page (e.g. when a page was | |
| 159 // opened in a new tab, and our content script didn't run yet), the | |
| 160 // toolbar item of the window, is reset to its intial configuration. | |
| 161 updateToolbarItemForPage(event.target._visiblePage, event.target.browserWind ow); | |
| 162 }, true); | |
| 163 | |
| 164 | |
| 20 /* Pages */ | 165 /* Pages */ |
| 21 | 166 |
| 22 var pages = Object.create(null); | 167 var pages = Object.create(null); |
| 23 var pageCounter = 0; | 168 var pageCounter = 0; |
| 24 | 169 |
| 170 var Frame = function(url, parent) | |
| 171 { | |
| 172 this._urlString = url; | |
| 173 this._urlObj = null; | |
| 174 | |
| 175 this.parent = parent; | |
| 176 } | |
| 177 Frame.prototype = { | |
| 178 get url() | |
| 179 { | |
| 180 // On Safari 6 and before, the URL constuctor doesn't exist. | |
| 181 // The "urls" module provides a polifill, but it might not | |
| 182 // be loaded yet. So we have to lazily parse URLs. | |
| 183 if (!this._urlObj) | |
| 184 { | |
| 185 this._urlObj = new URL(this._urlString); | |
| 186 this._urlString = null; | |
| 187 } | |
| 188 | |
| 189 return this._urlObj; | |
| 190 } | |
| 191 }; | |
| 192 | |
| 25 var Page = function(id, tab, url) | 193 var Page = function(id, tab, url) |
| 26 { | 194 { |
| 27 this._id = id; | 195 this._id = id; |
| 28 this._tab = tab; | 196 this._tab = tab; |
| 29 this._frames = [{url: new URL(url), parent: null}]; | 197 this._frames = [new Frame(url, null)]; |
| 30 | 198 |
| 31 if (tab.page) | 199 if (tab.page) |
| 32 this._messageProxy = new ext._MessageProxy(tab.page); | 200 this._messageProxy = new ext._MessageProxy(tab.page); |
| 33 else | 201 else |
| 34 // while the new tab page is shown on Safari 7, the 'page' property | 202 // while the new tab page is shown on Safari 7, the 'page' property |
| 35 // of the tab is undefined, and we can't send messages to that page | 203 // of the tab is undefined, and we can't send messages to that page |
| 36 this._messageProxy = { | 204 this._messageProxy = { |
| 37 handleRequest: function() {}, | 205 handleRequest: function() {}, |
| 38 handleResponse: function() {}, | 206 handleResponse: function() {}, |
| 39 sendMessage: function() {} | 207 sendMessage: function() {} |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 for (var id in tab._pages) | 249 for (var id in tab._pages) |
| 82 { | 250 { |
| 83 if (id != page._id) | 251 if (id != page._id) |
| 84 forgetPage(id); | 252 forgetPage(id); |
| 85 } | 253 } |
| 86 | 254 |
| 87 if (isPageActive(page)) | 255 if (isPageActive(page)) |
| 88 updateToolbarItemForPage(page, tab.browserWindow); | 256 updateToolbarItemForPage(page, tab.browserWindow); |
| 89 }; | 257 }; |
| 90 | 258 |
| 259 var addPage = function(tab, url, prerendered) | |
| 260 { | |
| 261 var pageId = ++pageCounter; | |
| 262 | |
| 263 if (!('_pages' in tab)) | |
| 264 tab._pages = Object.create(null); | |
| 265 | |
| 266 var page = new Page(pageId, tab, url); | |
| 267 pages[pageId] = tab._pages[pageId] = page; | |
| 268 | |
| 269 // When a new page is shown, forget the previous page associated | |
| 270 // with its tab, and reset the toolbar item if necessary. | |
| 271 // Note that it wouldn't be sufficient to do that when the old | |
| 272 // page is unloading, because Safari dispatches window.onunload | |
| 273 // only when reloading the page or following links, but not when | |
| 274 // you enter a new URL in the address bar. | |
| 275 if (!prerendered) | |
| 276 replacePage(page); | |
| 277 | |
| 278 return pageId; | |
| 279 }; | |
| 280 | |
| 91 ext.pages = { | 281 ext.pages = { |
| 92 open: function(url, callback) | 282 open: function(url, callback) |
| 93 { | 283 { |
| 94 var tab = safari.application.activeBrowserWindow.openTab(); | 284 var tab = safari.application.activeBrowserWindow.openTab(); |
| 95 tab.url = url; | 285 tab.url = url; |
| 96 | 286 |
| 97 if (callback) | 287 if (callback) |
| 98 { | 288 { |
| 99 var onLoading = function(page) | 289 var onLoading = function(page) |
| 100 { | 290 { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 return; | 328 return; |
| 139 | 329 |
| 140 // when a tab is closed, forget the previous page associated with that | 330 // when a tab is closed, forget the previous page associated with that |
| 141 // tab. Note that it wouldn't be sufficient do that when the old page | 331 // tab. Note that it wouldn't be sufficient do that when the old page |
| 142 // is unloading, because Safari dispatches window.onunload only when | 332 // is unloading, because Safari dispatches window.onunload only when |
| 143 // reloading the page or following links, but not when closing the tab. | 333 // reloading the page or following links, but not when closing the tab. |
| 144 for (var id in event.target._pages) | 334 for (var id in event.target._pages) |
| 145 forgetPage(id); | 335 forgetPage(id); |
| 146 }, true); | 336 }, true); |
| 147 | 337 |
| 148 | 338 // We generally rely on content scripts to report new pages, |
| 149 /* Browser actions */ | 339 // since Safari's extension API doesn't consider pre-rendered |
| 150 | 340 // pages. However, when the extension initializes we have to |
| 151 var toolbarItemProperties = {}; | 341 // use Safari's extension API to detect existing tabs. |
| 152 | 342 safari.application.browserWindows.forEach(function(win) |
| 153 var getToolbarItemForWindow = function(win) | 343 { |
| 154 { | 344 for (var i = 0; i < win.tabs.length; i++) |
| 155 for (var i = 0; i < safari.extension.toolbarItems.length; i++) | 345 { |
| 156 { | 346 var tab = win.tabs[i]; |
| 157 var toolbarItem = safari.extension.toolbarItems[i]; | 347 var url = tab.url; |
| 158 | 348 |
| 159 if (toolbarItem.browserWindow == win) | 349 // For the new tab page the url property is undefined. |
| 160 return toolbarItem; | 350 if (url) |
| 161 } | 351 addPage(tab, url, false); |
| 162 | 352 } |
| 163 return null; | |
| 164 }; | |
| 165 | |
| 166 var updateToolbarItemForPage = function(page, win) { | |
| 167 var toolbarItem = getToolbarItemForWindow(win); | |
| 168 if (!toolbarItem) | |
| 169 return; | |
| 170 | |
| 171 for (var name in toolbarItemProperties) | |
| 172 { | |
| 173 var property = toolbarItemProperties[name]; | |
| 174 | |
| 175 if (page && property.pages.has(page)) | |
| 176 toolbarItem[name] = property.pages.get(page); | |
| 177 else | |
| 178 toolbarItem[name] = property.global; | |
| 179 } | |
| 180 }; | |
| 181 | |
| 182 var BrowserAction = function(page) | |
| 183 { | |
| 184 this._page = page; | |
| 185 }; | |
| 186 BrowserAction.prototype = { | |
| 187 _set: function(name, value) | |
| 188 { | |
| 189 var toolbarItem = getToolbarItemForWindow(this._page._tab.browserWindow); | |
| 190 if (!toolbarItem) | |
| 191 return; | |
| 192 | |
| 193 var property = toolbarItemProperties[name]; | |
| 194 if (!property) | |
| 195 property = toolbarItemProperties[name] = { | |
| 196 pages: new ext.PageMap(), | |
| 197 global: toolbarItem[name] | |
| 198 }; | |
| 199 | |
| 200 property.pages.set(this._page, value); | |
| 201 | |
| 202 if (isPageActive(this._page)) | |
| 203 toolbarItem[name] = value; | |
| 204 }, | |
| 205 setIcon: function(path) | |
| 206 { | |
| 207 this._set("image", safari.extension.baseURI + path.replace("$size", "16")) ; | |
| 208 }, | |
| 209 setBadge: function(badge) | |
| 210 { | |
| 211 if (!badge) | |
| 212 this._set("badge", 0); | |
| 213 else if ("number" in badge) | |
| 214 this._set("badge", badge.number); | |
| 215 } | |
| 216 }; | |
| 217 | |
| 218 safari.application.addEventListener("activate", function(event) | |
| 219 { | |
| 220 // this event is also dispatched on windows that got focused. But we | |
| 221 // are only interested in tabs, which became active in their window. | |
| 222 if (!(event.target instanceof SafariBrowserTab)) | |
| 223 return; | |
| 224 | |
| 225 // update the toolbar item for the page visible in the tab that just | |
| 226 // became active. If we can't find that page (e.g. when a page was | |
| 227 // opened in a new tab, and our content script didn't run yet), the | |
| 228 // toolbar item of the window, is reset to its intial configuration. | |
| 229 updateToolbarItemForPage(event.target._visiblePage, event.target.browserWind ow); | |
| 230 }, true); | |
| 231 | |
| 232 | |
| 233 /* Context menus */ | |
| 234 | |
| 235 var contextMenuItems = new ext.PageMap(); | |
| 236 | |
| 237 var ContextMenus = function(page) | |
| 238 { | |
| 239 this._page = page; | |
| 240 }; | |
| 241 ContextMenus.prototype = { | |
| 242 create: function(item) | |
| 243 { | |
| 244 var items = contextMenuItems.get(this._page); | |
| 245 if (!items) | |
| 246 contextMenuItems.set(this._page, items = []); | |
| 247 | |
| 248 items.push(item); | |
| 249 }, | |
| 250 removeAll: function() | |
| 251 { | |
| 252 contextMenuItems.delete(this._page); | |
| 253 } | |
| 254 }; | |
| 255 | |
| 256 safari.application.addEventListener("contextmenu", function(event) | |
| 257 { | |
| 258 if (!event.userInfo) | |
| 259 return; | |
| 260 | |
| 261 var pageId = event.userInfo.pageId; | |
| 262 if (!pageId) | |
| 263 return; | |
| 264 | |
| 265 var page = pages[event.userInfo.pageId]; | |
| 266 var items = contextMenuItems.get(page); | |
| 267 if (!items) | |
| 268 return; | |
| 269 | |
| 270 var context = event.userInfo.tagName; | |
| 271 if (context == "img") | |
| 272 context = "image"; | |
| 273 | |
| 274 for (var i = 0; i < items.length; i++) | |
| 275 { | |
| 276 // Supported contexts are: all, audio, image, video | |
| 277 var menuItem = items[i]; | |
| 278 if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(co ntext) == -1) | |
| 279 continue; | |
| 280 | |
| 281 event.contextMenu.appendContextMenuItem(i, menuItem.title); | |
| 282 } | |
| 283 }); | |
| 284 | |
| 285 safari.application.addEventListener("command", function(event) | |
| 286 { | |
| 287 var page = pages[event.userInfo.pageId]; | |
| 288 var items = contextMenuItems.get(page); | |
| 289 | |
| 290 items[event.command].onclick(page); | |
| 291 }); | 353 }); |
| 292 | 354 |
| 293 | 355 |
| 294 /* Web requests */ | 356 /* Web requests */ |
| 295 | 357 |
| 296 ext.webRequest = { | 358 ext.webRequest = { |
| 297 onBeforeRequest: new ext._EventTarget(), | 359 onBeforeRequest: new ext._EventTarget(), |
| 298 handlerBehaviorChanged: function() {}, | 360 handlerBehaviorChanged: function() {}, |
| 299 indistinguishableTypes: [["OTHER", "FONT"]] | 361 indistinguishableTypes: [["OTHER", "FONT"]] |
| 300 }; | 362 }; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 { | 580 { |
| 519 case "loading": | 581 case "loading": |
| 520 var tab = event.target; | 582 var tab = event.target; |
| 521 var message = event.message; | 583 var message = event.message; |
| 522 | 584 |
| 523 var pageId; | 585 var pageId; |
| 524 var frameId; | 586 var frameId; |
| 525 | 587 |
| 526 if (message.isTopLevel) | 588 if (message.isTopLevel) |
| 527 { | 589 { |
| 528 pageId = ++pageCounter; | 590 pageId = addPage(tab, message.url, message.isPrerendered); |
| 529 frameId = 0; | 591 frameId = 0; |
| 530 | 592 |
| 531 if (!('_pages' in tab)) | 593 ext.pages.onLoading._dispatch(pages[pageId]); |
| 532 tab._pages = Object.create(null); | |
| 533 | |
| 534 var page = new Page(pageId, tab, message.url); | |
| 535 pages[pageId] = tab._pages[pageId] = page; | |
| 536 | |
| 537 // when a new page is shown, forget the previous page associated | |
| 538 // with its tab, and reset the toolbar item if necessary. | |
| 539 // Note that it wouldn't be sufficient to do that when the old | |
| 540 // page is unloading, because Safari dispatches window.onunload | |
| 541 // only when reloading the page or following links, but not when | |
| 542 // you enter a new URL in the address bar. | |
| 543 if (!message.isPrerendered) | |
| 544 replacePage(page); | |
| 545 | |
| 546 ext.pages.onLoading._dispatch(page); | |
| 547 } | 594 } |
| 548 else | 595 else |
| 549 { | 596 { |
| 550 var page; | 597 var page; |
| 551 var parentFrame; | 598 var parentFrame; |
| 552 | 599 |
| 553 var lastPageId; | 600 var lastPageId; |
| 554 var lastPage; | 601 var lastPage; |
| 555 var lastPageTopLevelFrame; | 602 var lastPageTopLevelFrame; |
| 556 | 603 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 585 // if we can't find the parent frame and its page, fall back to | 632 // if we can't find the parent frame and its page, fall back to |
| 586 // the page most recently loaded in the tab and its top level fram e | 633 // the page most recently loaded in the tab and its top level fram e |
| 587 if (!page) | 634 if (!page) |
| 588 { | 635 { |
| 589 pageId = lastPageId; | 636 pageId = lastPageId; |
| 590 page = lastPage; | 637 page = lastPage; |
| 591 parentFrame = lastPageTopLevelFrame; | 638 parentFrame = lastPageTopLevelFrame; |
| 592 } | 639 } |
| 593 | 640 |
| 594 frameId = page._frames.length; | 641 frameId = page._frames.length; |
| 595 page._frames.push({url: new URL(message.url), parent: parentFrame} ); | 642 page._frames.push(new Frame(message.url, parentFrame)); |
| 596 } | 643 } |
| 597 | |
| 598 event.message = {pageId: pageId, frameId: frameId}; | 644 event.message = {pageId: pageId, frameId: frameId}; |
| 599 break; | 645 break; |
| 600 case "webRequest": | 646 case "webRequest": |
| 601 var page = pages[event.message.pageId]; | 647 var page = pages[event.message.pageId]; |
| 602 var frame = page._frames[event.message.frameId]; | 648 var frame = page._frames[event.message.frameId]; |
| 603 | 649 |
| 604 var results = ext.webRequest.onBeforeRequest._dispatch( | 650 var results = ext.webRequest.onBeforeRequest._dispatch( |
| 605 new URL(event.message.url, frame.url), | 651 new URL(event.message.url, frame.url), |
| 606 event.message.type, page, frame | 652 event.message.type, page, frame |
| 607 ); | 653 ); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 653 var items = {}; | 699 var items = {}; |
| 654 var settings = safari.extension.settings; | 700 var settings = safari.extension.settings; |
| 655 | 701 |
| 656 for (var i = 0; i < keys.length; i++) | 702 for (var i = 0; i < keys.length; i++) |
| 657 { | 703 { |
| 658 var key = keys[i]; | 704 var key = keys[i]; |
| 659 if (key in settings) | 705 if (key in settings) |
| 660 items[key] = settings[key]; | 706 items[key] = settings[key]; |
| 661 } | 707 } |
| 662 | 708 |
| 663 setTimeout(callback, 0, items); | 709 setTimeout(callback, 0, items); |
|
Wladimir Palant
2015/03/12 23:05:37
Did you verify that this works on all Safari versi
Sebastian Noack
2015/03/12 23:35:29
I saw this one coming. I checked MDN and made the
| |
| 664 }, | 710 }, |
| 665 set: function(key, value, callback) | 711 set: function(key, value, callback) |
| 666 { | 712 { |
| 667 safari.extension.settings[key] = value; | 713 safari.extension.settings[key] = value; |
| 668 | 714 |
| 669 if (callback) | 715 if (callback) |
| 670 setTimeout(callback, 0); | 716 setTimeout(callback, 0); |
| 671 }, | 717 }, |
| 672 remove: function(key, callback) | 718 remove: function(key, callback) |
| 673 { | 719 { |
| 674 delete safari.extension.settings[key]; | 720 delete safari.extension.settings[key]; |
| 675 | 721 |
| 676 if (callback) | 722 if (callback) |
| 677 setTimeout(callback, 0); | 723 setTimeout(callback, 0); |
| 678 }, | 724 }, |
| 679 onChanged: new ext._EventTarget(), | 725 onChanged: new ext._EventTarget(), |
| 680 | 726 |
| 681 // Preferences were previously encoded as JSON for compatibility | 727 // Preferences were previously encoded as JSON for compatibility |
| 682 // with localStorage, which has been used on Chrome. | 728 // with localStorage, which has been used on Chrome. |
| 683 migratePrefs: function(prefs) | 729 migratePrefs: function(hooks) |
| 684 { | 730 { |
| 685 var settings = safari.extension.settings; | 731 var settings = safari.extension.settings; |
| 686 | 732 |
| 687 for (var key in settings) | 733 for (var key in settings) |
| 688 { | 734 { |
| 689 if (key in prefs) | 735 var item = hooks.map(key, settings[key]); |
| 736 | |
| 737 if (item) | |
| 690 { | 738 { |
| 691 try | |
| 692 { | |
| 693 settings["pref:" + key] = JSON.parse(settings[key]); | |
| 694 } | |
| 695 catch (e) | |
| 696 { | |
| 697 } | |
| 698 | |
| 699 delete settings[key]; | 739 delete settings[key]; |
| 740 settings[item.key] = item.value; | |
| 700 } | 741 } |
| 701 } | 742 } |
| 743 | |
| 744 hooks.done(); | |
| 702 } | 745 } |
| 703 }; | 746 }; |
| 704 | 747 |
| 705 safari.extension.settings.addEventListener("change", function(event) | 748 safari.extension.settings.addEventListener("change", function(event) |
| 706 { | 749 { |
| 707 var changes = {}; | 750 var changes = {}; |
| 708 var change = changes[event.key] = {}; | 751 var change = changes[event.key] = {}; |
| 709 | 752 |
| 710 if (event.oldValue != null) | 753 if (event.oldValue != null) |
| 711 change.oldValue = event.oldValue; | 754 change.oldValue = event.oldValue; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 732 tab.activate(); | 775 tab.activate(); |
| 733 if (callback) | 776 if (callback) |
| 734 callback(page); | 777 callback(page); |
| 735 return; | 778 return; |
| 736 } | 779 } |
| 737 } | 780 } |
| 738 | 781 |
| 739 ext.pages.open(optionsUrl, callback); | 782 ext.pages.open(optionsUrl, callback); |
| 740 }; | 783 }; |
| 741 })(); | 784 })(); |
| LEFT | RIGHT |