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