Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | "use strict"; |
michael@0 | 7 | |
michael@0 | 8 | const Cu = Components.utils; |
michael@0 | 9 | |
michael@0 | 10 | Cu.import("resource://services-sync/main.js"); |
michael@0 | 11 | Cu.import("resource://gre/modules/PlacesUtils.jsm", this); |
michael@0 | 12 | |
michael@0 | 13 | /** |
michael@0 | 14 | * Wraps a list/grid control implementing nsIDOMXULSelectControlElement and |
michael@0 | 15 | * fills it with the user's synced tabs. |
michael@0 | 16 | * |
michael@0 | 17 | * Note, the Sync module takes care of initializing the sync service. We should |
michael@0 | 18 | * not make calls that start sync or sync tabs since this module loads really |
michael@0 | 19 | * early during startup. |
michael@0 | 20 | * |
michael@0 | 21 | * @param aSet Control implementing nsIDOMXULSelectControlElement. |
michael@0 | 22 | * @param aSetUIAccess The UI element that should be hidden when Sync is |
michael@0 | 23 | * disabled. Must sanely support 'hidden' attribute. |
michael@0 | 24 | * You may only have one UI access point at this time. |
michael@0 | 25 | */ |
michael@0 | 26 | function RemoteTabsView(aSet, aSetUIAccessList) { |
michael@0 | 27 | View.call(this, aSet); |
michael@0 | 28 | |
michael@0 | 29 | this._uiAccessElements = aSetUIAccessList; |
michael@0 | 30 | |
michael@0 | 31 | // Sync uses special voodoo observers. |
michael@0 | 32 | // If you want to change this code, talk to the fx-si team |
michael@0 | 33 | Weave.Svc.Obs.add("weave:service:sync:finish", this); |
michael@0 | 34 | Weave.Svc.Obs.add("weave:service:start-over", this); |
michael@0 | 35 | |
michael@0 | 36 | if (this.isSyncEnabled() ) { |
michael@0 | 37 | this.populateGrid(); |
michael@0 | 38 | } |
michael@0 | 39 | else { |
michael@0 | 40 | this.setUIAccessVisible(false); |
michael@0 | 41 | } |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | RemoteTabsView.prototype = Util.extend(Object.create(View.prototype), { |
michael@0 | 45 | _set: null, |
michael@0 | 46 | _uiAccessElements: [], |
michael@0 | 47 | |
michael@0 | 48 | handleItemClick: function tabview_handleItemClick(aItem) { |
michael@0 | 49 | let url = aItem.getAttribute("value"); |
michael@0 | 50 | StartUI.goToURI(url); |
michael@0 | 51 | }, |
michael@0 | 52 | |
michael@0 | 53 | observe: function(subject, topic, data) { |
michael@0 | 54 | switch (topic) { |
michael@0 | 55 | case "weave:service:sync:finish": |
michael@0 | 56 | this.populateGrid(); |
michael@0 | 57 | break; |
michael@0 | 58 | case "weave:service:start-over": |
michael@0 | 59 | this.setUIAccessVisible(false); |
michael@0 | 60 | break; |
michael@0 | 61 | } |
michael@0 | 62 | }, |
michael@0 | 63 | |
michael@0 | 64 | setUIAccessVisible: function setUIAccessVisible(aVisible) { |
michael@0 | 65 | for (let elem of this._uiAccessElements) { |
michael@0 | 66 | elem.hidden = !aVisible; |
michael@0 | 67 | } |
michael@0 | 68 | }, |
michael@0 | 69 | |
michael@0 | 70 | getIcon: function (iconUri, defaultIcon) { |
michael@0 | 71 | try { |
michael@0 | 72 | let iconURI = Weave.Utils.makeURI(iconUri); |
michael@0 | 73 | return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec; |
michael@0 | 74 | } catch(ex) { |
michael@0 | 75 | // Do nothing. |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | // Just give the provided default icon or the system's default. |
michael@0 | 79 | return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec; |
michael@0 | 80 | }, |
michael@0 | 81 | |
michael@0 | 82 | populateGrid: function populateGrid() { |
michael@0 | 83 | |
michael@0 | 84 | let tabsEngine = Weave.Service.engineManager.get("tabs"); |
michael@0 | 85 | let list = this._set; |
michael@0 | 86 | let seenURLs = new Set(); |
michael@0 | 87 | let localURLs = tabsEngine.getOpenURLs(); |
michael@0 | 88 | |
michael@0 | 89 | // Clear grid, We don't know what has happened to tabs since last sync |
michael@0 | 90 | // Also can result in duplicate tabs(bug 864614) |
michael@0 | 91 | this._set.clearAll(); |
michael@0 | 92 | let show = false; |
michael@0 | 93 | for (let [guid, client] in Iterator(tabsEngine.getAllClients())) { |
michael@0 | 94 | client.tabs.forEach(function({title, urlHistory, icon}) { |
michael@0 | 95 | let url = urlHistory[0]; |
michael@0 | 96 | if (!url || getOpenURLs.has(url) || seenURLs.has(url)) { |
michael@0 | 97 | return; |
michael@0 | 98 | } |
michael@0 | 99 | seenURLs.add(url); |
michael@0 | 100 | show = true; |
michael@0 | 101 | |
michael@0 | 102 | // If we wish to group tabs by client, we should be looking for records |
michael@0 | 103 | // of {type:client, clientName, class:{mobile, desktop}} and will |
michael@0 | 104 | // need to readd logic to reset seenURLs for each client. |
michael@0 | 105 | |
michael@0 | 106 | let item = this._set.appendItem((title || url), url); |
michael@0 | 107 | item.setAttribute("iconURI", this.getIcon(icon)); |
michael@0 | 108 | |
michael@0 | 109 | }, this); |
michael@0 | 110 | } |
michael@0 | 111 | this.setUIAccessVisible(show); |
michael@0 | 112 | this._set.arrangeItems(); |
michael@0 | 113 | }, |
michael@0 | 114 | |
michael@0 | 115 | destruct: function destruct() { |
michael@0 | 116 | Weave.Svc.Obs.remove("weave:engine:sync:finish", this); |
michael@0 | 117 | Weave.Svc.Obs.remove("weave:service:logout:start-over", this); |
michael@0 | 118 | View.prototype.destruct.call(this); |
michael@0 | 119 | }, |
michael@0 | 120 | |
michael@0 | 121 | isSyncEnabled: function isSyncEnabled() { |
michael@0 | 122 | return (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | }); |
michael@0 | 126 | |
michael@0 | 127 | let RemoteTabsStartView = { |
michael@0 | 128 | _view: null, |
michael@0 | 129 | get _grid() { return document.getElementById("start-remotetabs-grid"); }, |
michael@0 | 130 | |
michael@0 | 131 | init: function init() { |
michael@0 | 132 | let vbox = document.getElementById("start-remotetabs"); |
michael@0 | 133 | let uiList = [vbox]; |
michael@0 | 134 | this._view = new RemoteTabsView(this._grid, uiList); |
michael@0 | 135 | this._grid.removeAttribute("fade"); |
michael@0 | 136 | }, |
michael@0 | 137 | |
michael@0 | 138 | uninit: function uninit() { |
michael@0 | 139 | if (this._view) { |
michael@0 | 140 | this._view.destruct(); |
michael@0 | 141 | } |
michael@0 | 142 | }, |
michael@0 | 143 | }; |