mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-01-16 01:31:37 +00:00
121 lines
3.6 KiB
JavaScript
121 lines
3.6 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* Provides functions to handle remote tabs (ie, tabs known by Sync) in
|
|
* the awesomebar.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
this.EXPORTED_SYMBOLS = ["PlacesRemoteTabsAutocompleteProvider"];
|
|
|
|
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://services-sync/main.js");
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "weaveXPCService", function() {
|
|
return Cc["@mozilla.org/weave/service;1"]
|
|
.getService(Ci.nsISupports)
|
|
.wrappedJSObject;
|
|
});
|
|
|
|
// from MDN...
|
|
function escapeRegExp(string) {
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|
|
|
|
// Build the in-memory structure we use.
|
|
function buildItems() {
|
|
let clients = new Map(); // keyed by client guid, value is client
|
|
let tabs = new Map(); // keyed by string URL, value is {clientId, tab}
|
|
|
|
// If Sync isn't initialized (either due to lag at startup or due to no user
|
|
// being signed in), don't reach in to Weave.Service as that may initialize
|
|
// Sync unnecessarily - we'll get an observer notification later when it
|
|
// becomes ready and has synced a list of tabs.
|
|
if (weaveXPCService.ready) {
|
|
let engine = Weave.Service.engineManager.get("tabs");
|
|
|
|
for (let [guid, client] in Iterator(engine.getAllClients())) {
|
|
clients.set(guid, client);
|
|
for (let tab of client.tabs) {
|
|
let url = tab.urlHistory[0];
|
|
tabs.set(url, { clientId: guid, tab });
|
|
}
|
|
}
|
|
}
|
|
return { clients, tabs };
|
|
}
|
|
|
|
// Manage the cache of the items we use.
|
|
// The cache itself.
|
|
let _items = null;
|
|
|
|
// Ensure the cache is good.
|
|
function ensureItems() {
|
|
if (!_items) {
|
|
_items = buildItems();
|
|
}
|
|
return _items;
|
|
}
|
|
|
|
// An observer to invalidate _items.
|
|
function observe(subject, topic, data) {
|
|
switch (topic) {
|
|
case "weave:engine:sync:finish":
|
|
if (data == "tabs") {
|
|
// The tabs engine just finished syncing, so may have a different list
|
|
// of tabs then we previously cached.
|
|
_items = null;
|
|
}
|
|
break;
|
|
|
|
case "weave:service:start-over":
|
|
// Sync is being reset due to the user disconnecting - we must invalidate
|
|
// the cache so we don't supply tabs from a different user.
|
|
_items = null;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Services.obs.addObserver(observe, "weave:engine:sync:finish", false);
|
|
Services.obs.addObserver(observe, "weave:service:start-over", false);
|
|
|
|
// This public object is a static singleton.
|
|
this.PlacesRemoteTabsAutocompleteProvider = {
|
|
// a promise that resolves with an array of matching remote tabs.
|
|
getMatches(searchString) {
|
|
// If Sync isn't configured we bail early.
|
|
if (!Services.prefs.prefHasUserValue("services.sync.username")) {
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
let re = new RegExp(escapeRegExp(searchString), "i");
|
|
let matches = [];
|
|
let { tabs, clients } = ensureItems();
|
|
for (let [url, { clientId, tab }] of tabs) {
|
|
let title = tab.title;
|
|
if (url.match(re) || (title && title.match(re))) {
|
|
// lookup the client record.
|
|
let client = clients.get(clientId);
|
|
// create the record we return for auto-complete.
|
|
let record = {
|
|
url, title,
|
|
icon: tab.icon,
|
|
deviceClass: Weave.Service.clientsEngine.isMobile(clientId) ? "mobile" : "desktop",
|
|
deviceName: client.clientName,
|
|
};
|
|
matches.push(record);
|
|
}
|
|
}
|
|
return Promise.resolve(matches);
|
|
},
|
|
}
|