1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/metro/base/content/startui/RemoteTabsView.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,143 @@ 1.4 +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +"use strict"; 1.10 + 1.11 +const Cu = Components.utils; 1.12 + 1.13 +Cu.import("resource://services-sync/main.js"); 1.14 +Cu.import("resource://gre/modules/PlacesUtils.jsm", this); 1.15 + 1.16 +/** 1.17 + * Wraps a list/grid control implementing nsIDOMXULSelectControlElement and 1.18 + * fills it with the user's synced tabs. 1.19 + * 1.20 + * Note, the Sync module takes care of initializing the sync service. We should 1.21 + * not make calls that start sync or sync tabs since this module loads really 1.22 + * early during startup. 1.23 + * 1.24 + * @param aSet Control implementing nsIDOMXULSelectControlElement. 1.25 + * @param aSetUIAccess The UI element that should be hidden when Sync is 1.26 + * disabled. Must sanely support 'hidden' attribute. 1.27 + * You may only have one UI access point at this time. 1.28 + */ 1.29 +function RemoteTabsView(aSet, aSetUIAccessList) { 1.30 + View.call(this, aSet); 1.31 + 1.32 + this._uiAccessElements = aSetUIAccessList; 1.33 + 1.34 + // Sync uses special voodoo observers. 1.35 + // If you want to change this code, talk to the fx-si team 1.36 + Weave.Svc.Obs.add("weave:service:sync:finish", this); 1.37 + Weave.Svc.Obs.add("weave:service:start-over", this); 1.38 + 1.39 + if (this.isSyncEnabled() ) { 1.40 + this.populateGrid(); 1.41 + } 1.42 + else { 1.43 + this.setUIAccessVisible(false); 1.44 + } 1.45 +} 1.46 + 1.47 +RemoteTabsView.prototype = Util.extend(Object.create(View.prototype), { 1.48 + _set: null, 1.49 + _uiAccessElements: [], 1.50 + 1.51 + handleItemClick: function tabview_handleItemClick(aItem) { 1.52 + let url = aItem.getAttribute("value"); 1.53 + StartUI.goToURI(url); 1.54 + }, 1.55 + 1.56 + observe: function(subject, topic, data) { 1.57 + switch (topic) { 1.58 + case "weave:service:sync:finish": 1.59 + this.populateGrid(); 1.60 + break; 1.61 + case "weave:service:start-over": 1.62 + this.setUIAccessVisible(false); 1.63 + break; 1.64 + } 1.65 + }, 1.66 + 1.67 + setUIAccessVisible: function setUIAccessVisible(aVisible) { 1.68 + for (let elem of this._uiAccessElements) { 1.69 + elem.hidden = !aVisible; 1.70 + } 1.71 + }, 1.72 + 1.73 + getIcon: function (iconUri, defaultIcon) { 1.74 + try { 1.75 + let iconURI = Weave.Utils.makeURI(iconUri); 1.76 + return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec; 1.77 + } catch(ex) { 1.78 + // Do nothing. 1.79 + } 1.80 + 1.81 + // Just give the provided default icon or the system's default. 1.82 + return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec; 1.83 + }, 1.84 + 1.85 + populateGrid: function populateGrid() { 1.86 + 1.87 + let tabsEngine = Weave.Service.engineManager.get("tabs"); 1.88 + let list = this._set; 1.89 + let seenURLs = new Set(); 1.90 + let localURLs = tabsEngine.getOpenURLs(); 1.91 + 1.92 + // Clear grid, We don't know what has happened to tabs since last sync 1.93 + // Also can result in duplicate tabs(bug 864614) 1.94 + this._set.clearAll(); 1.95 + let show = false; 1.96 + for (let [guid, client] in Iterator(tabsEngine.getAllClients())) { 1.97 + client.tabs.forEach(function({title, urlHistory, icon}) { 1.98 + let url = urlHistory[0]; 1.99 + if (!url || getOpenURLs.has(url) || seenURLs.has(url)) { 1.100 + return; 1.101 + } 1.102 + seenURLs.add(url); 1.103 + show = true; 1.104 + 1.105 + // If we wish to group tabs by client, we should be looking for records 1.106 + // of {type:client, clientName, class:{mobile, desktop}} and will 1.107 + // need to readd logic to reset seenURLs for each client. 1.108 + 1.109 + let item = this._set.appendItem((title || url), url); 1.110 + item.setAttribute("iconURI", this.getIcon(icon)); 1.111 + 1.112 + }, this); 1.113 + } 1.114 + this.setUIAccessVisible(show); 1.115 + this._set.arrangeItems(); 1.116 + }, 1.117 + 1.118 + destruct: function destruct() { 1.119 + Weave.Svc.Obs.remove("weave:engine:sync:finish", this); 1.120 + Weave.Svc.Obs.remove("weave:service:logout:start-over", this); 1.121 + View.prototype.destruct.call(this); 1.122 + }, 1.123 + 1.124 + isSyncEnabled: function isSyncEnabled() { 1.125 + return (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED); 1.126 + } 1.127 + 1.128 +}); 1.129 + 1.130 +let RemoteTabsStartView = { 1.131 + _view: null, 1.132 + get _grid() { return document.getElementById("start-remotetabs-grid"); }, 1.133 + 1.134 + init: function init() { 1.135 + let vbox = document.getElementById("start-remotetabs"); 1.136 + let uiList = [vbox]; 1.137 + this._view = new RemoteTabsView(this._grid, uiList); 1.138 + this._grid.removeAttribute("fade"); 1.139 + }, 1.140 + 1.141 + uninit: function uninit() { 1.142 + if (this._view) { 1.143 + this._view.destruct(); 1.144 + } 1.145 + }, 1.146 +};