2010-08-02 16:37:56 -07:00
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
|
*
|
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
|
*
|
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
|
* License.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is Weave.
|
|
|
|
|
*
|
|
|
|
|
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2009
|
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s):
|
|
|
|
|
* Edward Lee <edilee@mozilla.com>
|
|
|
|
|
* Mike Connor <mconnor@mozilla.com>
|
|
|
|
|
* Paul O’Shannessy <paul@oshannessy.com>
|
|
|
|
|
*
|
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
|
*
|
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
|
2010-09-07 18:37:46 -07:00
|
|
|
|
Cu.import("resource://services-sync/main.js");
|
2010-08-02 16:37:56 -07:00
|
|
|
|
Cu.import("resource:///modules/PlacesUIUtils.jsm");
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
|
|
|
|
|
|
let RemoteTabViewer = {
|
|
|
|
|
_tabsList: null,
|
|
|
|
|
|
|
|
|
|
init: function () {
|
|
|
|
|
Services.obs.addObserver(this, "weave:service:login:finish", false);
|
|
|
|
|
Services.obs.addObserver(this, "weave:engine:sync:finish", false);
|
|
|
|
|
|
|
|
|
|
this._tabsList = document.getElementById("tabsList");
|
|
|
|
|
|
|
|
|
|
this.buildList(true);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
uninit: function () {
|
|
|
|
|
Services.obs.removeObserver(this, "weave:service:login:finish");
|
|
|
|
|
Services.obs.removeObserver(this, "weave:engine:sync:finish");
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
buildList: function(force) {
|
|
|
|
|
if (!Weave.Service.isLoggedIn || !this._refetchTabs(force))
|
|
|
|
|
return;
|
|
|
|
|
//XXXzpao We should say something about not being logged in & not having data
|
|
|
|
|
// or tell the appropriate condition. (bug 583344)
|
|
|
|
|
|
|
|
|
|
this._generateTabList();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
createItem: function(attrs) {
|
|
|
|
|
let item = document.createElement("richlistitem");
|
|
|
|
|
|
|
|
|
|
// Copy the attributes from the argument into the item
|
|
|
|
|
for (let attr in attrs)
|
|
|
|
|
item.setAttribute(attr, attrs[attr]);
|
|
|
|
|
|
|
|
|
|
if (attrs["type"] == "tab")
|
|
|
|
|
item.label = attrs.title != "" ? attrs.title : attrs.url;
|
|
|
|
|
|
|
|
|
|
return item;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
filterTabs: function(event) {
|
|
|
|
|
let val = event.target.value.toLowerCase();
|
|
|
|
|
let numTabs = this._tabsList.getRowCount();
|
|
|
|
|
let clientTabs = 0;
|
|
|
|
|
let currentClient = null;
|
|
|
|
|
for (let i = 0;i < numTabs;i++) {
|
|
|
|
|
let item = this._tabsList.getItemAtIndex(i);
|
|
|
|
|
let hide = false;
|
|
|
|
|
if (item.getAttribute("type") == "tab") {
|
|
|
|
|
if (item.getAttribute("url").toLowerCase().indexOf(val) == -1 &&
|
|
|
|
|
item.getAttribute("title").toLowerCase().indexOf(val) == -1)
|
|
|
|
|
hide = true;
|
|
|
|
|
else
|
|
|
|
|
clientTabs++;
|
|
|
|
|
}
|
|
|
|
|
else if (item.getAttribute("type") == "client") {
|
|
|
|
|
if (currentClient) {
|
|
|
|
|
if (clientTabs == 0)
|
|
|
|
|
currentClient.hidden = true;
|
|
|
|
|
}
|
|
|
|
|
currentClient = item;
|
|
|
|
|
clientTabs = 0;
|
|
|
|
|
}
|
|
|
|
|
item.hidden = hide;
|
|
|
|
|
}
|
|
|
|
|
if (clientTabs == 0)
|
|
|
|
|
currentClient.hidden = true;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
openSelected: function() {
|
|
|
|
|
let items = this._tabsList.selectedItems;
|
|
|
|
|
let urls = [];
|
|
|
|
|
for (let i = 0;i < items.length;i++) {
|
|
|
|
|
if (items[i].getAttribute("type") == "tab") {
|
|
|
|
|
urls.push(items[i].getAttribute("url"));
|
|
|
|
|
let index = this._tabsList.getIndexOfItem(items[i]);
|
|
|
|
|
this._tabsList.removeItemAt(index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (urls.length) {
|
|
|
|
|
getTopWin().gBrowser.loadTabs(urls);
|
|
|
|
|
this._tabsList.clearSelection();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
bookmarkSingleTab: function() {
|
|
|
|
|
let item = this._tabsList.selectedItems[0];
|
|
|
|
|
let uri = Weave.Utils.makeURI(item.getAttribute("url"));
|
|
|
|
|
let title = item.getAttribute("title");
|
|
|
|
|
PlacesUIUtils.showMinimalAddBookmarkUI(uri, title);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
bookmarkSelectedTabs: function() {
|
|
|
|
|
let items = this._tabsList.selectedItems;
|
|
|
|
|
let URIs = [];
|
|
|
|
|
for (let i = 0;i < items.length;i++) {
|
|
|
|
|
if (items[i].getAttribute("type") == "tab") {
|
|
|
|
|
let uri = Weave.Utils.makeURI(items[i].getAttribute("url"));
|
|
|
|
|
if (!uri)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
URIs.push(uri);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (URIs.length)
|
|
|
|
|
PlacesUIUtils.showMinimalAddMultiBookmarkUI(URIs);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
_generateTabList: function() {
|
|
|
|
|
let engine = Weave.Engines.get("tabs");
|
|
|
|
|
let list = this._tabsList;
|
|
|
|
|
|
|
|
|
|
// clear out existing richlistitems
|
|
|
|
|
let count = list.getRowCount();
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
for (let i = count - 1; i >= 0; i--)
|
|
|
|
|
list.removeItemAt(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (let [guid, client] in Iterator(engine.getAllClients())) {
|
|
|
|
|
// Create the client node, but don't add it in-case we don't show any tabs
|
|
|
|
|
let appendClient = true;
|
|
|
|
|
let seenURLs = {};
|
|
|
|
|
client.tabs.forEach(function({title, urlHistory, icon}) {
|
|
|
|
|
let url = urlHistory[0];
|
|
|
|
|
if (engine.locallyOpenTabMatchesURL(url) || url in seenURLs)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
seenURLs[url] = null;
|
|
|
|
|
|
|
|
|
|
if (appendClient) {
|
|
|
|
|
let attrs = {
|
|
|
|
|
type: "client",
|
|
|
|
|
clientName: client.clientName,
|
|
|
|
|
class: Weave.Clients.isMobile(client.id) ? "mobile" : "desktop"
|
|
|
|
|
};
|
|
|
|
|
let clientEnt = this.createItem(attrs);
|
|
|
|
|
list.appendChild(clientEnt);
|
|
|
|
|
appendClient = false;
|
|
|
|
|
clientEnt.disabled = true;
|
|
|
|
|
}
|
|
|
|
|
let attrs = {
|
|
|
|
|
type: "tab",
|
|
|
|
|
title: title || url,
|
|
|
|
|
url: url,
|
|
|
|
|
icon: Weave.Utils.getIcon(icon)
|
|
|
|
|
}
|
|
|
|
|
let tab = this.createItem(attrs);
|
|
|
|
|
list.appendChild(tab);
|
|
|
|
|
}, this);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
adjustContextMenu: function(event) {
|
|
|
|
|
let mode = "all";
|
|
|
|
|
switch (this._tabsList.selectedItems.length) {
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
mode = "single"
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
mode = "multiple";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
let menu = document.getElementById("tabListContext");
|
|
|
|
|
let el = menu.firstChild;
|
|
|
|
|
while (el) {
|
|
|
|
|
let showFor = el.getAttribute("showFor");
|
|
|
|
|
if (showFor)
|
|
|
|
|
el.hidden = showFor != mode && showFor != "all";
|
|
|
|
|
|
|
|
|
|
el = el.nextSibling;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
_refetchTabs: function(force) {
|
|
|
|
|
if (!force) {
|
|
|
|
|
// Don't bother refetching tabs if we already did so recently
|
|
|
|
|
let lastFetch = 0;
|
|
|
|
|
try {
|
|
|
|
|
lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch");
|
|
|
|
|
}
|
|
|
|
|
catch (e) { /* Just use the default value of 0 */ }
|
|
|
|
|
let now = Math.floor(Date.now() / 1000);
|
|
|
|
|
if (now - lastFetch < 30)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if Clients hasn't synced yet this session, need to sync it as well
|
|
|
|
|
if (Weave.Clients.lastSync == 0)
|
|
|
|
|
Weave.Clients.sync();
|
|
|
|
|
|
|
|
|
|
// Force a sync only for the tabs engine
|
|
|
|
|
let engine = Weave.Engines.get("tabs");
|
|
|
|
|
engine.lastModified = null;
|
|
|
|
|
engine.sync();
|
|
|
|
|
Services.prefs.setIntPref("services.sync.lastTabFetch",
|
|
|
|
|
Math.floor(Date.now() / 1000));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
observe: function(subject, topic, data) {
|
|
|
|
|
switch (topic) {
|
|
|
|
|
case "weave:service:login:finish":
|
|
|
|
|
this.buildList(true);
|
|
|
|
|
break;
|
|
|
|
|
case "weave:engine:sync:finish":
|
|
|
|
|
if (subject == "tabs")
|
|
|
|
|
this._generateTabList();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleClick: function(event) {
|
|
|
|
|
if (event.target.getAttribute("type") != "tab")
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (event.button == 1) {
|
|
|
|
|
let url = event.target.getAttribute("url");
|
|
|
|
|
openUILink(url, event);
|
|
|
|
|
let index = this._tabsList.getIndexOfItem(event.target);
|
|
|
|
|
this._tabsList.removeItemAt(index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|