mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
652 lines
22 KiB
JavaScript
652 lines
22 KiB
JavaScript
/* ***** 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 TPS.
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Jonathan Griffin <jgriffin@mozilla.com>
|
|
* Philipp von Weitershausen <philipp@weitershausen.de>
|
|
*
|
|
* 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 ***** */
|
|
|
|
/* This is a JavaScript module (JSM) to be imported via
|
|
* Components.utils.import() and acts as a singleton. Only the following
|
|
* listed symbols will exposed on import, and only when and where imported.
|
|
*/
|
|
|
|
var EXPORTED_SYMBOLS = ["TPS"];
|
|
|
|
const CC = Components.classes;
|
|
const CI = Components.interfaces;
|
|
const CU = Components.utils;
|
|
|
|
CU.import("resource://services-sync/service.js");
|
|
CU.import("resource://services-sync/constants.js");
|
|
CU.import("resource://services-sync/util.js");
|
|
CU.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
CU.import("resource://gre/modules/Services.jsm");
|
|
CU.import("resource://tps/bookmarks.jsm");
|
|
CU.import("resource://tps/logger.jsm");
|
|
CU.import("resource://tps/passwords.jsm");
|
|
CU.import("resource://tps/history.jsm");
|
|
CU.import("resource://tps/forms.jsm");
|
|
CU.import("resource://tps/prefs.jsm");
|
|
CU.import("resource://tps/tabs.jsm");
|
|
|
|
const ACTION_ADD = "add";
|
|
const ACTION_VERIFY = "verify";
|
|
const ACTION_VERIFY_NOT = "verify-not";
|
|
const ACTION_MODIFY = "modify";
|
|
const ACTION_SYNC = "sync";
|
|
const ACTION_DELETE = "delete";
|
|
const ACTION_PRIVATE_BROWSING = "private-browsing";
|
|
const ACTION_WIPE_SERVER = "wipe-server";
|
|
const ACTIONS = [ACTION_ADD, ACTION_VERIFY, ACTION_VERIFY_NOT,
|
|
ACTION_MODIFY, ACTION_SYNC, ACTION_DELETE,
|
|
ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER];
|
|
|
|
const SYNC_WIPE_SERVER = "wipe-server";
|
|
const SYNC_RESET_CLIENT = "reset-client";
|
|
const SYNC_WIPE_CLIENT = "wipe-client";
|
|
|
|
function GetFileAsText(file)
|
|
{
|
|
let channel = Services.io.newChannel(file, null, null);
|
|
let inputStream = channel.open();
|
|
if (channel instanceof CI.nsIHttpChannel &&
|
|
channel.responseStatus != 200) {
|
|
return "";
|
|
}
|
|
|
|
let streamBuf = "";
|
|
let sis = CC["@mozilla.org/scriptableinputstream;1"]
|
|
.createInstance(CI.nsIScriptableInputStream);
|
|
sis.init(inputStream);
|
|
|
|
let available;
|
|
while ((available = sis.available()) != 0) {
|
|
streamBuf += sis.read(available);
|
|
}
|
|
|
|
inputStream.close();
|
|
return streamBuf;
|
|
}
|
|
|
|
var TPS =
|
|
{
|
|
_waitingForSync: false,
|
|
_test: null,
|
|
_currentAction: -1,
|
|
_currentPhase: -1,
|
|
_errors: 0,
|
|
_syncErrors: 0,
|
|
_usSinceEpoch: 0,
|
|
_tabsAdded: 0,
|
|
_tabsFinished: 0,
|
|
_phaselist: {},
|
|
_operations_pending: 0,
|
|
|
|
DumpError: function (msg) {
|
|
this._errors++;
|
|
Logger.logError("[phase" + this._currentPhase + "] " + msg);
|
|
this.quit();
|
|
},
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([CI.nsIObserver,
|
|
CI.nsISupportsWeakReference]),
|
|
|
|
observe: function TPS__observe(subject, topic, data) {
|
|
try {
|
|
Logger.logInfo("----------event observed: " + topic);
|
|
switch(topic) {
|
|
case "private-browsing":
|
|
Logger.logInfo("private browsing " + data);
|
|
break;
|
|
case "weave:service:sync:error":
|
|
if (this._waitingForSync && this._syncErrors == 0) {
|
|
// if this is the first sync error, retry...
|
|
Logger.logInfo("sync error; retrying...");
|
|
this._syncErrors++;
|
|
this._waitingForSync = false;
|
|
Weave.Service.logout();
|
|
Utils.nextTick(this.RunNextTestAction, this);
|
|
}
|
|
else {
|
|
// ...otherwise abort the test
|
|
this.DumpError("sync error; aborting test");
|
|
return;
|
|
}
|
|
break;
|
|
case "weave:service:sync:finish":
|
|
if (this._waitingForSync) {
|
|
this._syncErrors = 0;
|
|
this._waitingForSync = false;
|
|
// Wait a second before continuing, otherwise we can get
|
|
// 'sync not complete' errors.
|
|
Utils.namedTimer(function() {
|
|
Weave.Service.logout();
|
|
this.FinishAsyncOperation();
|
|
}, 1000, this, "postsync");
|
|
}
|
|
break;
|
|
case "sessionstore-windows-restored":
|
|
Utils.nextTick(this.RunNextTestAction, this);
|
|
break;
|
|
}
|
|
}
|
|
catch(e) {
|
|
this.DumpError("Exception caught: " + e);
|
|
return;
|
|
}
|
|
},
|
|
|
|
StartAsyncOperation: function TPS__StartAsyncOperation() {
|
|
this._operations_pending++;
|
|
},
|
|
|
|
FinishAsyncOperation: function TPS__FinishAsyncOperation() {
|
|
this._operations_pending--;
|
|
if (!this.operations_pending) {
|
|
this._currentAction++;
|
|
Utils.nextTick(function() {
|
|
this.RunNextTestAction();
|
|
}, this);
|
|
}
|
|
},
|
|
|
|
quit: function () {
|
|
Logger.close();
|
|
this.goQuitApplication();
|
|
},
|
|
|
|
HandleTabs: function (tabs, action) {
|
|
this._tabsAdded = tabs.length;
|
|
this._tabsFinished = 0;
|
|
for each (let tab in tabs) {
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on tab " + JSON.stringify(tab));
|
|
switch(action) {
|
|
case ACTION_ADD:
|
|
// When adding tabs, we keep track of how many tabs we're adding,
|
|
// and wait until we've received that many onload events from our
|
|
// new tabs before continuing
|
|
let that = this;
|
|
let taburi = tab.uri;
|
|
BrowserTabs.Add(tab.uri, function() {
|
|
that._tabsFinished++;
|
|
Logger.logInfo("tab for " + taburi + " finished loading");
|
|
if (that._tabsFinished == that._tabsAdded) {
|
|
Logger.logInfo("all tabs loaded, continuing...");
|
|
that.FinishAsyncOperation();
|
|
}
|
|
});
|
|
break;
|
|
case ACTION_VERIFY:
|
|
Logger.AssertTrue(typeof(tab.profile) != "undefined",
|
|
"profile must be defined when verifying tabs");
|
|
Logger.AssertTrue(
|
|
BrowserTabs.Find(tab.uri, tab.title, tab.profile), "error locating tab");
|
|
break;
|
|
case ACTION_VERIFY_NOT:
|
|
Logger.AssertTrue(typeof(tab.profile) != "undefined",
|
|
"profile must be defined when verifying tabs");
|
|
Logger.AssertTrue(
|
|
!BrowserTabs.Find(tab.uri, tab.title, tab.profile),
|
|
"tab found which was expected to be absent");
|
|
break;
|
|
default:
|
|
Logger.AssertTrue(false, "invalid action: " + action);
|
|
}
|
|
}
|
|
Logger.logPass("executing action " + action.toUpperCase() + " on tabs");
|
|
},
|
|
|
|
HandlePrefs: function (prefs, action) {
|
|
for each (pref in prefs) {
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on pref " + JSON.stringify(pref));
|
|
let preference = new Preference(pref);
|
|
switch(action) {
|
|
case ACTION_MODIFY:
|
|
preference.Modify();
|
|
break;
|
|
case ACTION_VERIFY:
|
|
preference.Find();
|
|
break;
|
|
default:
|
|
Logger.AssertTrue(false, "invalid action: " + action);
|
|
}
|
|
}
|
|
Logger.logPass("executing action " + action.toUpperCase() + " on pref");
|
|
},
|
|
|
|
HandleForms: function (data, action) {
|
|
for each (datum in data) {
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on form entry " + JSON.stringify(datum));
|
|
let formdata = new FormData(datum, this._usSinceEpoch);
|
|
switch(action) {
|
|
case ACTION_ADD:
|
|
formdata.Create();
|
|
break;
|
|
case ACTION_DELETE:
|
|
formdata.Remove();
|
|
break;
|
|
case ACTION_VERIFY:
|
|
Logger.AssertTrue(formdata.Find(), "form data not found");
|
|
break;
|
|
case ACTION_VERIFY_NOT:
|
|
Logger.AssertTrue(!formdata.Find(),
|
|
"form data found, but it shouldn't be present");
|
|
break;
|
|
default:
|
|
Logger.AssertTrue(false, "invalid action: " + action);
|
|
}
|
|
}
|
|
Logger.logPass("executing action " + action.toUpperCase() +
|
|
" on formdata");
|
|
},
|
|
|
|
HandleHistory: function (entries, action) {
|
|
for each (entry in entries) {
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on history entry " + JSON.stringify(entry));
|
|
switch(action) {
|
|
case ACTION_ADD:
|
|
HistoryEntry.Add(entry, this._usSinceEpoch);
|
|
break;
|
|
case ACTION_DELETE:
|
|
HistoryEntry.Delete(entry, this._usSinceEpoch);
|
|
break;
|
|
case ACTION_VERIFY:
|
|
Logger.AssertTrue(HistoryEntry.Find(entry, this._usSinceEpoch),
|
|
"Uri visits not found in history database");
|
|
break;
|
|
case ACTION_VERIFY_NOT:
|
|
Logger.AssertTrue(!HistoryEntry.Find(entry, this._usSinceEpoch),
|
|
"Uri visits found in history database, but they shouldn't be");
|
|
break;
|
|
default:
|
|
Logger.AssertTrue(false, "invalid action: " + action);
|
|
}
|
|
}
|
|
Logger.logPass("executing action " + action.toUpperCase() +
|
|
" on history");
|
|
},
|
|
|
|
HandlePasswords: function (passwords, action) {
|
|
for each (password in passwords) {
|
|
let password_id = -1;
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on password " + JSON.stringify(password));
|
|
var password = new Password(password);
|
|
switch (action) {
|
|
case ACTION_ADD:
|
|
Logger.AssertTrue(password.Create() > -1, "error adding password");
|
|
break;
|
|
case ACTION_VERIFY:
|
|
Logger.AssertTrue(password.Find() != -1, "password not found");
|
|
break;
|
|
case ACTION_VERIFY_NOT:
|
|
Logger.AssertTrue(password.Find() == -1,
|
|
"password found, but it shouldn't exist");
|
|
break;
|
|
case ACTION_DELETE:
|
|
Logger.AssertTrue(password.Find() != -1, "password not found");
|
|
password.Remove();
|
|
break;
|
|
case ACTION_MODIFY:
|
|
if (password.updateProps != null) {
|
|
Logger.AssertTrue(password.Find() != -1, "password not found");
|
|
password.Update();
|
|
}
|
|
break;
|
|
default:
|
|
Logger.AssertTrue(false, "invalid action: " + action);
|
|
}
|
|
}
|
|
Logger.logPass("executing action " + action.toUpperCase() +
|
|
" on passwords");
|
|
},
|
|
|
|
HandleBookmarks: function (bookmarks, action) {
|
|
let items = [];
|
|
for (folder in bookmarks) {
|
|
let last_item_pos = -1;
|
|
for each (bookmark in bookmarks[folder]) {
|
|
Logger.clearPotentialError();
|
|
let placesItem;
|
|
bookmark['location'] = folder;
|
|
if (last_item_pos != -1)
|
|
bookmark['last_item_pos'] = last_item_pos;
|
|
let item_id = -1;
|
|
if (action != ACTION_MODIFY && action != ACTION_DELETE)
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on bookmark " + JSON.stringify(bookmark));
|
|
if ("uri" in bookmark)
|
|
placesItem = new Bookmark(bookmark);
|
|
else if ("folder" in bookmark)
|
|
placesItem = new BookmarkFolder(bookmark);
|
|
else if ("livemark" in bookmark)
|
|
placesItem = new Livemark(bookmark);
|
|
else if ("separator" in bookmark)
|
|
placesItem = new Separator(bookmark);
|
|
if (action == ACTION_ADD) {
|
|
item_id = placesItem.Create();
|
|
}
|
|
else {
|
|
item_id = placesItem.Find();
|
|
if (action == ACTION_VERIFY_NOT) {
|
|
Logger.AssertTrue(item_id == -1,
|
|
"places item exists but it shouldn't: " +
|
|
JSON.stringify(bookmark));
|
|
}
|
|
else
|
|
Logger.AssertTrue(item_id != -1, "places item not found", true);
|
|
}
|
|
|
|
last_item_pos = placesItem.GetItemIndex();
|
|
items.push(placesItem);
|
|
}
|
|
}
|
|
|
|
if (action == ACTION_DELETE || action == ACTION_MODIFY) {
|
|
for each (item in items) {
|
|
Logger.logInfo("executing action " + action.toUpperCase() +
|
|
" on bookmark " + JSON.stringify(item));
|
|
switch(action) {
|
|
case ACTION_DELETE:
|
|
item.Remove();
|
|
break;
|
|
case ACTION_MODIFY:
|
|
if (item.updateProps != null)
|
|
item.Update();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Logger.logPass("executing action " + action.toUpperCase() +
|
|
" on bookmarks");
|
|
},
|
|
|
|
RunNextTestAction: function() {
|
|
try {
|
|
if (this._currentAction >=
|
|
this._phaselist["phase" + this._currentPhase].length) {
|
|
// we're all done
|
|
Logger.logInfo("test phase " + this._currentPhase + ": " +
|
|
(this._errors ? "FAIL" : "PASS"));
|
|
this.quit();
|
|
return;
|
|
}
|
|
|
|
if (this.seconds_since_epoch)
|
|
this._usSinceEpoch = this.seconds_since_epoch * 1000 * 1000;
|
|
else {
|
|
this.DumpError("seconds-since-epoch not set");
|
|
return;
|
|
}
|
|
|
|
let phase = this._phaselist["phase" + this._currentPhase];
|
|
let action = phase[this._currentAction];
|
|
Logger.logInfo("starting action: " + JSON.stringify(action));
|
|
action[0].call(this, action[1]);
|
|
|
|
// if we're in an async operation, don't continue on to the next action
|
|
if (this._operations_pending)
|
|
return;
|
|
|
|
this._currentAction++;
|
|
}
|
|
catch(e) {
|
|
this.DumpError("Exception caught: " + e);
|
|
return;
|
|
}
|
|
this.RunNextTestAction();
|
|
},
|
|
|
|
RunTestPhase: function (file, phase, logpath) {
|
|
try {
|
|
Logger.init(logpath);
|
|
Logger.logInfo("Weave version: " + WEAVE_VERSION);
|
|
Logger.logInfo("Firefox builddate: " + Services.appinfo.appBuildID);
|
|
Logger.logInfo("Firefox version: " + Services.appinfo.version);
|
|
|
|
// do some weave housekeeping
|
|
if (Weave.Service.isLoggedIn) {
|
|
this.DumpError("Weave logged in on startup...profile may be dirty");
|
|
return;
|
|
}
|
|
|
|
// setup observers
|
|
Services.obs.addObserver(this, "weave:service:sync:finish", true);
|
|
Services.obs.addObserver(this, "weave:service:sync:error", true);
|
|
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
|
Services.obs.addObserver(this, "private-browsing", true);
|
|
|
|
// parse the test file
|
|
Services.scriptloader.loadSubScript(file, this);
|
|
this._currentPhase = phase;
|
|
let this_phase = this._phaselist["phase" + this._currentPhase];
|
|
|
|
if (this_phase == undefined) {
|
|
this.DumpError("invalid phase " + this._currentPhase);
|
|
return;
|
|
}
|
|
|
|
if (this.phases["phase" + this._currentPhase] == undefined) {
|
|
this.DumpError("no profile defined for phase " + this._currentPhase);
|
|
return;
|
|
}
|
|
Logger.logInfo("setting client.name to " + this.phases["phase" + this._currentPhase]);
|
|
Weave.Svc.Prefs.set("client.name", this.phases["phase" + this._currentPhase]);
|
|
|
|
// wipe the server at the end of the final test phase
|
|
if (this.phases["phase" + (parseInt(this._currentPhase) + 1)] == undefined)
|
|
this_phase.push([this.WipeServer]);
|
|
|
|
// start processing the test actions
|
|
this._currentAction = 0;
|
|
}
|
|
catch(e) {
|
|
this.DumpError("Exception caught: " + e);
|
|
return;
|
|
}
|
|
},
|
|
|
|
Phase: function Test__Phase(phasename, fnlist) {
|
|
this._phaselist[phasename] = fnlist;
|
|
},
|
|
|
|
SetPrivateBrowsing: function TPS__SetPrivateBrowsing(options) {
|
|
let PBSvc = CC["@mozilla.org/privatebrowsing;1"].
|
|
getService(CI.nsIPrivateBrowsingService);
|
|
PBSvc.privateBrowsingEnabled = options;
|
|
Logger.logInfo("set privateBrowsingEnabled: " + options);
|
|
},
|
|
|
|
Sync: function TPS__Sync(options) {
|
|
Logger.logInfo("executing Sync " + (options ? options : ""));
|
|
if (options == SYNC_WIPE_SERVER) {
|
|
Weave.Svc.Prefs.set("firstSync", "wipeRemote");
|
|
}
|
|
else if (options == SYNC_WIPE_CLIENT) {
|
|
Weave.Svc.Prefs.set("firstSync", "wipeClient");
|
|
}
|
|
else if (options == SYNC_RESET_CLIENT) {
|
|
Weave.Svc.Prefs.set("firstSync", "resetClient");
|
|
}
|
|
else {
|
|
Weave.Svc.Prefs.reset("firstSync");
|
|
}
|
|
if (this.config.account) {
|
|
let account = this.config.account;
|
|
if (account["serverURL"]) {
|
|
Weave.Service.serverURL = account["serverURL"];
|
|
}
|
|
if (account["admin-secret"]) {
|
|
// if admin-secret is specified, we'll dynamically create
|
|
// a new sync account
|
|
Weave.Svc.Prefs.set("admin-secret", account["admin-secret"]);
|
|
let suffix = account["account-suffix"];
|
|
Weave.Service.account = "tps" + suffix + "@mozilla.com";
|
|
Weave.Service.password = "tps" + suffix + "tps" + suffix;
|
|
Weave.Service.passphrase = Weave.Utils.generatePassphrase();
|
|
Weave.Service.createAccount(Weave.Service.account,
|
|
Weave.Service.password,
|
|
"dummy1", "dummy2");
|
|
Weave.Service.login();
|
|
}
|
|
else if (account["username"] && account["password"] &&
|
|
account["passphrase"]) {
|
|
Weave.Service.account = account["username"];
|
|
Weave.Service.password = account["password"];
|
|
Weave.Service.passphrase = account["passphrase"];
|
|
Weave.Service.login();
|
|
}
|
|
else {
|
|
this.DumpError("Must specify admin-secret, or " +
|
|
"username/password/passphrase in the config file");
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
this.DumpError("No account information found; did you use " +
|
|
"a valid config file?");
|
|
return;
|
|
}
|
|
Logger.AssertEqual(Weave.Status.service, Weave.STATUS_OK, "Weave status not OK");
|
|
Weave.Svc.Obs.notify("weave:service:setup-complete");
|
|
this._waitingForSync = true;
|
|
this.StartAsyncOperation();
|
|
Weave.Service.sync();
|
|
},
|
|
|
|
WipeServer: function TPS__WipeServer() {
|
|
Logger.logInfo("WipeServer()");
|
|
Weave.Service.login();
|
|
Weave.Service.wipeServer();
|
|
Logger.AssertEqual(Weave.Status.service, Weave.STATUS_OK, "Weave status not OK");
|
|
this._waitingForSync = true;
|
|
this.StartAsyncOperation();
|
|
Weave.Service.sync();
|
|
return;
|
|
},
|
|
};
|
|
|
|
var Bookmarks = {
|
|
add: function Bookmarks__add(bookmarks) {
|
|
TPS.HandleBookmarks(bookmarks, ACTION_ADD);
|
|
},
|
|
modify: function Bookmarks__modify(bookmarks) {
|
|
TPS.HandleBookmarks(bookmarks, ACTION_MODIFY);
|
|
},
|
|
delete: function Bookmarks__delete(bookmarks) {
|
|
TPS.HandleBookmarks(bookmarks, ACTION_DELETE);
|
|
},
|
|
verify: function Bookmarks__verify(bookmarks) {
|
|
TPS.HandleBookmarks(bookmarks, ACTION_VERIFY);
|
|
},
|
|
verifyNot: function Bookmarks__verifyNot(bookmarks) {
|
|
TPS.HandleBookmarks(bookmarks, ACTION_VERIFY_NOT);
|
|
}
|
|
};
|
|
|
|
var Formdata = {
|
|
add: function Formdata__add(formdata) {
|
|
this.HandleForms(formdata, ACTION_ADD);
|
|
},
|
|
delete: function Formdata__delete(formdata) {
|
|
this.HandleForms(formdata, ACTION_DELETE);
|
|
},
|
|
verify: function Formdata__verify(formdata) {
|
|
this.HandleForms(formdata, ACTION_VERIFY);
|
|
},
|
|
verifyNot: function Formdata__verifyNot(formdata) {
|
|
this.HandleForms(formdata, ACTION_VERIFY_NOT);
|
|
}
|
|
};
|
|
|
|
var History = {
|
|
add: function History__add(history) {
|
|
this.HandleHistory(history, ACTION_ADD);
|
|
},
|
|
delete: function History__delete(history) {
|
|
this.HandleHistory(history, ACTION_DELETE);
|
|
},
|
|
verify: function History__verify(history) {
|
|
this.HandleHistory(history, ACTION_VERIFY);
|
|
},
|
|
verifyNot: function History__verifyNot(history) {
|
|
this.HandleHistory(history, ACTION_VERIFY_NOT);
|
|
}
|
|
};
|
|
|
|
var Passwords = {
|
|
add: function Passwords__add(passwords) {
|
|
this.HandlePasswords(passwords, ACTION_ADD);
|
|
},
|
|
modify: function Passwords__modify(passwords) {
|
|
this.HandlePasswords(passwords, ACTION_MODIFY);
|
|
},
|
|
delete: function Passwords__delete(passwords) {
|
|
this.HandlePasswords(passwords, ACTION_DELETE);
|
|
},
|
|
verify: function Passwords__verify(passwords) {
|
|
this.HandlePasswords(passwords, ACTION_VERIFY);
|
|
},
|
|
verifyNot: function Passwords__verifyNot(passwords) {
|
|
this.HandlePasswords(passwords, ACTION_VERIFY_NOT);
|
|
}
|
|
};
|
|
|
|
var Prefs = {
|
|
modify: function Prefs__modify(prefs) {
|
|
TPS.HandlePrefs(prefs, ACTION_MODIFY);
|
|
},
|
|
verify: function Prefs__verify(prefs) {
|
|
TPS.HandlePrefs(prefs, ACTION_VERIFY);
|
|
}
|
|
};
|
|
|
|
var Tabs = {
|
|
add: function Tabs__add(tabs) {
|
|
TPS.StartAsyncOperation();
|
|
TPS.HandleTabs(tabs, ACTION_ADD);
|
|
},
|
|
verify: function Tabs__verify(tabs) {
|
|
TPS.HandleTabs(tabs, ACTION_VERIFY);
|
|
},
|
|
verifyNot: function Tabs__verifyNot(tabs) {
|
|
TPS.HandleTabs(tabs, ACTION_VERIFY_NOT);
|
|
}
|
|
};
|
|
|