mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1261009 - Remove the Data Store API, r=fabrice (b22e580107) - Bug 1268393 - Some compilation issues in ServiceWorker code, r=ehsan (d9c2f2554b) - Bug 1209095 - Accept opaqueredirection fetch results if the request redirection type is manual. r=bkelly (6fe92d1368) - Bug 1267733 P2 Pass ServiceWorkerRegistrationInfo down to CancelChannelRunnable. r=jdm (0ec51f09ef) - Bug 1267733 P3 Trigger service worker update after failed interception. r=jdm (f89a7998d4) - Bug 1267733 P4 Add a wpt test that verifies a service worker update can recover from a broken navigation interception. r=jdm (9dc0ce97bd) - Bug 1267691: Assert on failed attempts to shutdown a thread from itself r=froyd (0cbd1e458c) - Bug 1180533 - Disable BackgroundHangMonitor on gonk (a2d666e741) - Bug 1121216 - disable BackgroundHangMonitor for TSan builds; r=jchen (ef15d1016f) - Bug 1265621 - Use StaticRefPtr in Omnijar.cpp; r=froydnj (81bc32836e) - Bug 1265621 - Expose outer zip readers in Omnijar::GetReader; r=froydnj (ce3f82929e) - Bug 1267021 - Use fallible allocation and move semantics for Push events. r=wchen (3a1ae23d8d) - Bug 1222899 - Handle geolocation-device-events callback. r=kchen (a33bcf4297) - Bug 1237831 - Update GonkGPSGeolocationProvider.cpp to use B2G-style. r=jst (d389eedf47) - Bug 1245033 - Build break in dom/system/gonk/GonkGPSGeolocationProvider.cpp:541:126: error: format '%d' expects argument of type 'int', but argument 5 has type 'nsresult'. r=fabrice (ecde789edf) - Bug 1264287: Convert Wifi to use |UniquePtr|, r=nfroyd (9bad7792bf) - Bug 1267577 - Move nsRunnable to mozilla::Runnable. r=gsvelto (f58e2161f2) - Bug 1210370 - Close wpa_supplicant before we shutdown nsIWifiProxyService. r=mrbkap (5cd4dce58f) - Bug 1218629 - Save audio volume for each device to setting db r=alwu (2f1847dd6f) - Bug 1249437 - Remove workaround of volume control r=alwu (13cd144a89) - Bug 1268432: Replace |Task| with |Runnable| in B2G code r=fabrice (bcc768e9cb) - Bug 1226483 - Add ASSERT check to AudioManager::SelectDeviceFromDevices() r=alwu (446e8f634e) - Bug 1229234 - Enable audio_is_output_device() on ICS r=alwu (84aae07f23) - Bug 1267369 - Only generate typelib data for scriptable interfaces; r=khuey (e49b44c9ce) - Bug 1155969 - Make runtests.py flake8 compliant. r=ted (1de456b206) - Bug 1266569 - Avoid including the ChromeUtils binding in Base64.h. r=froydnj (7ba39a7687)
This commit is contained in:
@@ -910,13 +910,6 @@ pref("network.sntp.pools", // Servers separated by ';'.
|
||||
pref("network.sntp.port", 123);
|
||||
pref("network.sntp.timeout", 30); // In seconds.
|
||||
|
||||
// Enable dataStore
|
||||
pref("dom.datastore.enabled", true);
|
||||
// When an entry is changed, use two timers to fire system messages in a more
|
||||
// moderate pattern.
|
||||
pref("dom.datastore.sysMsgOnChangeShortTimeoutSec", 10);
|
||||
pref("dom.datastore.sysMsgOnChangeLongTimeoutSec", 60);
|
||||
|
||||
// DOM Inter-App Communication API.
|
||||
pref("dom.inter-app-communication-api.enabled", true);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
window.performance.mark('gecko-shell-loadstart');
|
||||
|
||||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/DataStoreChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
||||
Cu.import('resource://gre/modules/NotificationDB.jsm');
|
||||
@@ -1064,22 +1063,49 @@ window.addEventListener('ContentStart', function update_onContentStart() {
|
||||
updatePrompt.wrappedJSObject.handleContentStart(shell);
|
||||
#endif
|
||||
});
|
||||
/* The "GPSChipOn" is to indicate that GPS engine is turned ON by the modem.
|
||||
During this GPS engine is turned ON by the modem, we make the location tracking icon visible to user.
|
||||
Once GPS engine is turned OFF, the location icon will disappear.
|
||||
If GPS engine is not turned ON by the modem or GPS location service is triggered,
|
||||
we let GPS service take over the control of showing the location tracking icon.
|
||||
The regular sequence of the geolocation-device-events is: starting-> GPSStarting-> shutdown-> GPSShutdown
|
||||
*/
|
||||
|
||||
(function geolocationStatusTracker() {
|
||||
let gGeolocationActive = false;
|
||||
let GPSChipOn = false;
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
let oldState = gGeolocationActive;
|
||||
if (aData == "starting") {
|
||||
gGeolocationActive = true;
|
||||
} else if (aData == "shutdown") {
|
||||
gGeolocationActive = false;
|
||||
let promptWarning = false;
|
||||
switch (aData) {
|
||||
case "GPSStarting":
|
||||
if (!gGeolocationActive) {
|
||||
gGeolocationActive = true;
|
||||
GPSChipOn = true;
|
||||
promptWarning = true;
|
||||
}
|
||||
break;
|
||||
case "GPSShutdown":
|
||||
if (GPSChipOn) {
|
||||
gGeolocationActive = false;
|
||||
GPSChipOn = false;
|
||||
}
|
||||
break;
|
||||
case "starting":
|
||||
gGeolocationActive = true;
|
||||
GPSChipOn = false;
|
||||
break;
|
||||
case "shutdown":
|
||||
gGeolocationActive = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gGeolocationActive != oldState) {
|
||||
shell.sendChromeEvent({
|
||||
type: 'geolocation-status',
|
||||
active: gGeolocationActive
|
||||
active: gGeolocationActive,
|
||||
prompt: promptWarning
|
||||
});
|
||||
}
|
||||
}, "geolocation-device-events", false);
|
||||
|
||||
@@ -938,10 +938,6 @@ bin/libfreebl_32int64_3.so
|
||||
@RESPATH@/components/FxAccountsUIGlue.js
|
||||
@RESPATH@/components/services_fxaccounts.xpt
|
||||
|
||||
@RESPATH@/components/DataStore.manifest
|
||||
@RESPATH@/components/DataStoreImpl.js
|
||||
@RESPATH@/components/dom_datastore.xpt
|
||||
|
||||
@RESPATH@/components/MobileIdentity.manifest
|
||||
@RESPATH@/components/MobileIdentity.js
|
||||
@RESPATH@/components/dom_mobileidentity.xpt
|
||||
|
||||
@@ -815,10 +815,6 @@ bin/libfreebl_32int64_3.so
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@RESPATH@/components/DataStore.manifest
|
||||
@RESPATH@/components/DataStoreImpl.js
|
||||
@RESPATH@/components/dom_datastore.xpt
|
||||
|
||||
@RESPATH@/components/dom_audiochannel.xpt
|
||||
|
||||
; Shutdown Terminator
|
||||
|
||||
@@ -170,10 +170,6 @@ AppsService.prototype = {
|
||||
return UserCustomizations.isFromExtension(aURI);
|
||||
},
|
||||
|
||||
updateDataStoreEntriesFromLocalId: function(aLocalId) {
|
||||
return DOMApplicationRegistry.updateDataStoreEntriesFromLocalId(aLocalId);
|
||||
},
|
||||
|
||||
classID : APPS_SERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
|
||||
}
|
||||
|
||||
@@ -419,10 +419,6 @@ this.DOMApplicationRegistry = {
|
||||
|
||||
getAppInfo: function getAppInfo(aAppId) {
|
||||
return AppsUtils.getAppInfo(this.webapps, aAppId);
|
||||
},
|
||||
|
||||
updateDataStoreEntriesFromLocalId: function(aLocalId) {
|
||||
debug("updateDataStoreEntriesFromLocalId() not yet supported on child!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,10 +149,6 @@ XPCOMUtils.defineLazyGetter(this, "interAppCommService", function() {
|
||||
.getService(Ci.nsIInterAppCommService);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
|
||||
"@mozilla.org/datastore-service;1",
|
||||
"nsIDataStoreService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
@@ -452,18 +448,6 @@ this.DOMApplicationRegistry = {
|
||||
}
|
||||
}),
|
||||
|
||||
updateDataStoreForApp: Task.async(function*(aId) {
|
||||
if (!this.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create or Update the DataStore for this app
|
||||
let results = yield this._readManifests([{ id: aId }]);
|
||||
let app = this.webapps[aId];
|
||||
this.updateDataStore(app.localId, app.origin, app.manifestURL,
|
||||
results[0].manifest, app.appStatus);
|
||||
}),
|
||||
|
||||
appKind: function(aApp, aManifest) {
|
||||
if (aApp.origin.startsWith("android://")) {
|
||||
return this.kAndroid;
|
||||
@@ -815,52 +799,10 @@ this.DOMApplicationRegistry = {
|
||||
Services.prefs.setBoolPref("dom.apps.reset-permissions", true);
|
||||
}
|
||||
|
||||
// DataStores must be initialized at startup.
|
||||
for (let id in this.webapps) {
|
||||
yield this.updateDataStoreForApp(id);
|
||||
}
|
||||
|
||||
yield this.registerAppsHandlers(runUpdate);
|
||||
}.bind(this)).then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
updateDataStore: function(aId, aOrigin, aManifestURL, aManifest) {
|
||||
if (!aManifest) {
|
||||
debug("updateDataStore: no manifest for " + aOrigin);
|
||||
return;
|
||||
}
|
||||
|
||||
let uri = Services.io.newURI(aOrigin, null, null);
|
||||
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
let principal = secMan.createCodebasePrincipal(uri, {appId: aId});
|
||||
if (!dataStoreService.checkPermission(principal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('datastores-owned' in aManifest) {
|
||||
for (let name in aManifest['datastores-owned']) {
|
||||
let readonly = "access" in aManifest['datastores-owned'][name]
|
||||
? aManifest['datastores-owned'][name].access == 'readonly'
|
||||
: false;
|
||||
|
||||
dataStoreService.installDataStore(aId, name, aOrigin, aManifestURL,
|
||||
readonly);
|
||||
}
|
||||
}
|
||||
|
||||
if ('datastores-access' in aManifest) {
|
||||
for (let name in aManifest['datastores-access']) {
|
||||
let readonly = ("readonly" in aManifest['datastores-access'][name]) &&
|
||||
!aManifest['datastores-access'][name].readonly
|
||||
? false : true;
|
||||
|
||||
dataStoreService.installAccessDataStore(aId, name, aOrigin,
|
||||
aManifestURL, readonly);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// |aEntryPoint| is either the entry_point name or the null in which case we
|
||||
// use the root of the manifest.
|
||||
//
|
||||
@@ -1927,8 +1869,6 @@ this.DOMApplicationRegistry = {
|
||||
kind: app.kind },
|
||||
true);
|
||||
}
|
||||
this.updateDataStore(this.webapps[id].localId, app.origin,
|
||||
app.manifestURL, newManifest);
|
||||
MessageBroadcaster.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
manifest: newManifest,
|
||||
@@ -2373,9 +2313,6 @@ this.DOMApplicationRegistry = {
|
||||
}, true);
|
||||
}
|
||||
|
||||
this.updateDataStore(this.webapps[aId].localId, aApp.origin,
|
||||
aApp.manifestURL, aApp.manifest);
|
||||
|
||||
aApp.name = aNewManifest.name;
|
||||
aApp.csp = manifest.csp || "";
|
||||
aApp.updateTime = Date.now();
|
||||
@@ -3015,9 +2952,6 @@ this.DOMApplicationRegistry = {
|
||||
this.doUninstall.bind(this, aData, aData.mm)
|
||||
);
|
||||
}
|
||||
|
||||
this.updateDataStore(this.webapps[id].localId, this.webapps[id].origin,
|
||||
this.webapps[id].manifestURL, jsonManifest);
|
||||
}
|
||||
|
||||
for (let prop of ["installState", "downloadAvailable", "downloading",
|
||||
@@ -3162,9 +3096,6 @@ this.DOMApplicationRegistry = {
|
||||
}, true);
|
||||
}
|
||||
|
||||
this.updateDataStore(this.webapps[aId].localId, aNewApp.origin,
|
||||
aNewApp.manifestURL, aManifest);
|
||||
|
||||
if (aInstallSuccessCallback) {
|
||||
try {
|
||||
yield aInstallSuccessCallback(aNewApp, aManifest, zipFile.path);
|
||||
@@ -4676,13 +4607,6 @@ this.DOMApplicationRegistry = {
|
||||
return AppsUtils.areAnyAppsInstalled(this.webapps);
|
||||
},
|
||||
|
||||
updateDataStoreEntriesFromLocalId: function(aLocalId) {
|
||||
let app = appsService.getAppByLocalId(aLocalId);
|
||||
if (app) {
|
||||
this.updateDataStoreForApp(app.id);
|
||||
}
|
||||
},
|
||||
|
||||
_isLaunchable: function(aApp) {
|
||||
return true;
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
<title>?!?</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="file_test_widget.js"></script>
|
||||
<script type="application/javascript" src="common.js"></script>
|
||||
|
||||
@@ -74,7 +74,9 @@ ThreadSafeChromeUtils::Base64URLEncode(GlobalObject& aGlobal,
|
||||
MOZ_CRASH("Uninitialized union: expected buffer or view");
|
||||
}
|
||||
|
||||
nsresult rv = mozilla::Base64URLEncode(length, data, aOptions, aResult);
|
||||
auto paddingPolicy = aOptions.mPad ? Base64URLEncodePaddingPolicy::Include :
|
||||
Base64URLEncodePaddingPolicy::Omit;
|
||||
nsresult rv = mozilla::Base64URLEncode(length, data, paddingPolicy, aResult);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aResult.Truncate();
|
||||
aRv.Throw(rv);
|
||||
@@ -88,8 +90,26 @@ ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Base64URLDecodePaddingPolicy paddingPolicy;
|
||||
switch (aOptions.mPadding) {
|
||||
case Base64URLDecodePadding::Require:
|
||||
paddingPolicy = Base64URLDecodePaddingPolicy::Require;
|
||||
break;
|
||||
|
||||
case Base64URLDecodePadding::Ignore:
|
||||
paddingPolicy = Base64URLDecodePaddingPolicy::Ignore;
|
||||
break;
|
||||
|
||||
case Base64URLDecodePadding::Reject:
|
||||
paddingPolicy = Base64URLDecodePaddingPolicy::Reject;
|
||||
break;
|
||||
|
||||
default:
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
FallibleTArray<uint8_t> data;
|
||||
nsresult rv = mozilla::Base64URLDecode(aString, aOptions, data);
|
||||
nsresult rv = mozilla::Base64URLDecode(aString, paddingPolicy, data);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
|
||||
@@ -95,7 +95,6 @@
|
||||
#endif
|
||||
|
||||
#include "nsIDOMGlobalPropertyInitializer.h"
|
||||
#include "mozilla/dom/DataStoreService.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
#include "nsScriptNameSpaceManager.h"
|
||||
@@ -1503,38 +1502,6 @@ Navigator::GetDeprecatedBattery(ErrorResult& aRv)
|
||||
return mBatteryManager;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Navigator::GetDataStores(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOwner,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aWindow || !aWindow->GetDocShell()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
|
||||
if (!service) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
aRv = service->GetDataStores(aWindow, aName, aOwner, getter_AddRefs(promise));
|
||||
|
||||
RefPtr<Promise> p = static_cast<Promise*>(promise.get());
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigator::GetDataStores(const nsAString& aName,
|
||||
const nsAString& aOwner,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return GetDataStores(mWindow, aName, aOwner, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
@@ -2294,75 +2261,6 @@ Navigator::HasUserMediaSupport(JSContext* /* unused */,
|
||||
Preferences::GetBool("media.peerconnection.enabled", false);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasDataStoreSupport(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
|
||||
return DataStoreService::CheckPermission(aPrincipal);
|
||||
}
|
||||
|
||||
// A WorkerMainThreadRunnable to synchronously dispatch the call of
|
||||
// HasDataStoreSupport() from the worker thread to the main thread.
|
||||
class HasDataStoreSupportRunnable final
|
||||
: public workers::WorkerCheckAPIExposureOnMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
bool mResult;
|
||||
|
||||
explicit HasDataStoreSupportRunnable(workers::WorkerPrivate* aWorkerPrivate)
|
||||
: workers::WorkerCheckAPIExposureOnMainThreadRunnable(aWorkerPrivate)
|
||||
, mResult(false)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() override
|
||||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
|
||||
mResult = Navigator::HasDataStoreSupport(mWorkerPrivate->GetPrincipal());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::HasDataStoreSupport(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
// If the caller is on the worker thread, dispatch this to the main thread.
|
||||
if (!NS_IsMainThread()) {
|
||||
workers::WorkerPrivate* workerPrivate =
|
||||
workers::GetWorkerPrivateFromContext(aCx);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<HasDataStoreSupportRunnable> runnable =
|
||||
new HasDataStoreSupportRunnable(workerPrivate);
|
||||
return runnable->Dispatch() && runnable->mResult;
|
||||
}
|
||||
|
||||
workers::AssertIsOnMainThread();
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx, aGlobal);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIDocument* doc = win->GetExtantDoc();
|
||||
if (!doc || !doc->NodePrincipal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasDataStoreSupport(doc->NodePrincipal());
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
/* static */
|
||||
bool
|
||||
|
||||
@@ -164,11 +164,6 @@ public:
|
||||
Promise* GetBattery(ErrorResult& aRv);
|
||||
battery::BatteryManager* GetDeprecatedBattery(ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise> GetDataStores(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOwner,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void AppName(nsAString& aAppName, bool aUsePrefOverriddenValue);
|
||||
|
||||
static nsresult GetPlatform(nsAString& aPlatform,
|
||||
@@ -186,10 +181,6 @@ public:
|
||||
// NavigatorBinding::ClearCachedUserAgentValue(this);
|
||||
void ClearUserAgentCache();
|
||||
|
||||
already_AddRefed<Promise> GetDataStores(const nsAString& aName,
|
||||
const nsAString& aOwner,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Feature Detection API
|
||||
already_AddRefed<Promise> GetFeature(const nsAString& aName,
|
||||
ErrorResult& aRv);
|
||||
@@ -326,10 +317,6 @@ public:
|
||||
static bool HasUserMediaSupport(JSContext* /* unused */,
|
||||
JSObject* /* unused */);
|
||||
|
||||
static bool HasDataStoreSupport(nsIPrincipal* aPrincipal);
|
||||
|
||||
static bool HasDataStoreSupport(JSContext* cx, JSObject* aGlobal);
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal);
|
||||
#endif
|
||||
|
||||
@@ -88,8 +88,10 @@ function testDecode(input, decoded) {
|
||||
function test_base64URLDecode() {
|
||||
throws(_ => ChromeUtils.base64URLDecode(""), /TypeError/,
|
||||
"Should require decoding options");
|
||||
throws(_ => ChromeUtils.base64URLEncode("", {}), /TypeError/,
|
||||
throws(_ => ChromeUtils.base64URLDecode("", {}), /TypeError/,
|
||||
"Decoding should require the padding option");
|
||||
throws(_ => ChromeUtils.base64URLDecode("", { padding: "chocolate" }),
|
||||
"Decoding should throw for invalid padding policy");
|
||||
|
||||
for (let {decoded, encoded} of binaryTests) {
|
||||
testDecode(encoded, decoded);
|
||||
|
||||
@@ -362,25 +362,6 @@ DOMInterfaces = {
|
||||
'nativeType': 'nsDOMDataChannel',
|
||||
},
|
||||
|
||||
'DataStore': [{
|
||||
'workers': False
|
||||
}, {
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDataStore',
|
||||
'implicitJSContext': ['name', 'owner', 'readOnly', 'get', 'remove',
|
||||
'clear', 'revisionId', 'getLength', 'sync']
|
||||
}],
|
||||
|
||||
'DataStoreCursor': [{
|
||||
'workers': False,
|
||||
'wrapperCache': False
|
||||
}, {
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDataStoreCursor',
|
||||
'wrapperCache': False,
|
||||
'implicitJSContext': ['store', 'next', 'close']
|
||||
}],
|
||||
|
||||
'DedicatedWorkerGlobalScope': {
|
||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
'workers': True,
|
||||
@@ -1611,10 +1592,6 @@ DOMInterfaces = {
|
||||
},
|
||||
},
|
||||
|
||||
'WorkerNavigator': {
|
||||
'implicitJSContext': ['getDataStores'],
|
||||
},
|
||||
|
||||
'XMLHttpRequest': [
|
||||
{
|
||||
'nativeType': 'nsXMLHttpRequest',
|
||||
|
||||
@@ -129,7 +129,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothA2dpManager::InitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -171,7 +171,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (sBtA2dpInterface) {
|
||||
BT_LOGR("Bluetooth A2DP interface is already initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP Init runnable");
|
||||
@@ -184,7 +184,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no Bluetooth interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP OnError runnable");
|
||||
@@ -197,7 +197,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP OnError runnable");
|
||||
@@ -210,7 +210,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!a2dpInterface)) {
|
||||
// If there's no A2DP interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP OnError runnable");
|
||||
@@ -329,7 +329,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothA2dpManager::DeinitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -365,7 +365,7 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (!sBtA2dpInterface) {
|
||||
BT_LOGR("Bluetooth A2DP interface has not been initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP Deinit runnable");
|
||||
@@ -378,7 +378,7 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP OnError runnable");
|
||||
@@ -391,7 +391,7 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch A2DP OnError runnable");
|
||||
|
||||
@@ -172,7 +172,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothAvrcpManager::InitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -211,7 +211,7 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (sBtAvrcpInterface) {
|
||||
BT_LOGR("Bluetooth AVRCP interface is already initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP Init runnable");
|
||||
@@ -224,7 +224,7 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no Bluetooth interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP OnError runnable");
|
||||
@@ -237,7 +237,7 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP OnError runnable");
|
||||
@@ -250,7 +250,7 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!avrcpInterface)) {
|
||||
// If there's no AVRCP interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP OnError runnable");
|
||||
@@ -350,7 +350,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothAvrcpManager::DeinitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -386,7 +386,7 @@ BluetoothAvrcpManager::DeinitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (!sBtAvrcpInterface) {
|
||||
BT_LOGR("Bluetooth AVRCP interface has not been initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP Deinit runnable");
|
||||
@@ -399,7 +399,7 @@ BluetoothAvrcpManager::DeinitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP OnError runnable");
|
||||
@@ -412,7 +412,7 @@ BluetoothAvrcpManager::DeinitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch AVRCP OnError runnable");
|
||||
@@ -434,7 +434,7 @@ BluetoothAvrcpManager::HandleShutdown()
|
||||
sBluetoothAvrcpManager = nullptr;
|
||||
}
|
||||
|
||||
class BluetoothAvrcpManager::ConnectRunnable final : public nsRunnable
|
||||
class BluetoothAvrcpManager::ConnectRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
ConnectRunnable(BluetoothAvrcpManager* aManager)
|
||||
@@ -467,7 +467,7 @@ BluetoothAvrcpManager::Connect(const BluetoothAddress& aDeviceAddress,
|
||||
NS_DispatchToMainThread(new ConnectRunnable(this));
|
||||
}
|
||||
|
||||
class BluetoothAvrcpManager::DisconnectRunnable final : public nsRunnable
|
||||
class BluetoothAvrcpManager::DisconnectRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
DisconnectRunnable(BluetoothAvrcpManager* aManager)
|
||||
|
||||
@@ -88,16 +88,17 @@ BluetoothDaemonSocketModule::ConnectCmd(const BluetoothAddress& aBdAddr,
|
||||
/* |DeleteTask| deletes a class instance on the I/O thread
|
||||
*/
|
||||
template <typename T>
|
||||
class DeleteTask final : public Task
|
||||
class DeleteTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
DeleteTask(T* aPtr)
|
||||
: mPtr(aPtr)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mPtr = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -134,7 +135,7 @@ public:
|
||||
}
|
||||
|
||||
MessageLoopForIO::current()->PostTask(
|
||||
FROM_HERE, new DeleteTask<AcceptWatcher>(this));
|
||||
MakeAndAddRef<DeleteTask<AcceptWatcher>>(this));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,8 +146,8 @@ BluetoothDaemonSocketModule::AcceptCmd(int aFd,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
/* receive Bluedroid's socket-setup messages and client fd */
|
||||
Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes));
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
MakeAndAddRef<SocketMessageWatcherTask>(new AcceptWatcher(aFd, aRes)));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -157,8 +158,8 @@ BluetoothDaemonSocketModule::CloseCmd(BluetoothSocketResultHandler* aRes)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
/* stop the watcher corresponding to |aRes| */
|
||||
Task* t = new DeleteSocketMessageWatcherTask(aRes);
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
MakeAndAddRef<DeleteSocketMessageWatcherTask>(aRes));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -273,7 +274,7 @@ public:
|
||||
}
|
||||
|
||||
MessageLoopForIO::current()->PostTask(
|
||||
FROM_HERE, new DeleteTask<ConnectWatcher>(this));
|
||||
MakeAndAddRef<DeleteTask<ConnectWatcher>>(this));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -298,8 +299,8 @@ BluetoothDaemonSocketModule::ConnectRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
}
|
||||
|
||||
/* receive Bluedroid's socket-setup messages */
|
||||
Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes));
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
MakeAndAddRef<SocketMessageWatcherTask>(new ConnectWatcher(fd, aRes)));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -465,7 +465,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothGattManager::InitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -501,7 +501,7 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (sBluetoothGattInterface) {
|
||||
BT_LOGR("Bluetooth GATT interface is already initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT Init runnable");
|
||||
@@ -514,7 +514,7 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no Bluetooth interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT OnError runnable");
|
||||
@@ -527,7 +527,7 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT OnError runnable");
|
||||
@@ -540,7 +540,7 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!gattInterface)) {
|
||||
// If there's no GATT interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT OnError runnable");
|
||||
@@ -615,7 +615,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothGattManager::DeinitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -651,7 +651,7 @@ BluetoothGattManager::DeinitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (!sBluetoothGattInterface) {
|
||||
BT_LOGR("Bluetooth GATT interface has not been initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT Deinit runnable");
|
||||
@@ -664,7 +664,7 @@ BluetoothGattManager::DeinitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT OnError runnable");
|
||||
@@ -677,7 +677,7 @@ BluetoothGattManager::DeinitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch GATT OnError runnable");
|
||||
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothHidManager::InitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -114,7 +114,7 @@ BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (sBluetoothHidInterface) {
|
||||
BT_LOGR("Bluetooth HID interface is already initialized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID Init runnable");
|
||||
@@ -127,7 +127,7 @@ BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID OnError runnable");
|
||||
@@ -140,7 +140,7 @@ BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID OnError runnable");
|
||||
@@ -153,7 +153,7 @@ BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!hidinterface)) {
|
||||
// If there's no HID interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID OnError runnable");
|
||||
@@ -230,7 +230,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothHidManager::DeinitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -266,7 +266,7 @@ BluetoothHidManager::DeinitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (!sBluetoothHidInterface) {
|
||||
BT_LOGR("Bluetooth Hid interface has not been initialized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID Deinit runnable");
|
||||
@@ -279,7 +279,7 @@ BluetoothHidManager::DeinitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID OnError runnable");
|
||||
@@ -292,7 +292,7 @@ BluetoothHidManager::DeinitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HID OnError runnable");
|
||||
|
||||
@@ -102,7 +102,7 @@ BluetoothOppManager::Observe(nsISupports* aSubject,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
class BluetoothOppManager::SendSocketDataTask final : public nsRunnable
|
||||
class BluetoothOppManager::SendSocketDataTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
SendSocketDataTask(UniquePtr<uint8_t[]> aStream, uint32_t aSize)
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
uint32_t mSize;
|
||||
};
|
||||
|
||||
class BluetoothOppManager::ReadFileTask final : public nsRunnable
|
||||
class BluetoothOppManager::ReadFileTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
ReadFileTask(nsIInputStream* aInputStream,
|
||||
@@ -172,7 +172,7 @@ private:
|
||||
uint32_t mAvailablePacketSize;
|
||||
};
|
||||
|
||||
class BluetoothOppManager::CloseSocketTask final : public Task
|
||||
class BluetoothOppManager::CloseSocketTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket)
|
||||
@@ -180,10 +180,11 @@ public:
|
||||
MOZ_ASSERT(aSocket);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mSocket->Close();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -1138,8 +1139,8 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
|
||||
// Disconnect request, so we make a delay here. If the socket hasn't been
|
||||
// disconnected, we will close it.
|
||||
if (mSocket) {
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
MakeAndAddRef<CloseSocketTask>(mSocket), 1000);
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::Connect) {
|
||||
MOZ_ASSERT(!mFileName.IsEmpty());
|
||||
|
||||
@@ -200,12 +200,14 @@ public:
|
||||
, mFd(aFd)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Connect(mFd);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -220,13 +222,14 @@ public:
|
||||
, mFd(aFd)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
if (!IsCanceled()) {
|
||||
GetIO()->Listen(mFd);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -240,11 +243,13 @@ class SocketConnectClientFdTask final
|
||||
: SocketIOTask<DroidSocketImpl>(aImpl)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
GetIO()->ConnectClientFd();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -303,7 +308,7 @@ DroidSocketImpl::Accept(int aFd)
|
||||
mConnectionStatus = SOCKET_IS_CONNECTED;
|
||||
|
||||
GetConsumerThread()->PostTask(
|
||||
FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
MakeAndAddRef<SocketEventTask>(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
@@ -347,12 +352,14 @@ public:
|
||||
, mFd(aFd)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Accept(mFd);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -386,8 +393,8 @@ public:
|
||||
}
|
||||
|
||||
mImpl->mConsumer->SetAddress(aBdAddress);
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE,
|
||||
new AcceptTask(mImpl, fd.forget()));
|
||||
mImpl->GetIOLoop()->PostTask(
|
||||
mozilla::MakeAndAddRef<AcceptTask>(mImpl, fd.forget()));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
@@ -416,11 +423,13 @@ public:
|
||||
, mListenFd(aListenFd)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
||||
|
||||
GetIO()->mConsumer->Accept(mListenFd, new AcceptResultHandler(GetIO()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -438,7 +447,7 @@ DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
|
||||
*/
|
||||
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
GetConsumerThread()->PostTask(FROM_HERE, new InvokeAcceptTask(this, aFd));
|
||||
GetConsumerThread()->PostTask(MakeAndAddRef<InvokeAcceptTask>(this, aFd));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -483,7 +492,7 @@ DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
|
||||
mConnectionStatus = SOCKET_IS_CONNECTED;
|
||||
|
||||
GetConsumerThread()->PostTask(
|
||||
FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
MakeAndAddRef<SocketEventTask>(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
@@ -519,7 +528,7 @@ public:
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
DroidSocketImpl* io = SocketTask<DroidSocketImpl>::GetIO();
|
||||
|
||||
@@ -528,13 +537,15 @@ public:
|
||||
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
|
||||
MOZ_ASSERT(bluetoothSocket);
|
||||
|
||||
bluetoothSocket->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -544,8 +555,8 @@ private:
|
||||
void
|
||||
DroidSocketImpl::ConsumeBuffer()
|
||||
{
|
||||
GetConsumerThread()->PostTask(FROM_HERE,
|
||||
new ReceiveTask(this, mBuffer.release()));
|
||||
GetConsumerThread()->PostTask(
|
||||
MakeAndAddRef<ReceiveTask>(this, mBuffer.release()));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -605,8 +616,8 @@ public:
|
||||
}
|
||||
|
||||
mImpl->mConsumer->SetAddress(aBdAddress);
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE,
|
||||
new SocketConnectTask(mImpl, aFd));
|
||||
mImpl->GetIOLoop()->PostTask(
|
||||
mozilla::MakeAndAddRef<SocketConnectTask>(mImpl, aFd));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
@@ -682,7 +693,8 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl, aFd));
|
||||
mImpl->GetIOLoop()->PostTask(
|
||||
mozilla::MakeAndAddRef<SocketListenTask>(mImpl, aFd));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
@@ -776,8 +788,8 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
||||
MOZ_ASSERT(!mImpl->IsShutdownOnConsumerThread());
|
||||
|
||||
mImpl->GetIOLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new SocketIOSendTask<DroidSocketImpl, UnixSocketIOBuffer>(mImpl, aBuffer));
|
||||
MakeAndAddRef<SocketIOSendTask<DroidSocketImpl, UnixSocketIOBuffer>>(
|
||||
mImpl, aBuffer));
|
||||
}
|
||||
|
||||
// |SocketBase|
|
||||
@@ -860,7 +872,7 @@ BluetoothSocket::Cleanup()
|
||||
// sever the relationship here so any future calls to listen
|
||||
// or connect will create a new implementation.
|
||||
mImpl->ShutdownOnConsumerThread();
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
|
||||
mImpl->GetIOLoop()->PostTask(MakeAndAddRef<SocketIOShutdownTask>(mImpl));
|
||||
mImpl = nullptr;
|
||||
|
||||
mSocketInterface = nullptr;
|
||||
|
||||
@@ -277,10 +277,11 @@ SocketMessageWatcherTask::SocketMessageWatcherTask(
|
||||
MOZ_ASSERT(mWatcher);
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
SocketMessageWatcherTask::Run()
|
||||
{
|
||||
mWatcher->Watch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -294,19 +295,20 @@ DeleteSocketMessageWatcherTask::DeleteSocketMessageWatcherTask(
|
||||
MOZ_ASSERT(mRes);
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
DeleteSocketMessageWatcherTask::Run()
|
||||
{
|
||||
// look up hash table for the watcher corresponding to |mRes|
|
||||
SocketMessageWatcherWrapper* wrapper = sWatcherHashtable.Get(mRes);
|
||||
if (!wrapper) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// stop the watcher if it exists
|
||||
SocketMessageWatcher* watcher = wrapper->GetSocketMessageWatcher();
|
||||
watcher->StopWatching();
|
||||
watcher->Proceed(STATUS_DONE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
@@ -84,12 +84,12 @@ private:
|
||||
/* |SocketMessageWatcherTask| starts a SocketMessageWatcher
|
||||
* on the I/O task
|
||||
*/
|
||||
class SocketMessageWatcherTask final : public Task
|
||||
class SocketMessageWatcherTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
SocketMessageWatcherTask(SocketMessageWatcher* aWatcher);
|
||||
|
||||
void Run() override;
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
SocketMessageWatcher* mWatcher;
|
||||
@@ -98,12 +98,12 @@ private:
|
||||
/* |DeleteSocketMessageWatcherTask| deletes a watching SocketMessageWatcher
|
||||
* on the I/O task
|
||||
*/
|
||||
class DeleteSocketMessageWatcherTask final : public Task
|
||||
class DeleteSocketMessageWatcherTask final : public Runnable
|
||||
{
|
||||
public:
|
||||
DeleteSocketMessageWatcherTask(BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Run() override;
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
BluetoothSocketResultHandler* mRes;
|
||||
|
||||
@@ -108,17 +108,18 @@ protected:
|
||||
~GetVolumeTask() { }
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::CloseScoTask : public Task
|
||||
class BluetoothHfpManager::CloseScoTask : public Runnable
|
||||
{
|
||||
private:
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothHfpManager);
|
||||
sBluetoothHfpManager->DisconnectSco();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::CloseScoRunnable : public nsRunnable
|
||||
class BluetoothHfpManager::CloseScoRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run() override
|
||||
@@ -126,16 +127,16 @@ public:
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE, new CloseScoTask(), sBusyToneInterval);
|
||||
MakeAndAddRef<CloseScoTask>(), sBusyToneInterval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::RespondToBLDNTask : public Task
|
||||
class BluetoothHfpManager::RespondToBLDNTask : public Runnable
|
||||
{
|
||||
private:
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothHfpManager);
|
||||
|
||||
@@ -143,6 +144,7 @@ private:
|
||||
sBluetoothHfpManager->mDialingRequestProcessed = true;
|
||||
sBluetoothHfpManager->SendResponse(HFP_AT_RESPONSE_ERROR);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -319,7 +321,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::InitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -355,7 +357,7 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (sBluetoothHfpInterface) {
|
||||
BT_LOGR("Bluetooth Handsfree interface is already initalized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP Init runnable");
|
||||
@@ -368,7 +370,7 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP OnError runnable");
|
||||
@@ -381,7 +383,7 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP OnError runnable");
|
||||
@@ -394,7 +396,7 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!interface)) {
|
||||
// If there's no HFP interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP OnError runnable");
|
||||
@@ -471,7 +473,7 @@ private:
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::DeinitProfileResultHandlerRunnable final
|
||||
: public nsRunnable
|
||||
: public Runnable
|
||||
{
|
||||
public:
|
||||
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
|
||||
@@ -507,7 +509,7 @@ BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
||||
if (!sBluetoothHfpInterface) {
|
||||
BT_LOGR("Bluetooth Handsfree interface has not been initialized.");
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP Deinit runnable");
|
||||
@@ -520,7 +522,7 @@ BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!btInf)) {
|
||||
// If there's no backend interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP OnError runnable");
|
||||
@@ -533,7 +535,7 @@ BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
||||
if (NS_WARN_IF(!setupInterface)) {
|
||||
// If there's no Setup interface, we dispatch a runnable
|
||||
// that calls the profile result handler.
|
||||
RefPtr<nsRunnable> r =
|
||||
RefPtr<Runnable> r =
|
||||
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch HFP OnError runnable");
|
||||
@@ -1597,8 +1599,7 @@ void BluetoothHfpManager::DialCallNotification(const nsAString& aNumber,
|
||||
mDialingRequestProcessed = false;
|
||||
NotifyDialer(NS_LITERAL_STRING("BLDN"));
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new RespondToBLDNTask(),
|
||||
MessageLoop::current()->PostDelayedTask(MakeAndAddRef<RespondToBLDNTask>(),
|
||||
sWaitingForDialingInterval);
|
||||
} else if (message[0] == '>') {
|
||||
mDialingRequestProcessed = false;
|
||||
@@ -1607,8 +1608,7 @@ void BluetoothHfpManager::DialCallNotification(const nsAString& aNumber,
|
||||
newMsg += StringHead(message, message.Length() - 1);
|
||||
NotifyDialer(NS_ConvertUTF8toUTF16(newMsg));
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new RespondToBLDNTask(),
|
||||
MessageLoop::current()->PostDelayedTask(MakeAndAddRef<RespondToBLDNTask>(),
|
||||
sWaitingForDialingInterval);
|
||||
} else {
|
||||
SendResponse(HFP_AT_RESPONSE_OK);
|
||||
@@ -1766,8 +1766,7 @@ BluetoothHfpManager::KeyPressedNotification(const BluetoothAddress& aBdAddress)
|
||||
|
||||
NotifyDialer(NS_LITERAL_STRING("BLDN"));
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new RespondToBLDNTask(),
|
||||
MessageLoop::current()->PostDelayedTask(MakeAndAddRef<RespondToBLDNTask>(),
|
||||
sWaitingForDialingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -242,10 +242,10 @@ BluetoothHfpManager::Notify(const hal::BatteryInformation& aBatteryInfo)
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class BluetoothHfpManager::RespondToBLDNTask : public Task
|
||||
class BluetoothHfpManager::RespondToBLDNTask : public Runnable
|
||||
{
|
||||
private:
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothHfpManager);
|
||||
|
||||
@@ -253,10 +253,11 @@ private:
|
||||
sBluetoothHfpManager->mDialingRequestProcessed = true;
|
||||
sBluetoothHfpManager->SendLine("ERROR");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class BluetoothHfpManager::SendRingIndicatorTask : public Task
|
||||
class BluetoothHfpManager::SendRingIndicatorTask : public Runnable
|
||||
{
|
||||
public:
|
||||
SendRingIndicatorTask(const nsAString& aNumber, int aType)
|
||||
@@ -266,18 +267,18 @@ public:
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Stop sending RING indicator
|
||||
if (sStopSendingRingFlag) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!sBluetoothHfpManager) {
|
||||
BT_WARNING("BluetoothHfpManager no longer exists, cannot send ring!");
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString ringMsg("RING");
|
||||
@@ -291,10 +292,10 @@ public:
|
||||
sBluetoothHfpManager->SendLine(clipMsg.get());
|
||||
}
|
||||
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
new SendRingIndicatorTask(mNumber, mType),
|
||||
sRingInterval);
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
MakeAndAddRef<SendRingIndicatorTask>(mNumber, mType), sRingInterval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -303,14 +304,16 @@ private:
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
class BluetoothHfpManager::CloseScoTask : public Task
|
||||
class BluetoothHfpManager::CloseScoTask : public Runnable
|
||||
{
|
||||
private:
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothHfpManager);
|
||||
|
||||
sBluetoothHfpManager->DisconnectSco();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -985,7 +988,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
||||
}
|
||||
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE, new RespondToBLDNTask(),
|
||||
PostDelayedTask(MakeAndAddRef<RespondToBLDNTask>(),
|
||||
sWaitingForDialingInterval);
|
||||
|
||||
// Don't send response 'OK' here because we'll respond later in either
|
||||
@@ -1490,7 +1493,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
}
|
||||
mCurrentCallArray[aCallIndex].mNumber = aNumber;
|
||||
|
||||
RefPtr<nsRunnable> sendRingTask;
|
||||
RefPtr<Runnable> sendRingTask;
|
||||
nsString address;
|
||||
|
||||
switch (aCallState) {
|
||||
@@ -1576,9 +1579,8 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
}
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
new SendRingIndicatorTask(number,
|
||||
mCurrentCallArray[aCallIndex].mType),
|
||||
MakeAndAddRef<SendRingIndicatorTask>(
|
||||
number, mCurrentCallArray[aCallIndex].mType),
|
||||
sRingInterval);
|
||||
}
|
||||
break;
|
||||
@@ -1686,8 +1688,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
DisconnectSco();
|
||||
} else {
|
||||
// Close Sco later since Dialer is still playing busy tone via HF.
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new CloseScoTask(),
|
||||
MessageLoop::current()->PostDelayedTask(MakeAndAddRef<CloseScoTask>(),
|
||||
sBusyToneInterval);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ BluetoothOppManager::Observe(nsISupports* aSubject,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
class SendSocketDataTask : public nsRunnable
|
||||
class SendSocketDataTask : public Runnable
|
||||
{
|
||||
public:
|
||||
SendSocketDataTask(UniquePtr<uint8_t[]> aStream, uint32_t aSize)
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
uint32_t mSize;
|
||||
};
|
||||
|
||||
class ReadFileTask : public nsRunnable
|
||||
class ReadFileTask : public Runnable
|
||||
{
|
||||
public:
|
||||
ReadFileTask(nsIInputStream* aInputStream,
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
uint32_t mAvailablePacketSize;
|
||||
};
|
||||
|
||||
class CloseSocketTask : public Task
|
||||
class CloseSocketTask : public Runnable
|
||||
{
|
||||
public:
|
||||
CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket)
|
||||
@@ -175,7 +175,7 @@ public:
|
||||
MOZ_ASSERT(aSocket);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@@ -183,6 +183,7 @@ public:
|
||||
SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
mSocket->Close();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -1076,7 +1077,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
|
||||
// disconnected, we will close it.
|
||||
if (mSocket) {
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
|
||||
PostDelayedTask(MakeAndAddRef<CloseSocketTask>(mSocket), 1000);
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::Connect) {
|
||||
MOZ_ASSERT(!mFileName.IsEmpty());
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
// Delayed-task handling
|
||||
//
|
||||
|
||||
void SetDelayedConnectTask(CancelableTask* aTask);
|
||||
void SetDelayedConnectTask(CancelableRunnable* aTask);
|
||||
void ClearDelayedConnectTask();
|
||||
void CancelDelayedConnectTask();
|
||||
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
* Task member for delayed connect task. Should only be access on consumer
|
||||
* thread.
|
||||
*/
|
||||
CancelableTask* mDelayedConnectTask;
|
||||
CancelableRunnable* mDelayedConnectTask;
|
||||
|
||||
/**
|
||||
* I/O buffer for received data
|
||||
@@ -193,7 +193,7 @@ BluetoothSocket::BluetoothSocketIO::GetDataSocket()
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
|
||||
BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableRunnable* aTask)
|
||||
{
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
@@ -285,7 +285,7 @@ BluetoothSocket::BluetoothSocketIO::OnConnected()
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->PostTask(
|
||||
FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
MakeAndAddRef<SocketEventTask>(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
@@ -334,7 +334,7 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanAcceptWithoutBlocking()
|
||||
SetSocket(fd, SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->PostTask(
|
||||
FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
MakeAndAddRef<SocketEventTask>(this, SocketEventTask::CONNECT_SUCCESS));
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
@@ -384,7 +384,7 @@ BluetoothSocket::BluetoothSocketIO::FireSocketError()
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->PostTask(
|
||||
FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_ERROR));
|
||||
MakeAndAddRef<SocketEventTask>(this, SocketEventTask::CONNECT_ERROR));
|
||||
}
|
||||
|
||||
// |DataSocketIO|
|
||||
@@ -416,7 +416,7 @@ public:
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
BluetoothSocketIO* io = SocketTask<BluetoothSocketIO>::GetIO();
|
||||
|
||||
@@ -425,13 +425,15 @@ public:
|
||||
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
|
||||
MOZ_ASSERT(bluetoothSocket);
|
||||
|
||||
bluetoothSocket->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -441,8 +443,8 @@ private:
|
||||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
|
||||
{
|
||||
GetConsumerThread()->PostTask(FROM_HERE,
|
||||
new ReceiveTask(this, mBuffer.release()));
|
||||
GetConsumerThread()->PostTask(
|
||||
MakeAndAddRef<ReceiveTask>(this, mBuffer.release()));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -505,13 +507,14 @@ public:
|
||||
: SocketIOTask<BluetoothSocketIO>(aIO)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
if (!IsCanceled()) {
|
||||
GetIO()->Listen();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -523,12 +526,14 @@ public:
|
||||
: SocketIOTask<BluetoothSocketIO>(aIO)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Connect();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -540,21 +545,23 @@ public:
|
||||
: SocketIOTask<BluetoothSocketIO>(aIO)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
||||
|
||||
if (IsCanceled()) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BluetoothSocketIO* io = GetIO();
|
||||
if (io->IsShutdownOnConsumerThread()) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
io->ClearDelayedConnectTask();
|
||||
io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
|
||||
io->GetIOLoop()->PostTask(MakeAndAddRef<ConnectTask>(io));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -670,11 +677,12 @@ BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
|
||||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
if (aDelayMs > 0) {
|
||||
DelayedConnectTask* connectTask = new DelayedConnectTask(mIO);
|
||||
RefPtr<DelayedConnectTask> connectTask =
|
||||
MakeAndAddRef<DelayedConnectTask>(mIO);
|
||||
mIO->SetDelayedConnectTask(connectTask);
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
|
||||
MessageLoop::current()->PostDelayedTask(connectTask.forget(), aDelayMs);
|
||||
} else {
|
||||
aIOLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
|
||||
aIOLoop->PostTask(MakeAndAddRef<ConnectTask>(mIO));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -700,7 +708,7 @@ BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector,
|
||||
mIO = new BluetoothSocketIO(aConsumerLoop, aIOLoop, this, aConnector);
|
||||
SetConnectionStatus(SOCKET_LISTENING);
|
||||
|
||||
aIOLoop->PostTask(FROM_HERE, new ListenTask(mIO));
|
||||
aIOLoop->PostTask(MakeAndAddRef<ListenTask>(mIO));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -733,8 +741,7 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
||||
MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
|
||||
|
||||
mIO->GetIOLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new SocketIOSendTask<BluetoothSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
|
||||
MakeAndAddRef<SocketIOSendTask<BluetoothSocketIO, UnixSocketIOBuffer>>(mIO, aBuffer));
|
||||
}
|
||||
|
||||
// |SocketBase|
|
||||
@@ -754,7 +761,7 @@ BluetoothSocket::Close()
|
||||
// We sever the relationship here so any future calls to listen or connect
|
||||
// will create a new implementation.
|
||||
mIO->ShutdownOnConsumerThread();
|
||||
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
|
||||
mIO->GetIOLoop()->PostTask(MakeAndAddRef<SocketIOShutdownTask>(mIO));
|
||||
mIO = nullptr;
|
||||
|
||||
NotifyDisconnect();
|
||||
|
||||
@@ -25,7 +25,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothReply;
|
||||
|
||||
class BluetoothReplyRunnable : public nsRunnable
|
||||
class BluetoothReplyRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
@@ -96,7 +96,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class BluetoothReplyTaskQueue : public nsRunnable
|
||||
class BluetoothReplyTaskQueue : public Runnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
@@ -434,7 +434,7 @@ BluetoothService::StartBluetooth(bool aIsStartup,
|
||||
}
|
||||
} else {
|
||||
BT_WARNING("Bluetooth has already been enabled before.");
|
||||
RefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(true);
|
||||
RefPtr<Runnable> runnable = new BluetoothService::ToggleBtAck(true);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
@@ -465,7 +465,7 @@ BluetoothService::StopBluetooth(bool aIsStartup,
|
||||
}
|
||||
} else {
|
||||
BT_WARNING("Bluetooth has already been enabled/disabled before.");
|
||||
RefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
|
||||
RefPtr<Runnable> runnable = new BluetoothService::ToggleBtAck(false);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class BluetoothService : public nsIObserver
|
||||
friend class StartupTask;
|
||||
|
||||
public:
|
||||
class ToggleBtAck : public nsRunnable
|
||||
class ToggleBtAck : public Runnable
|
||||
{
|
||||
public:
|
||||
ToggleBtAck(bool aEnabled);
|
||||
|
||||
@@ -897,9 +897,9 @@ private:
|
||||
{
|
||||
mService->AssignAppUuid(mServer->mAppUuid);
|
||||
|
||||
RefPtr<nsRunnable> runnable = new AddServiceTaskQueue(mServer,
|
||||
mService,
|
||||
mPromise);
|
||||
RefPtr<Runnable> runnable = new AddServiceTaskQueue(mServer,
|
||||
mService,
|
||||
mPromise);
|
||||
nsresult rv = NS_DispatchToMainThread(runnable.forget());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
||||
@@ -153,7 +153,7 @@ TestGonkCameraHardwareListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
OnTakePictureError(mTarget);
|
||||
} else if (errorType.EqualsLiteral("system")) {
|
||||
if (!NS_WARN_IF(!mCameraThread)) {
|
||||
class DeferredSystemFailure : public nsRunnable
|
||||
class DeferredSystemFailure : public Runnable
|
||||
{
|
||||
public:
|
||||
DeferredSystemFailure(nsGonkCameraControl* aTarget)
|
||||
@@ -228,7 +228,7 @@ TestGonkCameraHardwareListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
|
||||
NS_IMPL_ISUPPORTS(TestGonkCameraHardwareListener, nsIDOMEventListener)
|
||||
|
||||
class TestGonkCameraHardware::ControlMessage : public nsRunnable
|
||||
class TestGonkCameraHardware::ControlMessage : public Runnable
|
||||
{
|
||||
public:
|
||||
ControlMessage(TestGonkCameraHardware* aTestHw)
|
||||
|
||||
@@ -115,10 +115,9 @@ CryptoBuffer::FromJwkBase64(const nsString& aBase64)
|
||||
NS_ConvertUTF16toUTF8 temp(aBase64);
|
||||
temp.StripWhitespace();
|
||||
|
||||
Base64URLDecodeOptions options;
|
||||
// JWK prohibits padding per RFC 7515, section 2.
|
||||
options.mPadding = Base64URLDecodePadding::Reject;
|
||||
nsresult rv = Base64URLDecode(temp, options, *this);
|
||||
nsresult rv = Base64URLDecode(temp, Base64URLDecodePaddingPolicy::Reject,
|
||||
*this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@@ -134,9 +133,8 @@ CryptoBuffer::ToJwkBase64(nsString& aBase64)
|
||||
}
|
||||
|
||||
nsAutoCString base64;
|
||||
Base64URLEncodeOptions options;
|
||||
options.mPad = false;
|
||||
nsresult rv = Base64URLEncode(Length(), Elements(), options, base64);
|
||||
nsresult rv = Base64URLEncode(Length(), Elements(),
|
||||
Base64URLEncodePaddingPolicy::Omit, base64);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
CopyASCIItoUTF16(base64, aBase64);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js
|
||||
contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2}
|
||||
@@ -1,54 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_DataStoreCallbacks_h
|
||||
#define mozilla_dom_DataStoreCallbacks_h
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DataStoreDB;
|
||||
|
||||
class DataStoreDBCallback
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
|
||||
|
||||
enum RunStatus {
|
||||
Success,
|
||||
CreatedSchema,
|
||||
Error
|
||||
};
|
||||
|
||||
virtual void Run(DataStoreDB* aDb, RunStatus aStatus) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~DataStoreDBCallback()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DataStoreRevisionCallback
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
|
||||
|
||||
virtual void Run(const nsAString& aRevisionID) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~DataStoreRevisionCallback()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DataStoreCallbacks_h
|
||||
@@ -1,223 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"];
|
||||
|
||||
function debug(s) {
|
||||
//dump('DEBUG DataStoreChangeNotifier: ' + s + '\n');
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageBroadcaster");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
|
||||
"@mozilla.org/datastore-service;1",
|
||||
"nsIDataStoreService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "systemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
var kSysMsgOnChangeShortTimeoutSec =
|
||||
Services.prefs.getIntPref("dom.datastore.sysMsgOnChangeShortTimeoutSec");
|
||||
var kSysMsgOnChangeLongTimeoutSec =
|
||||
Services.prefs.getIntPref("dom.datastore.sysMsgOnChangeLongTimeoutSec");
|
||||
|
||||
this.DataStoreChangeNotifier = {
|
||||
children: [],
|
||||
messages: [ "DataStore:Changed", "DataStore:RegisterForMessages",
|
||||
"DataStore:UnregisterForMessages",
|
||||
"child-process-shutdown" ],
|
||||
|
||||
// These hashes are used for storing the mapping between the datastore
|
||||
// identifiers (name | owner manifest URL) and their correspondent timers.
|
||||
// The object literal is defined as below:
|
||||
//
|
||||
// {
|
||||
// "datastore name 1|owner manifest URL 1": timer1,
|
||||
// "datastore name 2|owner manifest URL 2": timer2,
|
||||
// ...
|
||||
// }
|
||||
sysMsgOnChangeShortTimers: {},
|
||||
sysMsgOnChangeLongTimers: {},
|
||||
|
||||
init: function() {
|
||||
debug("init");
|
||||
|
||||
this.messages.forEach((function(msgName) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
Services.obs.addObserver(this, 'xpcom-shutdown', false);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
debug("observe");
|
||||
|
||||
switch (aTopic) {
|
||||
case 'xpcom-shutdown':
|
||||
this.messages.forEach((function(msgName) {
|
||||
ppmm.removeMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
Services.obs.removeObserver(this, 'xpcom-shutdown');
|
||||
ppmm = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Wrong observer topic: " + aTopic);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
broadcastMessage: function broadcastMessage(aData) {
|
||||
debug("broadcast");
|
||||
|
||||
this.children.forEach(function(obj) {
|
||||
if (obj.store == aData.store && obj.owner == aData.owner) {
|
||||
obj.mm.sendAsyncMessage("DataStore:Changed:Return:OK", aData);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
broadcastSystemMessage: function(aStore, aOwner) {
|
||||
debug("broadcastSystemMessage");
|
||||
|
||||
// Clear relevant timers.
|
||||
var storeKey = aStore + "|" + aOwner;
|
||||
var shortTimer = this.sysMsgOnChangeShortTimers[storeKey];
|
||||
if (shortTimer) {
|
||||
shortTimer.cancel();
|
||||
delete this.sysMsgOnChangeShortTimers[storeKey];
|
||||
}
|
||||
var longTimer = this.sysMsgOnChangeLongTimers[storeKey];
|
||||
if (longTimer) {
|
||||
longTimer.cancel();
|
||||
delete this.sysMsgOnChangeLongTimers[storeKey];
|
||||
}
|
||||
|
||||
systemMessenger.broadcastMessage("datastore-update-" + aStore,
|
||||
{ owner: aOwner });
|
||||
},
|
||||
|
||||
// Use the following logic to broadcast system messages in a moderate pattern.
|
||||
// 1. When an entry is changed, start a short timer and a long timer.
|
||||
// 2. If an entry is changed while the short timer is running, reset it.
|
||||
// Do not reset the long timer.
|
||||
// 3. Once either fires, broadcast the system message and cancel both timers.
|
||||
setSystemMessageTimeout: function(aStore, aOwner) {
|
||||
debug("setSystemMessageTimeout");
|
||||
|
||||
var storeKey = aStore + "|" + aOwner;
|
||||
|
||||
// Reset the short timer.
|
||||
var shortTimer = this.sysMsgOnChangeShortTimers[storeKey];
|
||||
if (!shortTimer) {
|
||||
shortTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.sysMsgOnChangeShortTimers[storeKey] = shortTimer;
|
||||
} else {
|
||||
shortTimer.cancel();
|
||||
}
|
||||
shortTimer.initWithCallback({ notify: this.broadcastSystemMessage.bind(this, aStore, aOwner) },
|
||||
kSysMsgOnChangeShortTimeoutSec * 1000,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
// Set the long timer if necessary.
|
||||
if (!this.sysMsgOnChangeLongTimers[storeKey]) {
|
||||
var longTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.sysMsgOnChangeLongTimers[storeKey] = longTimer;
|
||||
longTimer.initWithCallback({ notify: this.broadcastSystemMessage.bind(this, aStore, aOwner) },
|
||||
kSysMsgOnChangeLongTimeoutSec * 1000,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage ");
|
||||
|
||||
// No check has to be done when the message is 'child-process-shutdown'.
|
||||
if (aMessage.name != "child-process-shutdown") {
|
||||
let principal = aMessage.principal;
|
||||
if (!principal || !dataStoreService.checkPermission(principal)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "DataStore:Changed":
|
||||
this.broadcastMessage(aMessage.data);
|
||||
if (Services.prefs.getBoolPref("dom.sysmsg.enabled")) {
|
||||
this.setSystemMessageTimeout(aMessage.data.store, aMessage.data.owner);
|
||||
}
|
||||
break;
|
||||
|
||||
case "DataStore:RegisterForMessages":
|
||||
debug("Register!");
|
||||
|
||||
for (let i = 0; i < this.children.length; ++i) {
|
||||
if (this.children[i].mm == aMessage.target &&
|
||||
this.children[i].store == aMessage.data.store &&
|
||||
this.children[i].owner == aMessage.data.owner) {
|
||||
debug("Register on existing index: " + i);
|
||||
this.children[i].windows.push(aMessage.data.innerWindowID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.children.push({ mm: aMessage.target,
|
||||
store: aMessage.data.store,
|
||||
owner: aMessage.data.owner,
|
||||
windows: [ aMessage.data.innerWindowID ]});
|
||||
break;
|
||||
|
||||
case "DataStore:UnregisterForMessages":
|
||||
debug("Unregister");
|
||||
|
||||
for (let i = 0; i < this.children.length; ++i) {
|
||||
if (this.children[i].mm == aMessage.target) {
|
||||
debug("Unregister index: " + i);
|
||||
|
||||
var pos = this.children[i].windows.indexOf(aMessage.data.innerWindowID);
|
||||
if (pos != -1) {
|
||||
this.children[i].windows.splice(pos, 1);
|
||||
}
|
||||
|
||||
if (this.children[i].windows.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Unregister delete index: " + i);
|
||||
this.children.splice(i, 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "child-process-shutdown":
|
||||
debug("Child process shutdown");
|
||||
|
||||
for (let i = 0; i < this.children.length; ++i) {
|
||||
if (this.children[i].mm == aMessage.target) {
|
||||
debug("Unregister index: " + i);
|
||||
this.children.splice(i, 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataStoreChangeNotifier.init();
|
||||
@@ -1,79 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/DataStore.h"
|
||||
#include "mozilla/dom/DataStoreCursor.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/DataStoreImplBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DataStoreCursor)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DataStoreCursor)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataStoreCursor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(DataStoreCursor, mCursor)
|
||||
|
||||
already_AddRefed<DataStoreCursor>
|
||||
DataStoreCursor::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<DataStoreCursor> cursor = new DataStoreCursor();
|
||||
return cursor.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
DataStoreCursor::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector)
|
||||
{
|
||||
return DataStoreCursorBinding::Wrap(aCx, this, aGivenProto, aReflector);
|
||||
}
|
||||
|
||||
already_AddRefed<DataStore>
|
||||
DataStoreCursor::GetStore(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mCursor);
|
||||
|
||||
return mCursor->GetStore(aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
DataStoreCursor::Next(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mCursor);
|
||||
|
||||
return mCursor->Next(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
DataStoreCursor::Close(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mCursor);
|
||||
|
||||
mCursor->Close(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
DataStoreCursor::SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mCursor);
|
||||
|
||||
mCursor = &aCursor;
|
||||
}
|
||||
|
||||
} //namespace dom
|
||||
} //namespace mozilla
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_DataStoreCursor_h
|
||||
#define mozilla_dom_DataStoreCursor_h
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class DataStore;
|
||||
class GlobalObject;
|
||||
class DataStoreCursorImpl;
|
||||
|
||||
class DataStoreCursor final : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(DataStoreCursor)
|
||||
|
||||
// WebIDL (internal functions)
|
||||
|
||||
static already_AddRefed<DataStoreCursor> Constructor(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
|
||||
|
||||
// WebIDL (public APIs)
|
||||
|
||||
already_AddRefed<DataStore> GetStore(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Next(ErrorResult& aRv);
|
||||
|
||||
void Close(ErrorResult& aRv);
|
||||
|
||||
// This internal function (ChromeOnly) is aimed to make the DataStoreCursor
|
||||
// keep a reference to the DataStoreCursorImpl which really implements the
|
||||
// API's logic in JS.
|
||||
void SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor);
|
||||
|
||||
private:
|
||||
~DataStoreCursor() {}
|
||||
RefPtr<DataStoreCursorImpl> mCursor;
|
||||
};
|
||||
|
||||
} //namespace dom
|
||||
} //namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -1,444 +0,0 @@
|
||||
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
'use strict'
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['DataStoreCursor'];
|
||||
|
||||
function debug(s) {
|
||||
//dump('DEBUG DataStoreCursor: ' + s + '\n');
|
||||
}
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
const STATE_INIT = 0;
|
||||
const STATE_REVISION_INIT = 1;
|
||||
const STATE_REVISION_CHECK = 2;
|
||||
const STATE_SEND_ALL = 3;
|
||||
const STATE_REVISION_SEND = 4;
|
||||
const STATE_DONE = 5;
|
||||
|
||||
const REVISION_ADDED = 'added';
|
||||
const REVISION_UPDATED = 'updated';
|
||||
const REVISION_REMOVED = 'removed';
|
||||
const REVISION_VOID = 'void';
|
||||
const REVISION_SKIP = 'skip'
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
/**
|
||||
* legend:
|
||||
* - RID = revision ID
|
||||
* - R = revision object (with the internalRevisionId that is a number)
|
||||
* - X = current object ID.
|
||||
* - L = the list of revisions that we have to send
|
||||
*
|
||||
* State: init: do you have RID ?
|
||||
* YES: state->initRevision; loop
|
||||
* NO: get R; X=0; state->sendAll; send a 'clear'
|
||||
*
|
||||
* State: initRevision. Get R from RID. Done?
|
||||
* YES: state->revisionCheck; loop
|
||||
* NO: RID = null; state->init; loop
|
||||
*
|
||||
* State: revisionCheck: get all the revisions between R and NOW. Done?
|
||||
* YES and R == NOW: state->done; loop
|
||||
* YES and R != NOW: Store this revisions in L; state->revisionSend; loop
|
||||
* NO: R = NOW; X=0; state->sendAll; send a 'clear'
|
||||
*
|
||||
* State: sendAll: is R still the last revision?
|
||||
* YES get the first object with id > X. Done?
|
||||
* YES: X = object.id; send 'add'
|
||||
* NO: state->revisionCheck; loop
|
||||
* NO: R = NOW; X=0; send a 'clear'
|
||||
*
|
||||
* State: revisionSend: do you have something from L to send?
|
||||
* YES and L[0] == 'removed': R=L[0]; send 'remove' with ID
|
||||
* YES and L[0] == 'added': R=L[0]; get the object; found?
|
||||
* NO: loop
|
||||
* YES: send 'add' with ID and object
|
||||
* YES and L[0] == 'updated': R=L[0]; get the object; found?
|
||||
* NO: loop
|
||||
* YES and object.R > R: continue
|
||||
* YES and object.R <= R: send 'update' with ID and object
|
||||
* YES L[0] == 'void': R=L[0]; state->init; loop
|
||||
* NO: state->revisionCheck; loop
|
||||
*
|
||||
* State: done: send a 'done' with R
|
||||
*/
|
||||
|
||||
/* Helper functions */
|
||||
function createDOMError(aWindow, aEvent) {
|
||||
return new aWindow.DOMError(aEvent);
|
||||
}
|
||||
|
||||
/* DataStoreCursor object */
|
||||
this.DataStoreCursor = function(aWindow, aDataStore, aRevisionId) {
|
||||
debug("DataStoreCursor created");
|
||||
this.init(aWindow, aDataStore, aRevisionId);
|
||||
}
|
||||
|
||||
this.DataStoreCursor.prototype = {
|
||||
classDescription: 'DataStoreCursor XPCOM Component',
|
||||
classID: Components.ID('{b6d14349-1eab-46b8-8513-584a7328a26b}'),
|
||||
contractID: '@mozilla.org/dom/datastore-cursor-impl;1',
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports]),
|
||||
|
||||
_shuttingdown: false,
|
||||
|
||||
_window: null,
|
||||
_dataStore: null,
|
||||
_revisionId: null,
|
||||
_revision: null,
|
||||
_revisionsList: null,
|
||||
_objectId: 0,
|
||||
|
||||
_state: STATE_INIT,
|
||||
|
||||
init: function(aWindow, aDataStore, aRevisionId) {
|
||||
debug('DataStoreCursor init');
|
||||
|
||||
this._window = aWindow;
|
||||
this._dataStore = aDataStore;
|
||||
this._revisionId = aRevisionId;
|
||||
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
this._innerWindowID = util.currentInnerWindowID;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this._innerWindowID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._shuttingdown = true;
|
||||
}
|
||||
},
|
||||
|
||||
// This is the implementation of the state machine.
|
||||
// Read the comments at the top of this file in order to follow what it does.
|
||||
stateMachine: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachine: ' + this._state);
|
||||
|
||||
// If the window has been destroyed we cannot create the Promise object.
|
||||
if (this._shuttingdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this._state) {
|
||||
case STATE_INIT:
|
||||
this.stateMachineInit(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
|
||||
case STATE_REVISION_INIT:
|
||||
this.stateMachineRevisionInit(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
|
||||
case STATE_REVISION_CHECK:
|
||||
this.stateMachineRevisionCheck(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
|
||||
case STATE_SEND_ALL:
|
||||
this.stateMachineSendAll(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
|
||||
case STATE_REVISION_SEND:
|
||||
this.stateMachineRevisionSend(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
|
||||
case STATE_DONE:
|
||||
this.stateMachineDone(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
stateMachineInit: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachineInit');
|
||||
|
||||
if (this._revisionId) {
|
||||
this._state = STATE_REVISION_INIT;
|
||||
this.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let request = aRevisionStore.openCursor(null, 'prev');
|
||||
request.onsuccess = function(aEvent) {
|
||||
if (aEvent.target.result === undefined) {
|
||||
aReject(self._window.DOMError("InvalidRevision",
|
||||
"The DataStore is corrupted"));
|
||||
return;
|
||||
}
|
||||
|
||||
self._revision = aEvent.target.result.value;
|
||||
self._objectId = 0;
|
||||
self._state = STATE_SEND_ALL;
|
||||
aResolve(self.createTask('clear', null, '', null));
|
||||
}
|
||||
},
|
||||
|
||||
stateMachineRevisionInit: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachineRevisionInit');
|
||||
|
||||
let self = this;
|
||||
let request = this._dataStore._db.getInternalRevisionId(
|
||||
self._revisionId,
|
||||
aRevisionStore,
|
||||
function(aInternalRevisionId) {
|
||||
// This revision doesn't exist.
|
||||
if (aInternalRevisionId == undefined) {
|
||||
self._revisionId = null;
|
||||
self._objectId = 0;
|
||||
self._state = STATE_INIT;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
self._revision = { revisionId: self._revisionId,
|
||||
internalRevisionId: aInternalRevisionId };
|
||||
self._state = STATE_REVISION_CHECK;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
stateMachineRevisionCheck: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachineRevisionCheck');
|
||||
|
||||
let changes = {
|
||||
addedIds: {},
|
||||
updatedIds: {},
|
||||
removedIds: {}
|
||||
};
|
||||
|
||||
let self = this;
|
||||
let request = aRevisionStore.mozGetAll(
|
||||
self._window.IDBKeyRange.lowerBound(this._revision.internalRevisionId, true));
|
||||
request.onsuccess = function(aEvent) {
|
||||
|
||||
// Optimize the operations.
|
||||
for (let i = 0; i < aEvent.target.result.length; ++i) {
|
||||
let data = aEvent.target.result[i];
|
||||
|
||||
switch (data.operation) {
|
||||
case REVISION_ADDED:
|
||||
changes.addedIds[data.objectId] = data.internalRevisionId;
|
||||
break;
|
||||
|
||||
case REVISION_UPDATED:
|
||||
// We don't consider an update if this object has been added
|
||||
// or if it has been already modified by a previous
|
||||
// operation.
|
||||
if (!(data.objectId in changes.addedIds) &&
|
||||
!(data.objectId in changes.updatedIds)) {
|
||||
changes.updatedIds[data.objectId] = data.internalRevisionId;
|
||||
}
|
||||
break;
|
||||
|
||||
case REVISION_REMOVED:
|
||||
let id = data.objectId;
|
||||
|
||||
// If the object has been added in this range of revisions
|
||||
// we can ignore it and remove it from the list.
|
||||
if (id in changes.addedIds) {
|
||||
delete changes.addedIds[id];
|
||||
} else {
|
||||
changes.removedIds[id] = data.internalRevisionId;
|
||||
}
|
||||
|
||||
if (id in changes.updatedIds) {
|
||||
delete changes.updatedIds[id];
|
||||
}
|
||||
break;
|
||||
|
||||
case REVISION_VOID:
|
||||
if (i != 0) {
|
||||
dump('Internal error: Revision "' + REVISION_VOID + '" should not be found!!!\n');
|
||||
return;
|
||||
}
|
||||
|
||||
self._revisionId = null;
|
||||
self._objectId = 0;
|
||||
self._state = STATE_INIT;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// From changes to a map of internalRevisionId.
|
||||
let revisions = {};
|
||||
function addRevisions(obj) {
|
||||
for (let key in obj) {
|
||||
revisions[obj[key]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
addRevisions(changes.addedIds);
|
||||
addRevisions(changes.updatedIds);
|
||||
addRevisions(changes.removedIds);
|
||||
|
||||
// Create the list of revisions.
|
||||
let list = [];
|
||||
for (let i = 0; i < aEvent.target.result.length; ++i) {
|
||||
let data = aEvent.target.result[i];
|
||||
|
||||
// If this revision doesn't contain useful data, we still need to keep
|
||||
// it in the list because we need to update the internal revision ID.
|
||||
if (!(data.internalRevisionId in revisions)) {
|
||||
data.operation = REVISION_SKIP;
|
||||
}
|
||||
|
||||
list.push(data);
|
||||
}
|
||||
|
||||
if (list.length == 0) {
|
||||
self._state = STATE_DONE;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
// Some revision has to be sent.
|
||||
self._revisionsList = list;
|
||||
self._state = STATE_REVISION_SEND;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
};
|
||||
},
|
||||
|
||||
stateMachineSendAll: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachineSendAll');
|
||||
|
||||
let self = this;
|
||||
let request = aRevisionStore.openCursor(null, 'prev');
|
||||
request.onsuccess = function(aEvent) {
|
||||
if (self._revision.revisionId != aEvent.target.result.value.revisionId) {
|
||||
self._revision = aEvent.target.result.value;
|
||||
self._objectId = 0;
|
||||
aResolve(self.createTask('clear', null, '', null));
|
||||
return;
|
||||
}
|
||||
|
||||
let request = aStore.openCursor(self._window.IDBKeyRange.lowerBound(self._objectId, true));
|
||||
request.onsuccess = function(aEvent) {
|
||||
let cursor = aEvent.target.result;
|
||||
if (!cursor) {
|
||||
self._state = STATE_REVISION_CHECK;
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
self._objectId = cursor.key;
|
||||
aResolve(self.createTask('add', self._objectId, '', cursor.value));
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
stateMachineRevisionSend: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
debug('StateMachineRevisionSend');
|
||||
|
||||
if (!this._revisionsList.length) {
|
||||
this._state = STATE_REVISION_CHECK;
|
||||
this.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
this._revision = this._revisionsList.shift();
|
||||
|
||||
switch (this._revision.operation) {
|
||||
case REVISION_REMOVED:
|
||||
aResolve(this.createTask('remove', this._revision.objectId, '', null));
|
||||
break;
|
||||
|
||||
case REVISION_ADDED: {
|
||||
let request = aStore.get(this._revision.objectId);
|
||||
let self = this;
|
||||
request.onsuccess = function(aEvent) {
|
||||
if (aEvent.target.result == undefined) {
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
aResolve(self.createTask('add', self._revision.objectId, '',
|
||||
aEvent.target.result));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case REVISION_UPDATED: {
|
||||
let request = aStore.get(this._revision.objectId);
|
||||
let self = this;
|
||||
request.onsuccess = function(aEvent) {
|
||||
if (aEvent.target.result == undefined) {
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aEvent.target.result.revisionId > self._revision.internalRevisionId) {
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
return;
|
||||
}
|
||||
|
||||
aResolve(self.createTask('update', self._revision.objectId, '',
|
||||
aEvent.target.result));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case REVISION_VOID:
|
||||
// Internal error!
|
||||
dump('Internal error: Revision "' + REVISION_VOID + '" should not be found!!!\n');
|
||||
break;
|
||||
|
||||
case REVISION_SKIP:
|
||||
// This revision contains data that has already been sent by another one.
|
||||
this.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
stateMachineDone: function(aStore, aRevisionStore, aResolve, aReject) {
|
||||
this.close();
|
||||
aResolve(this.createTask('done', null, this._revision.revisionId, null));
|
||||
},
|
||||
|
||||
// public interface
|
||||
|
||||
get store() {
|
||||
return this._dataStore.exposedObject;
|
||||
},
|
||||
|
||||
next: function() {
|
||||
debug('Next');
|
||||
|
||||
// If the window has been destroyed we cannot create the Promise object.
|
||||
if (this._shuttingdown) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
return new this._window.Promise(function(aResolve, aReject) {
|
||||
self._dataStore._db.cursorTxn(
|
||||
function(aTxn, aStore, aRevisionStore) {
|
||||
self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
|
||||
},
|
||||
function(aEvent) {
|
||||
aReject(createDOMError(self._window, aEvent));
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this._dataStore.syncTerminated(this);
|
||||
},
|
||||
|
||||
createTask: function(aOperation, aId, aRevisionId, aData) {
|
||||
return Cu.cloneInto({ operation: aOperation, id: aId,
|
||||
revisionId: aRevisionId, data: aData }, this._window);
|
||||
}
|
||||
};
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_DataStoreDB_h
|
||||
#define mozilla_dom_DataStoreDB_h
|
||||
|
||||
#include "mozilla/dom/IDBTransactionBinding.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define DATASTOREDB_REVISION "revision"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DataStoreDBCallback;
|
||||
class IDBDatabase;
|
||||
class IDBFactory;
|
||||
class IDBOpenDBRequest;
|
||||
class IDBTransaction;
|
||||
|
||||
class DataStoreDB final : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
DataStoreDB(const nsAString& aManifestURL, const nsAString& aName);
|
||||
|
||||
nsresult Open(IDBTransactionMode aMode, const Sequence<nsString>& aDb,
|
||||
DataStoreDBCallback* aCallback);
|
||||
|
||||
nsresult Delete();
|
||||
|
||||
IDBTransaction* Transaction() const;
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override;
|
||||
|
||||
private:
|
||||
~DataStoreDB();
|
||||
|
||||
nsresult CreateFactoryIfNeeded();
|
||||
|
||||
nsresult UpgradeSchema(nsIDOMEvent* aEvent);
|
||||
|
||||
nsresult DatabaseOpened();
|
||||
|
||||
nsresult AddEventListeners();
|
||||
|
||||
nsresult RemoveEventListeners();
|
||||
|
||||
nsString mDatabaseName;
|
||||
|
||||
RefPtr<IDBFactory> mFactory;
|
||||
RefPtr<IDBOpenDBRequest> mRequest;
|
||||
RefPtr<IDBDatabase> mDatabase;
|
||||
RefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
RefPtr<DataStoreDBCallback> mCallback;
|
||||
|
||||
// Internal state to avoid strange use of this class.
|
||||
enum StateType {
|
||||
Inactive,
|
||||
Active
|
||||
} mState;
|
||||
|
||||
IDBTransactionMode mTransactionMode;
|
||||
Sequence<nsString> mObjectStores;
|
||||
bool mCreatedSchema;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DataStoreDB_h
|
||||
@@ -1,118 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['DataStoreDB'];
|
||||
|
||||
function debug(s) {
|
||||
//dump('DEBUG DataStoreDB: ' + s + '\n');
|
||||
}
|
||||
|
||||
const DATASTOREDB_VERSION = 1;
|
||||
const DATASTOREDB_OBJECTSTORE_NAME = 'DataStoreDB';
|
||||
const DATASTOREDB_REVISION = 'revision';
|
||||
const DATASTOREDB_REVISION_INDEX = 'revisionIndex';
|
||||
|
||||
Cu.import('resource://gre/modules/IndexedDBHelper.jsm');
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
this.DataStoreDB = function DataStoreDB() {}
|
||||
|
||||
DataStoreDB.prototype = {
|
||||
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
upgradeSchema: function(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
debug('updateSchema');
|
||||
aDb.createObjectStore(DATASTOREDB_OBJECTSTORE_NAME, { autoIncrement: true });
|
||||
let store = aDb.createObjectStore(DATASTOREDB_REVISION,
|
||||
{ autoIncrement: true,
|
||||
keyPath: 'internalRevisionId' });
|
||||
store.createIndex(DATASTOREDB_REVISION_INDEX, 'revisionId', { unique: true });
|
||||
},
|
||||
|
||||
init: function(aOwner, aName) {
|
||||
let dbName = aName + '|' + aOwner;
|
||||
this.initDBHelper(dbName, DATASTOREDB_VERSION,
|
||||
[DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION]);
|
||||
},
|
||||
|
||||
txn: function(aType, aCallback, aErrorCb) {
|
||||
debug('Transaction request');
|
||||
this.newTxn(
|
||||
aType,
|
||||
aType == 'readonly'
|
||||
? [ DATASTOREDB_OBJECTSTORE_NAME ] : [ DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION ],
|
||||
function(aTxn, aStores) {
|
||||
aType == 'readonly' ? aCallback(aTxn, aStores[0], null) : aCallback(aTxn, aStores[0], aStores[1]);
|
||||
},
|
||||
function() {},
|
||||
aErrorCb
|
||||
);
|
||||
},
|
||||
|
||||
cursorTxn: function(aCallback, aErrorCb) {
|
||||
debug('Cursor transaction request');
|
||||
this.newTxn(
|
||||
'readonly',
|
||||
[ DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION ],
|
||||
function(aTxn, aStores) {
|
||||
aCallback(aTxn, aStores[0], aStores[1]);
|
||||
},
|
||||
function() {},
|
||||
aErrorCb
|
||||
);
|
||||
},
|
||||
|
||||
revisionTxn: function(aType, aCallback, aErrorCb) {
|
||||
debug("Transaction request");
|
||||
this.newTxn(
|
||||
aType,
|
||||
DATASTOREDB_REVISION,
|
||||
aCallback,
|
||||
function() {},
|
||||
aErrorCb
|
||||
);
|
||||
},
|
||||
|
||||
addRevision: function(aStore, aKey, aType, aSuccessCb) {
|
||||
debug("AddRevision: " + aKey + " - " + aType);
|
||||
let revisionId = uuidgen.generateUUID().toString();
|
||||
let request = aStore.put({ revisionId: revisionId, objectId: aKey, operation: aType });
|
||||
request.onsuccess = function() {
|
||||
aSuccessCb(revisionId);
|
||||
}
|
||||
},
|
||||
|
||||
getInternalRevisionId: function(aRevisionId, aStore, aSuccessCb) {
|
||||
debug('GetInternalRevisionId');
|
||||
let request = aStore.index(DATASTOREDB_REVISION_INDEX).getKey(aRevisionId);
|
||||
request.onsuccess = function(aEvent) {
|
||||
aSuccessCb(aEvent.target.result);
|
||||
}
|
||||
},
|
||||
|
||||
clearRevisions: function(aStore, aSuccessCb) {
|
||||
debug("ClearRevisions");
|
||||
let request = aStore.clear();
|
||||
request.onsuccess = function() {
|
||||
aSuccessCb();
|
||||
}
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
debug('delete');
|
||||
this.close();
|
||||
indexedDB.deleteDatabase(this.dbName);
|
||||
debug('database deleted');
|
||||
}
|
||||
}
|
||||
@@ -1,549 +0,0 @@
|
||||
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
'use strict'
|
||||
|
||||
function debug(s) {
|
||||
//dump('DEBUG DataStore: ' + s + '\n');
|
||||
}
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
const REVISION_ADDED = "added";
|
||||
const REVISION_UPDATED = "updated";
|
||||
const REVISION_REMOVED = "removed";
|
||||
const REVISION_VOID = "void";
|
||||
|
||||
// This value has to be tuned a bit. Currently it's just a guess
|
||||
// and yet we don't know if it's too low or too high.
|
||||
const MAX_REQUESTS = 25;
|
||||
|
||||
Cu.import("resource://gre/modules/DataStoreCursorImpl.jsm");
|
||||
Cu.import("resource://gre/modules/DataStoreDB.jsm");
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
/* Helper functions */
|
||||
function createDOMError(aWindow, aEvent) {
|
||||
return new aWindow.DOMError(aEvent);
|
||||
}
|
||||
|
||||
function throwInvalidArg(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("SyntaxError", "Non-numeric or invalid id"));
|
||||
}
|
||||
|
||||
function throwReadOnly(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("ReadOnlyError", "DataStore in readonly mode"));
|
||||
}
|
||||
|
||||
function validateId(aId) {
|
||||
// If string, it cannot be empty.
|
||||
if (typeof(aId) == 'string') {
|
||||
return aId.length;
|
||||
}
|
||||
|
||||
aId = parseInt(aId);
|
||||
return (!isNaN(aId) && aId > 0);
|
||||
}
|
||||
|
||||
/* DataStore object */
|
||||
function DataStore() {
|
||||
debug("DataStore created");
|
||||
}
|
||||
|
||||
DataStore.prototype = {
|
||||
classDescription: "DataStore XPCOM Component",
|
||||
classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"),
|
||||
contractID: "@mozilla.org/dom/datastore-impl;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStore, Ci.nsISupports,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
callbacks: [],
|
||||
|
||||
_window: null,
|
||||
_name: null,
|
||||
_owner: null,
|
||||
_readOnly: null,
|
||||
_revisionId: null,
|
||||
_exposedObject: null,
|
||||
_cursor: null,
|
||||
_shuttingdown: false,
|
||||
_eventTarget: null,
|
||||
|
||||
init: function(aWindow, aName, aOwner, aReadOnly) {
|
||||
debug("DataStore init");
|
||||
|
||||
this._window = aWindow;
|
||||
this._name = aName;
|
||||
this._owner = aOwner;
|
||||
this._readOnly = aReadOnly;
|
||||
|
||||
this._db = new DataStoreDB();
|
||||
this._db.init(aOwner, aName);
|
||||
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
this._innerWindowID = util.currentInnerWindowID;
|
||||
|
||||
cpmm.addMessageListener("DataStore:Changed:Return:OK", this);
|
||||
cpmm.sendAsyncMessage("DataStore:RegisterForMessages",
|
||||
{ store: this._name, owner: this._owner,
|
||||
innerWindowID: this._innerWindowID },
|
||||
null,
|
||||
this._window.document.nodePrincipal);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this._innerWindowID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
|
||||
cpmm.removeMessageListener("DataStore:Changed:Return:OK", this);
|
||||
cpmm.sendAsyncMessage("DataStore:UnregisterForMessages",
|
||||
{ innerWindowID: this._innerWindowID },
|
||||
null,
|
||||
this._window.document.nodePrincipal);
|
||||
this._shuttingdown = true;
|
||||
this._db.close();
|
||||
}
|
||||
},
|
||||
|
||||
setEventTarget: function(aEventTarget) {
|
||||
this._eventTarget = aEventTarget;
|
||||
},
|
||||
|
||||
newDBPromise: function(aTxnType, aFunction) {
|
||||
let self = this;
|
||||
return new this._window.Promise(function(aResolve, aReject) {
|
||||
debug("DBPromise started");
|
||||
self._db.txn(
|
||||
aTxnType,
|
||||
function(aTxn, aStore, aRevisionStore) {
|
||||
debug("DBPromise success");
|
||||
aFunction(aResolve, aReject, aTxn, aStore, aRevisionStore);
|
||||
},
|
||||
function(aEvent) {
|
||||
debug("DBPromise error");
|
||||
aReject(createDOMError(self._window, aEvent));
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
checkRevision: function(aReject, aRevisionStore, aRevisionId, aCallback) {
|
||||
if (!aRevisionId) {
|
||||
aCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
let request = aRevisionStore.openCursor(null, 'prev');
|
||||
request.onsuccess = function(aEvent) {
|
||||
let cursor = aEvent.target.result;
|
||||
if (!cursor) {
|
||||
dump("This cannot really happen.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor.value.revisionId != aRevisionId) {
|
||||
aReject(new self._window.DOMError("ConstraintError",
|
||||
"RevisionId is not up-to-date"));
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback();
|
||||
}
|
||||
},
|
||||
|
||||
getInternal: function(aStore, aIds, aCallback) {
|
||||
debug("GetInternal: " + aIds.toSource());
|
||||
|
||||
// Creation of the results array.
|
||||
let results = new this._window.Array(aIds.length);
|
||||
|
||||
// We're going to create this amount of requests.
|
||||
let pendingIds = aIds.length;
|
||||
let indexPos = 0;
|
||||
|
||||
let self = this;
|
||||
|
||||
function getInternalSuccess(aEvent, aPos) {
|
||||
debug("GetInternal success. Record: " + aEvent.target.result);
|
||||
results[aPos] = Cu.cloneInto(aEvent.target.result, self._window);
|
||||
if (!--pendingIds) {
|
||||
aCallback(results);
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexPos < aIds.length) {
|
||||
// Just MAX_REQUESTS requests at the same time.
|
||||
let count = 0;
|
||||
while (indexPos < aIds.length && ++count < MAX_REQUESTS) {
|
||||
getInternalRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getInternalRequest() {
|
||||
let currentPos = indexPos++;
|
||||
let request = aStore.get(aIds[currentPos]);
|
||||
request.onsuccess = function(aEvent) {
|
||||
getInternalSuccess(aEvent, currentPos);
|
||||
}
|
||||
}
|
||||
|
||||
getInternalRequest();
|
||||
},
|
||||
|
||||
putInternal: function(aResolve, aStore, aRevisionStore, aObj, aId) {
|
||||
debug("putInternal " + aId);
|
||||
|
||||
let self = this;
|
||||
let request = aStore.put(aObj, aId);
|
||||
request.onsuccess = function(aEvent) {
|
||||
debug("putInternal success");
|
||||
|
||||
self.addRevision(aRevisionStore, aId, REVISION_UPDATED,
|
||||
function() {
|
||||
debug("putInternal - revisionId increased");
|
||||
// No wrap here because the result is always a int.
|
||||
aResolve(aEvent.target.result);
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
addInternal: function(aResolve, aStore, aRevisionStore, aObj, aId) {
|
||||
debug("AddInternal");
|
||||
|
||||
let self = this;
|
||||
let request = aStore.add(aObj, aId);
|
||||
request.onsuccess = function(aEvent) {
|
||||
debug("Request successful. Id: " + aEvent.target.result);
|
||||
self.addRevision(aRevisionStore, aEvent.target.result, REVISION_ADDED,
|
||||
function() {
|
||||
debug("AddInternal - revisionId increased");
|
||||
// No wrap here because the result is always a int.
|
||||
aResolve(aEvent.target.result);
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
removeInternal: function(aResolve, aStore, aRevisionStore, aId) {
|
||||
debug("RemoveInternal");
|
||||
|
||||
let self = this;
|
||||
let request = aStore.get(aId);
|
||||
request.onsuccess = function(aEvent) {
|
||||
debug("RemoveInternal success. Record: " + aEvent.target.result);
|
||||
if (aEvent.target.result === undefined) {
|
||||
aResolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let deleteRequest = aStore.delete(aId);
|
||||
deleteRequest.onsuccess = function() {
|
||||
debug("RemoveInternal success");
|
||||
self.addRevision(aRevisionStore, aId, REVISION_REMOVED,
|
||||
function() {
|
||||
aResolve(true);
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
clearInternal: function(aResolve, aStore, aRevisionStore) {
|
||||
debug("ClearInternal");
|
||||
|
||||
let self = this;
|
||||
let request = aStore.clear();
|
||||
request.onsuccess = function() {
|
||||
debug("ClearInternal success");
|
||||
self._db.clearRevisions(aRevisionStore,
|
||||
function() {
|
||||
debug("Revisions cleared");
|
||||
|
||||
self.addRevision(aRevisionStore, null, REVISION_VOID,
|
||||
function() {
|
||||
debug("ClearInternal - revisionId increased");
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
getLengthInternal: function(aResolve, aStore) {
|
||||
debug("GetLengthInternal");
|
||||
|
||||
let request = aStore.count();
|
||||
request.onsuccess = function(aEvent) {
|
||||
debug("GetLengthInternal success: " + aEvent.target.result);
|
||||
// No wrap here because the result is always a int.
|
||||
aResolve(aEvent.target.result);
|
||||
};
|
||||
},
|
||||
|
||||
addRevision: function(aRevisionStore, aId, aType, aSuccessCb) {
|
||||
let self = this;
|
||||
this._db.addRevision(aRevisionStore, aId, aType,
|
||||
function(aRevisionId) {
|
||||
self._revisionId = aRevisionId;
|
||||
self.sendNotification(aId, aType, aRevisionId);
|
||||
aSuccessCb();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
retrieveRevisionId: function(aSuccessCb) {
|
||||
let self = this;
|
||||
this._db.revisionTxn(
|
||||
'readonly',
|
||||
function(aTxn, aRevisionStore) {
|
||||
debug("RetrieveRevisionId transaction success");
|
||||
|
||||
let request = aRevisionStore.openCursor(null, 'prev');
|
||||
request.onsuccess = function(aEvent) {
|
||||
let cursor = aEvent.target.result;
|
||||
if (cursor) {
|
||||
self._revisionId = cursor.value.revisionId;
|
||||
}
|
||||
|
||||
aSuccessCb(self._revisionId);
|
||||
};
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
sendNotification: function(aId, aOperation, aRevisionId) {
|
||||
debug("SendNotification");
|
||||
if (aOperation == REVISION_VOID) {
|
||||
aOperation = "cleared";
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("DataStore:Changed",
|
||||
{ store: this.name, owner: this._owner,
|
||||
message: { revisionId: aRevisionId, id: aId,
|
||||
operation: aOperation, owner: this._owner } },
|
||||
null,
|
||||
this._window.document.nodePrincipal);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage");
|
||||
|
||||
if (aMessage.name != "DataStore:Changed:Return:OK") {
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
return;
|
||||
}
|
||||
|
||||
// If this message is not for this DataStore, let's ignore it.
|
||||
if (aMessage.data.owner != this._owner ||
|
||||
aMessage.data.store != this._name) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
this.retrieveRevisionId(
|
||||
function() {
|
||||
// If the window has been destroyed we don't emit the events.
|
||||
if (self._shuttingdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have an active cursor we don't emit events.
|
||||
if (self._cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
let event = new self._window.DataStoreChangeEvent('change',
|
||||
aMessage.data.message);
|
||||
self._eventTarget.dispatchEvent(event);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
get exposedObject() {
|
||||
debug("get exposedObject");
|
||||
return this._exposedObject;
|
||||
},
|
||||
|
||||
set exposedObject(aObject) {
|
||||
debug("set exposedObject");
|
||||
this._exposedObject = aObject;
|
||||
},
|
||||
|
||||
syncTerminated: function(aCursor) {
|
||||
// This checks is to avoid that an invalid cursor stops a sync.
|
||||
if (this._cursor == aCursor) {
|
||||
this._cursor = null;
|
||||
}
|
||||
},
|
||||
|
||||
// Public interface :
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
},
|
||||
|
||||
get owner() {
|
||||
return this._owner;
|
||||
},
|
||||
|
||||
get readOnly() {
|
||||
return this._readOnly;
|
||||
},
|
||||
|
||||
get: function() {
|
||||
let ids = Array.prototype.slice.call(arguments);
|
||||
for (let i = 0; i < ids.length; ++i) {
|
||||
if (!validateId(ids[i])) {
|
||||
return throwInvalidArg(this._window);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.length == 0) {
|
||||
return this._window.Promise.resolve(new this._window.Array());
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<Object>
|
||||
return this.newDBPromise("readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.getInternal(aStore, ids,
|
||||
function(aResults) {
|
||||
aResolve(ids.length > 1 ? aResults : aResults[0]);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
put: function(aObj, aId, aRevisionId) {
|
||||
if (!validateId(aId)) {
|
||||
return throwInvalidArg(this._window);
|
||||
}
|
||||
|
||||
if (this._readOnly) {
|
||||
return throwReadOnly(this._window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.newDBPromise("readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.checkRevision(aReject, aRevisionStore, aRevisionId, function() {
|
||||
self.putInternal(aResolve, aStore, aRevisionStore, aObj, aId);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
add: function(aObj, aId, aRevisionId) {
|
||||
if (aId) {
|
||||
if (!validateId(aId)) {
|
||||
return throwInvalidArg(this._window);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._readOnly) {
|
||||
return throwReadOnly(this._window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<int>
|
||||
return this.newDBPromise("readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.checkRevision(aReject, aRevisionStore, aRevisionId, function() {
|
||||
self.addInternal(aResolve, aStore, aRevisionStore, aObj, aId);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
remove: function(aId, aRevisionId) {
|
||||
if (!validateId(aId)) {
|
||||
return throwInvalidArg(this._window);
|
||||
}
|
||||
|
||||
if (this._readOnly) {
|
||||
return throwReadOnly(this._window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.newDBPromise("readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.checkRevision(aReject, aRevisionStore, aRevisionId, function() {
|
||||
self.removeInternal(aResolve, aStore, aRevisionStore, aId);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
clear: function(aRevisionId) {
|
||||
if (this._readOnly) {
|
||||
return throwReadOnly(this._window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.newDBPromise("readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.checkRevision(aReject, aRevisionStore, aRevisionId, function() {
|
||||
self.clearInternal(aResolve, aStore, aRevisionStore);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
get revisionId() {
|
||||
return this._revisionId;
|
||||
},
|
||||
|
||||
getLength: function() {
|
||||
let self = this;
|
||||
|
||||
// Promise<int>
|
||||
return this.newDBPromise("readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.getLengthInternal(aResolve, aStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
sync: function(aRevisionId) {
|
||||
debug("Sync");
|
||||
this._cursor = new DataStoreCursor(this._window, this, aRevisionId);
|
||||
|
||||
let cursorImpl = this._window.DataStoreCursorImpl.
|
||||
_create(this._window, this._cursor);
|
||||
|
||||
let exposedCursor = new this._window.DataStoreCursor();
|
||||
exposedCursor.setDataStoreCursorImpl(cursorImpl);
|
||||
return exposedCursor;
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStore]);
|
||||
@@ -1,100 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "DataStoreRevision.h"
|
||||
|
||||
#include "DataStoreCallbacks.h"
|
||||
#include "DataStoreService.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStore.h"
|
||||
#include "mozilla/dom/IDBRequest.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_ISUPPORTS(DataStoreRevision, nsIDOMEventListener)
|
||||
|
||||
// Note: this code in it must not assume anything about the compartment cx is
|
||||
// in.
|
||||
nsresult
|
||||
DataStoreRevision::AddRevision(JSContext* aCx,
|
||||
IDBObjectStore* aStore,
|
||||
uint32_t aObjectId,
|
||||
RevisionType aRevisionType,
|
||||
DataStoreRevisionCallback* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aStore);
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
RefPtr<DataStoreService> service = DataStoreService::Get();
|
||||
if (!service) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsString id;
|
||||
nsresult rv = service->GenerateUUID(mRevisionID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DataStoreRevisionData data;
|
||||
data.mRevisionId = mRevisionID;
|
||||
data.mObjectId = aObjectId;
|
||||
|
||||
switch (aRevisionType) {
|
||||
case RevisionVoid:
|
||||
data.mOperation = NS_LITERAL_STRING("void");
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("This should not happen");
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!ToJSValue(aCx, data, &value)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult error;
|
||||
mRequest = aStore->Put(aCx, value, JS::UndefinedHandleValue, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
|
||||
this, false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mCallback = aCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DataStoreRevision::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsString type;
|
||||
nsresult rv = aEvent->GetType(type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!type.EqualsASCII("success")) {
|
||||
MOZ_CRASH("This should not happen");
|
||||
}
|
||||
|
||||
mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false);
|
||||
mRequest = nullptr;
|
||||
|
||||
mCallback->Run(mRevisionID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -1,50 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_DataStoreRevision_h
|
||||
#define mozilla_dom_DataStoreRevision_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DataStoreRevisionCallback;
|
||||
class IDBObjectStore;
|
||||
class IDBRequest;
|
||||
|
||||
class DataStoreRevision final : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
enum RevisionType {
|
||||
RevisionVoid
|
||||
};
|
||||
|
||||
nsresult AddRevision(JSContext* aCx,
|
||||
IDBObjectStore* aStore,
|
||||
uint32_t aObjectId,
|
||||
RevisionType aRevisionType,
|
||||
DataStoreRevisionCallback* aCallback);
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override;
|
||||
|
||||
private:
|
||||
~DataStoreRevision() {}
|
||||
RefPtr<DataStoreRevisionCallback> mCallback;
|
||||
RefPtr<IDBRequest> mRequest;
|
||||
nsString mRevisionID;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DataStoreRevision_h
|
||||
@@ -1,50 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDataStore.idl',
|
||||
'nsIDataStoreService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_datastore'
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'DataStore.h',
|
||||
'DataStoreCursor.h',
|
||||
'DataStoreService.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DataStore.cpp',
|
||||
'DataStoreCursor.cpp',
|
||||
'DataStoreDB.cpp',
|
||||
'DataStoreRevision.cpp',
|
||||
'DataStoreService.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'DataStore.manifest',
|
||||
'DataStoreImpl.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'DataStoreChangeNotifier.jsm',
|
||||
'DataStoreCursorImpl.jsm',
|
||||
'DataStoreDB.jsm',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
@@ -1,55 +0,0 @@
|
||||
var gBasePath = "tests/dom/datastore/tests/";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
var testToken = '';
|
||||
if ('testToken' in query) {
|
||||
testToken = query.testToken;
|
||||
}
|
||||
|
||||
var template = 'file_app.template.webapp';
|
||||
if ('template' in query) {
|
||||
template = query.template;
|
||||
}
|
||||
var template = gBasePath + template;
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
|
||||
}
|
||||
|
||||
// Copy-pasted incantations. There ought to be a better way to synchronously read
|
||||
// a file into a string, but I guess we're trying to discourage that.
|
||||
function readTemplate(path) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
var split = path.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fis.init(file, -1, -1, false);
|
||||
cis.init(fis, "UTF-8", 0, 0);
|
||||
|
||||
var data = "";
|
||||
let str = {};
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "Really Rapid Release (hosted)",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-owned" : {
|
||||
"foo" : { "access": "readwrite", "description" : "This store is called foo" },
|
||||
"bar" : { "access": "readonly", "description" : "This store is called bar" }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "Really Rapid Release (hosted) - app 2",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" },
|
||||
"bar" : { "readonly": true, "description" : "This store is called bar" }
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - install/uninstall apps</title>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_app_install.html';
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Get datastore with name 'foo'
|
||||
function() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
ok(stores[0].owner, 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
runTest();
|
||||
}, cbError);
|
||||
},
|
||||
|
||||
// Get datastore with name 'bar'
|
||||
function() {
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
ok(stores[0].owner, 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore bar is in readonly');
|
||||
runTest();
|
||||
}, cbError);
|
||||
},
|
||||
|
||||
// Get datastore with name 'foo' and a specified owner
|
||||
function() {
|
||||
navigator.getDataStores('foo', gHostedManifestURL).then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo','" + gHostedManifestURL +
|
||||
"') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
ok(stores[0].owner, 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
runTest();
|
||||
}, cbError);
|
||||
},
|
||||
|
||||
// Get datastore with name 'foo' and an arbitrary non-existent owner
|
||||
function() {
|
||||
navigator.getDataStores('foo', 'non-existent').then(function(stores) {
|
||||
is(stores.length, 0, "getDataStores('foo','non-existent') returns 0 element");
|
||||
runTest();
|
||||
}, cbError);
|
||||
},
|
||||
|
||||
// Get datastore with an arbitrary non-existent name
|
||||
function() {
|
||||
navigator.getDataStores('non-existent').then(function(stores) {
|
||||
is(stores.length, 0, "getDataStores('non-existent') returns 0 element");
|
||||
runTest();
|
||||
}, cbError);
|
||||
},
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</html>
|
||||
@@ -1,110 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - add([array]) remove([array])</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("put" in store, "store.put exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
var itemNumber = 60;
|
||||
|
||||
function testStoreAdd() {
|
||||
var objects = [];
|
||||
for (var i = 0; i < itemNumber; ++i) {
|
||||
objects.push(i);
|
||||
}
|
||||
|
||||
function testStoreAddInternal() {
|
||||
if (!objects.length) {
|
||||
ok(true, "We inserted " + itemNumber + " items");
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = objects.shift();
|
||||
gStore.add(obj).then(function() {
|
||||
ok(true, "We inserted a new item!");
|
||||
testStoreAddInternal();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
testStoreAddInternal();
|
||||
}
|
||||
|
||||
function testStoreGet() {
|
||||
var objects = [];
|
||||
for (var i = 1; i <= itemNumber; ++i) {
|
||||
objects.push(i);
|
||||
}
|
||||
|
||||
gStore.get.apply(gStore, objects).then(function(data) {
|
||||
is(data.length, objects.length, "Get - Data matches");
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
is(data[i], objects[i] - 1, "Get - Data matches: " + i + " " + data[i] + " == " + objects[i]);
|
||||
}
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Add many items
|
||||
function() { testStoreAdd() },
|
||||
function() { testStoreGet() },
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
<script type="text/javascript" src="file_basic_common.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,119 +0,0 @@
|
||||
var gStore;
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("put" in store, "store.put exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
ok("revisionId" in store, "store.revisionId exists");
|
||||
ok("getLength" in store, "store.getLength exists");
|
||||
ok("sync" in store, "store.sync exists");
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreGet(id, value) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(true, "store.get() retrieves data");
|
||||
is(what, value, "store.get(" + id + ") returns " + value);
|
||||
}, function() {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value) {
|
||||
return gStore.add(value).then(function(what) {
|
||||
ok(true, "store.add() is called");
|
||||
ok(what > 0, "store.add() returns something");
|
||||
return what;
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStorePut(value, id) {
|
||||
return gStore.put(value, id).then(function() {
|
||||
ok(true, "store.put() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreGetLength(number) {
|
||||
return gStore.getLength().then(function(n) {
|
||||
is(number, n, "store.getLength() returns the right number");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id) {
|
||||
return gStore.remove(id).then(function() {
|
||||
ok(true, "store.remove() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreClear() {
|
||||
return gStore.clear().then(function() {
|
||||
ok(true, "store.clear() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Unknown ID
|
||||
function() { testStoreGet(42, undefined); },
|
||||
function() { testStoreGet(42, undefined); }, // twice
|
||||
|
||||
// Add + Get - number
|
||||
function() { testStoreAdd(42).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, 42); },
|
||||
|
||||
// Add + Get - boolean
|
||||
function() { testStoreAdd(true).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, true); },
|
||||
|
||||
// Add + Get - string
|
||||
function() { testStoreAdd("hello world").then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world"); },
|
||||
|
||||
// Put + Get - string
|
||||
function() { testStorePut("hello world 2", gId).then(function() {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world 2"); },
|
||||
|
||||
// getLength
|
||||
function() { testStoreGetLength(3).then(function() { runTest(); }, cbError); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, undefined); },
|
||||
|
||||
// Remove - wrong ID
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Clear
|
||||
function() { testStoreClear().then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var messages = [];
|
||||
var worker = new Worker("file_basic_worker.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
messages.push(event.data)
|
||||
|
||||
if (event.data == 'DONE') {
|
||||
// Free the worker when all the tests are done.
|
||||
worker.terminate();
|
||||
|
||||
// Fire message to the test_basic_worker.html.
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
alert(messages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
function is(a, b, msg) {
|
||||
postMessage((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
postMessage((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
postMessage('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
postMessage('DONE');
|
||||
}
|
||||
|
||||
importScripts("file_basic_common.js");
|
||||
|
||||
runTest();
|
||||
@@ -1,46 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - bug 1008044</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((!!a ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
if (stores[0].name != 'foo') {
|
||||
ok(false, "Wrong name is received! Expected 'foo'");
|
||||
}
|
||||
runTest();
|
||||
});
|
||||
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
if (stores[0].name != 'bar') {
|
||||
ok(false, "Wrong name is received! Expected 'bar'");
|
||||
}
|
||||
runTest();
|
||||
});
|
||||
|
||||
var pending = 2;
|
||||
function runTest() {
|
||||
if (--pending == 0) {
|
||||
ok(true, "Test passed!");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,40 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
<script type="text/javascript" src="file_basic_common.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
store.get.apply(store, []).then(function(a) {
|
||||
ok(Array.isArray(a), "bug 1058108");
|
||||
is(a.length, 0, "bug 1058108");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for bug 924104</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testBug924104() {
|
||||
gStore
|
||||
.add({})
|
||||
.then(
|
||||
function(index) {
|
||||
ok(index, "store.add() created item" + index);
|
||||
return gStore.get(index);
|
||||
},
|
||||
cbError)
|
||||
.then(
|
||||
function(obj) {
|
||||
ok(true, "store.get() works");
|
||||
var status = false;
|
||||
try {
|
||||
obj['foobar'] = 42;
|
||||
status = true;
|
||||
} catch(e) {}
|
||||
ok(status, "Object is editable");
|
||||
runTest();
|
||||
},
|
||||
cbError);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
testGetDataStores,
|
||||
testBug924104
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,34 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - bug 1008044</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a == b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is (stores.length, 1, "Correct number of Stores");
|
||||
is (stores[0].name, 'foo', "Correct name is received!");
|
||||
stores[0].get(42).then(function(something) {
|
||||
is (something, null, "Correct value");
|
||||
finish();
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - bug 976311 app1</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStores = [];
|
||||
var expectedWhere;
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function checkEvent(id) {
|
||||
is(expectedWhere, id, "Message on the correct DS: " + id + " " + expectedWhere);
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 2, "getDataStores('foo') returns 1 element");
|
||||
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
stores[0].onchange = function(evt) { checkEvent(0); }
|
||||
gStores.push(stores[0]);
|
||||
|
||||
is(stores[1].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[1].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
stores[1].onchange = function(evt) { checkEvent(1); }
|
||||
gStores.push(stores[1]);
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(where, value) {
|
||||
expectedWhere = where;
|
||||
dump("ADD TO: " + gStores[where].owner + "\n");
|
||||
gStores[where].add({ a: value });
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
function() { testStoreAdd(0, 1); },
|
||||
function() { testStoreAdd(1, 2); },
|
||||
function() { testStoreAdd(0, 3); },
|
||||
function() { testStoreAdd(1, 4); }
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "Really Rapid Release (hosted)",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-owned" : {
|
||||
"foo" : { "access": "readwrite", "description" : "This store is called foo" }
|
||||
},
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" }
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - bug 986056 app</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
alert("OK " + stores.length);
|
||||
}, cbError);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "Really Rapid Release (hosted)",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-owned" : {
|
||||
"foo" : { "access": "readwrite", "description" : "This store is called foo" }
|
||||
},
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" }
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore just for certified Apps</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
ok(!("DataStore" in window), "DataStore is not an available interface");
|
||||
ok(!("DataStoreChangeEvent" in window), "DataStore is not an available interface");
|
||||
ok(!("getDataStores" in navigator), "DataStore not available");
|
||||
finish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,148 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
var gChangeId = null;
|
||||
var gChangeOperation = null;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value, expectedId) {
|
||||
gStore.add(value).then(function(id) {
|
||||
is(id, expectedId, "store.add() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStorePut(value, id) {
|
||||
gStore.put(value, id).then(function(retId) {
|
||||
is(id, retId, "store.put() is called with the right id");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id, expectedSuccess) {
|
||||
gStore.remove(id).then(function(success) {
|
||||
is(success, expectedSuccess, "store.remove() returns the right value");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreClear() {
|
||||
gStore.clear().catch(cbError);
|
||||
}
|
||||
|
||||
function eventListener(evt) {
|
||||
ok(evt instanceof DataStoreChangeEvent, "DataStoreChangeEvent has been received");
|
||||
ok(evt, "OnChangeListener is called with data");
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(evt.revisionId), true, "event.revisionId returns something");
|
||||
is(evt.id, gChangeId, "OnChangeListener is called with the right ID: " + evt.id);
|
||||
is(evt.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + evt.operation + " " + gChangeOperation);
|
||||
runTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Add onchange = function
|
||||
function() {
|
||||
gStore.onchange = eventListener;
|
||||
is(gStore.onchange, eventListener, "onChange is set");
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Add
|
||||
function() { gChangeId = 1; gChangeOperation = 'added';
|
||||
testStoreAdd({ number: 42 }, 1); },
|
||||
|
||||
// Put
|
||||
function() { gChangeId = 1; gChangeOperation = 'updated';
|
||||
testStorePut({ number: 43 }, 1); },
|
||||
|
||||
// Remove
|
||||
function() { gChangeId = 1; gChangeOperation = 'removed';
|
||||
testStoreRemove(1, true); },
|
||||
|
||||
// Clear
|
||||
function() { gChangeId = null; gChangeOperation = 'cleared';
|
||||
testStoreClear(); },
|
||||
|
||||
// Remove onchange function and replace it with addEventListener
|
||||
function() {
|
||||
gStore.onchange = null;
|
||||
gStore.addEventListener('change', eventListener);
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Add
|
||||
function() { gChangeId = 2; gChangeOperation = 'added';
|
||||
testStoreAdd({ number: 42 }, 2); },
|
||||
|
||||
// Put
|
||||
function() { gChangeId = 2; gChangeOperation = 'updated';
|
||||
testStorePut({ number: 43 }, 2); },
|
||||
|
||||
// Remove
|
||||
function() { gChangeId = 2; gChangeOperation = 'removed';
|
||||
testStoreRemove(2, true); },
|
||||
|
||||
// Clear
|
||||
function() { gChangeId = null; gChangeOperation = 'cleared';
|
||||
testStoreClear(); },
|
||||
|
||||
// Remove event listener
|
||||
function() {
|
||||
gStore.removeEventListener('change', eventListener);
|
||||
runTest();
|
||||
},
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,51 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function eventListener(obj) {
|
||||
ok(obj, "OnChangeListener is called with data");
|
||||
ok("revisionId" in obj, "the event contains a revisionId");
|
||||
ok("id" in obj, "the event contains a id");
|
||||
ok("operation" in obj, "the event contains a operation");
|
||||
ok("owner" in obj, "the event contains a owner");
|
||||
is(obj.owner, 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_changes.html', 'Owner matches');
|
||||
finish();
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
|
||||
stores[0].onchange = eventListener;
|
||||
alert('READY');
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,75 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - duplicate keys</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
var gEvent;
|
||||
var gChangeId;
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testAdd(success) {
|
||||
gStore.add({ a: 42 }, 'test').then(function() {
|
||||
is(success, true, "Record added");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
is(success, false, "Record failed");
|
||||
ok(e instanceof DOMError, "DOMError received");
|
||||
is(e.name, 'ConstraintError', 'e.name: ConstraintError');
|
||||
is(e.message, '', 'e.message');
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// add
|
||||
function() { testAdd(true); },
|
||||
|
||||
// add duplicate
|
||||
function() { testAdd(false); }
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - event maker</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
stores[0].add({a: 42}).then(finish, cbError);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - event receiver</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function eventListener(evt) {
|
||||
ok(evt, "OnChangeListener is called with data");
|
||||
finish();
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
store.onchange = eventListener;
|
||||
alert("READY");
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - string or unsigned long keys</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
var gEvent;
|
||||
var gChangeId;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testAdd_noKey(key) {
|
||||
gEvent = 'added';
|
||||
gChangeId = key;
|
||||
|
||||
gStore.add({ a: 42 }).then(function(id) {
|
||||
is(id, key, "Id must be " + key + " received: " + id);
|
||||
});
|
||||
}
|
||||
|
||||
function testAdd_withKey(key) {
|
||||
gEvent = 'added';
|
||||
gChangeId = key;
|
||||
|
||||
gStore.add({ a: 42 }, key).then(function(id) {
|
||||
is(id, key, "Id must be " + key + " received: " + id);
|
||||
});
|
||||
}
|
||||
|
||||
function testPut(key) {
|
||||
gEvent = 'updated';
|
||||
gChangeId = key;
|
||||
|
||||
gStore.put({ a: 42 }, key).then(function(id) {
|
||||
is(id, key, "Id must be " + key + " received: " + id);
|
||||
});
|
||||
}
|
||||
|
||||
function testGet(key) {
|
||||
gStore.get(key).then(function(value) {
|
||||
ok(value, "Object received!");
|
||||
is(value.a, 42, "Object received with right value!");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function testArrayGet(key) {
|
||||
gStore.get.apply(gStore, key).then(function(values) {
|
||||
is(values.length, key.length, "Object received!");
|
||||
for (var i = 0; i < values.length; ++i) {
|
||||
is(values[i].a, 42, "Object received with right value!");
|
||||
}
|
||||
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function testRemove(key, success) {
|
||||
gEvent = 'removed';
|
||||
gChangeId = key;
|
||||
|
||||
gStore.remove(key).then(function(value) {
|
||||
is(value, success, "Status must be " + success + " received: " + value);
|
||||
if (value == false) {
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function eventListener() {
|
||||
gStore.onchange = function(e) {
|
||||
is(e.operation, gEvent, "Operation matches: " + e.operation + " " + gEvent);
|
||||
ok(e.id === gChangeId, "Operation id matches");
|
||||
runTest();
|
||||
};
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Event listener
|
||||
eventListener,
|
||||
|
||||
// add
|
||||
function() { testAdd_noKey(1); },
|
||||
function() { testAdd_withKey(123); },
|
||||
function() { testAdd_noKey(124); },
|
||||
function() { testAdd_withKey('foobar'); },
|
||||
function() { testAdd_noKey(125); },
|
||||
function() { testAdd_withKey('125'); },
|
||||
function() { testAdd_withKey('126'); },
|
||||
function() { testAdd_noKey(126); },
|
||||
|
||||
// put
|
||||
function() { testPut(42); },
|
||||
function() { testPut('42'); },
|
||||
|
||||
// get
|
||||
function() { testGet('42'); },
|
||||
function() { testGet(42); },
|
||||
function() { testGet(1); },
|
||||
function() { testGet(123); },
|
||||
function() { testGet(124); },
|
||||
function() { testGet('foobar'); },
|
||||
function() { testGet(125); },
|
||||
function() { testGet('125'); },
|
||||
function() { testGet('126'); },
|
||||
function() { testGet(126); },
|
||||
function() { testArrayGet(['42', 42, 1, 123, 124, 'foobar', 125, '125', '126', 126]); },
|
||||
|
||||
// remove
|
||||
function() { testRemove(42, true); },
|
||||
function() { testRemove('42', true); },
|
||||
function() { testRemove('43', false); },
|
||||
function() { testRemove(43, false); },
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,120 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - notify updates with system messages</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
var gChangeId = null;
|
||||
var gChangeOperation = null;
|
||||
var gIsSystemMessageFired = false;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value, expectedId) {
|
||||
gStore.add(value).then(function(id) {
|
||||
is(id, expectedId, "store.add() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function eventListener(evt) {
|
||||
ok(evt instanceof DataStoreChangeEvent, "DataStoreChangeEvent has been received");
|
||||
ok(evt, "OnChangeListener is called with data");
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(evt.revisionId), true, "event.revisionId returns something");
|
||||
is(evt.id, gChangeId, "OnChangeListener is called with the right ID: " + evt.id);
|
||||
is(evt.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + evt.operation + " " + gChangeOperation);
|
||||
runTest();
|
||||
}
|
||||
|
||||
function onDatastoreUpdateFoo(message) {
|
||||
gIsSystemMessageFired = true;
|
||||
ok(true, "System message 'datastore-update-foo' has been received");
|
||||
runTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore.
|
||||
testGetDataStores,
|
||||
|
||||
// Add onchange = function.
|
||||
function() {
|
||||
gStore.onchange = eventListener;
|
||||
is(gStore.onchange, eventListener, "onChange is set");
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Set system message handler.
|
||||
function() {
|
||||
navigator.mozSetMessageHandler('datastore-update-foo', onDatastoreUpdateFoo);
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Add.
|
||||
function() { gChangeId = 1; gChangeOperation = 'added';
|
||||
testStoreAdd({ number: 42 }, 1); },
|
||||
|
||||
// Remove event listener.
|
||||
function() {
|
||||
gStore.removeEventListener('change', eventListener);
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Ensure the system message has fired and no more pending ones.
|
||||
function() {
|
||||
// Periodically check whether the system message has fired.
|
||||
var timer = setInterval(function() {
|
||||
if (gIsSystemMessageFired) {
|
||||
clearInterval(timer);
|
||||
ok(true, "The system message has fired");
|
||||
ok(!navigator.mozHasPendingMessage('datastore-update-foo'), "No more pending system message");
|
||||
finish();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (tests.length) {
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,72 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
dump((a === b ? 'OK' : 'KO') + ' ' + msg + "\n")
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
is(stores[0].readOnly, true, 'The dataStore bar is eadonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("put" in store, "store.put exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
|
||||
var f = store.clear();
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.clear() fails because the db is readonly");
|
||||
return store.remove(123);
|
||||
});
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.remove() fails because the db is readonly");
|
||||
return store.add(123, true);
|
||||
});
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.add() fails because the db is readonly");
|
||||
return store.put({}, 123);
|
||||
})
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.put() fails because the db is readonly");
|
||||
})
|
||||
|
||||
f.then(function() {
|
||||
// All done.
|
||||
ok(true, "All done");
|
||||
finish();
|
||||
});
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - sync</title>
|
||||
<script type="text/javascript" src="file_sync_common.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,461 +0,0 @@
|
||||
var gStore;
|
||||
var gRevisions = [];
|
||||
var gCursor;
|
||||
var gExpectedEvents = true;
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
|
||||
gStore = stores[0];
|
||||
gRevisions.push(gStore.revisionId);
|
||||
|
||||
gStore.onchange = function(aEvent) {
|
||||
ok(gExpectedEvents, "Events received!");
|
||||
runTest();
|
||||
}
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testBasicInterface() {
|
||||
var cursor = gStore.sync();
|
||||
ok(cursor, "Cursor is created");
|
||||
is(cursor.store, gStore, "Cursor.store is the store");
|
||||
|
||||
ok("next" in cursor, "Cursor.next exists");
|
||||
ok("close" in cursor, "Cursor.close exists");
|
||||
|
||||
cursor.close();
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testCursor(cursor, steps) {
|
||||
if (!steps.length) {
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
|
||||
var step = steps.shift();
|
||||
cursor.next().then(function(data) {
|
||||
ok(!!data, "Cursor.next returns data");
|
||||
is(data.operation, step.operation, "Waiting for operation: '" + step.operation + "' received '" + data.operation + "'");
|
||||
|
||||
|
||||
switch (data.operation) {
|
||||
case 'clear':
|
||||
is (data.id, null, "'clear' operation wants a null id");
|
||||
break;
|
||||
|
||||
case 'done':
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(data.revisionId), true, "done has a valid revisionId");
|
||||
is (data.revisionId, gRevisions[gRevisions.length-1], "Last revision matches");
|
||||
is (data.id, null, "'done' operation wants a null id");
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
case 'update':
|
||||
if ('id' in step) {
|
||||
is(data.id, step.id, "next() add: id matches: " + data.id + " " + step.id);
|
||||
}
|
||||
|
||||
if ('data' in step) {
|
||||
is(data.data, step.data, "next() add: data matches: " + data.data + " " + step.data);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
if ('id' in step) {
|
||||
is(data.id, step.id, "next() add: id matches: " + data.id + " " + step.id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
testCursor(cursor, steps);
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// interface test
|
||||
testBasicInterface,
|
||||
|
||||
// empty DataStore
|
||||
function() {
|
||||
var cursor = gStore.sync();
|
||||
var steps = [ { operation: 'clear' },
|
||||
{ operation: 'done' },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gExpectedEvents = false;
|
||||
var cursor = gStore.sync('wrong revision ID');
|
||||
var steps = [ { operation: 'clear' },
|
||||
{ operation: 'done' },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[0]);
|
||||
var steps = [ { operation: 'done' },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
// Test add from scratch
|
||||
function() {
|
||||
gExpectedEvents = true;
|
||||
|
||||
gStore.add(1).then(function(id) {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
ok(true, "Item: " + id + " added");
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(2,"foobar").then(function(id) {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
ok(true, "Item: " + id + " added");
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(3,3).then(function(id) {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
ok(true, "Item: " + id + " added");
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gExpectedEvents = false;
|
||||
var cursor = gStore.sync();
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 1 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync('wrong revision ID');
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 1 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[0]);
|
||||
var steps = [ { operation: 'add', id: 1, data: 1 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[1]);
|
||||
var steps = [ { operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[2]);
|
||||
var steps = [ { operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[3]);
|
||||
var steps = [ { operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
// Test after an update
|
||||
function() {
|
||||
gExpectedEvents = true;
|
||||
gStore.put(123, 1).then(function() {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gExpectedEvents = false;
|
||||
var cursor = gStore.sync();
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync('wrong revision ID');
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[0]);
|
||||
var steps = [ { operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[1]);
|
||||
var steps = [ { operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[2]);
|
||||
var steps = [ { operation: 'add', id: 3, data: 3 },
|
||||
{ operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[3]);
|
||||
var steps = [ { operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[4]);
|
||||
var steps = [ { operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
// Test after a remove
|
||||
function() {
|
||||
gExpectedEvents = true;
|
||||
gStore.remove(3).then(function() {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gExpectedEvents = false;
|
||||
var cursor = gStore.sync();
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync('wrong revision ID');
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[0]);
|
||||
var steps = [ { operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[1]);
|
||||
var steps = [ { operation: 'add', id: 'foobar', data: 2 },
|
||||
{ operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[2]);
|
||||
var steps = [ { operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[3]);
|
||||
var steps = [ { operation: 'update', id: 1, data: 123 },
|
||||
{ operation: 'remove', id: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[4]);
|
||||
var steps = [ { operation: 'remove', id: 3 },
|
||||
{ operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
var cursor = gStore.sync(gRevisions[5]);
|
||||
var steps = [ { operation: 'done' }];
|
||||
testCursor(cursor, steps);
|
||||
},
|
||||
|
||||
// New events when the cursor is active
|
||||
function() {
|
||||
gCursor = gStore.sync();
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 } ];
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(42, 2).then(function(id) {
|
||||
ok(true, "Item: " + id + " added");
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 2, data: 42 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 } ]
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.put(43, 2).then(function(id) {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 2, data: 43 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 } ]
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.remove(2).then(function(id) {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 } ]
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(42).then(function(id) {
|
||||
ok(true, "Item: " + id + " added");
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 1, data: 123 },
|
||||
{ operation: 'add', id: 4, data: 42 },
|
||||
{ operation: 'add', id: 'foobar', data: 2 } ]
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.clear().then(function() {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear' } ];
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(42).then(function(id) {
|
||||
ok(true, "Item: " + id + " added");
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear', },
|
||||
{ operation: 'add', id: 5, data: 42 } ];
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.clear().then(function() {
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
gStore.add(42).then(function(id) {
|
||||
ok(true, "Item: " + id + " added");
|
||||
gRevisions.push(gStore.revisionId);
|
||||
runTest();
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
var steps = [ { operation: 'clear' },
|
||||
{ operation: 'add', id: 6, data: 42 },
|
||||
{ operation: 'done'} ];
|
||||
testCursor(gCursor, steps);
|
||||
},
|
||||
|
||||
function() {
|
||||
gExpectedEvents = true;
|
||||
gStore.add(42).then(function(id) {
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - sync</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var messages = [];
|
||||
var worker = new Worker("file_sync_worker.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
messages.push(event.data)
|
||||
|
||||
if (event.data == 'DONE') {
|
||||
// Free the worker when all the tests are done.
|
||||
worker.terminate();
|
||||
|
||||
// Fire message to the test_sync_worker.html.
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
alert(messages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
function is(a, b, msg) {
|
||||
postMessage((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
postMessage((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
postMessage('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
postMessage('DONE');
|
||||
}
|
||||
|
||||
importScripts("file_sync_common.js");
|
||||
|
||||
runTest();
|
||||
@@ -1,129 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - transactional semantics</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function checkError(e) {
|
||||
ok(e instanceof DOMError, "Expecting a DOMError");
|
||||
is(e.name, "ConstraintError", "DOMError.name must be ConstraintError");
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Add
|
||||
function() { gStore.add("data", null, 'foobar').catch(function(e) {
|
||||
ok(true, "Add rejects when the revision is wrong");
|
||||
checkError(e); runTest(); }); },
|
||||
|
||||
function() { gStore.add("data").then(function() {
|
||||
ok(true, "Add succeeded without revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.add("data", null, gStore.revisionId).then(function() {
|
||||
ok(true, "Add succeeded with the correct revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.add("data", 42, 'foobar').catch(function(e) {
|
||||
ok(true, "Add rejects when the revision is wrong");
|
||||
checkError(e); runTest(); }); },
|
||||
|
||||
function() { gStore.add("data", 42).then(function() {
|
||||
ok(true, "Add succeeded without revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.add("data", 43, gStore.revisionId).then(function() {
|
||||
ok(true, "Add succeeded with the correct revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Put
|
||||
function() { gStore.put("data", 42, 'foobar').catch(function(e) {
|
||||
ok(true, "Put rejects when the revision is wrong");
|
||||
checkError(e); runTest(); }); },
|
||||
|
||||
function() { gStore.put("data", 42).then(function() {
|
||||
ok(true, "Put succeeded without revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.put("data", 42, gStore.revisionId).then(function() {
|
||||
ok(true, "Put succeeded with the correct revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Remove
|
||||
function() { gStore.remove(42, 'foobar').catch(function(e) {
|
||||
ok(true, "Remove rejects when the revision is wrong");
|
||||
checkError(e); runTest(); }); },
|
||||
|
||||
function() { gStore.remove(42).then(function() {
|
||||
ok(true, "Remove succeeded without revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.remove(42, gStore.revisionId).then(function() {
|
||||
ok(true, "Remove succeeded with the correct revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Clear
|
||||
function() { gStore.clear('foobar').catch(function(e) {
|
||||
ok(true, "Clear rejects when the revision is wrong");
|
||||
checkError(e); runTest(); }); },
|
||||
|
||||
function() { gStore.clear().then(function() {
|
||||
ok(true, "Clear succeeded without revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
function() { gStore.clear(gStore.revisionId).then(function() {
|
||||
ok(true, "Clear succeeded with the correct revisionId");
|
||||
runTest(); }, cbError); },
|
||||
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var messages = [];
|
||||
var worker = new Worker("file_worker_close.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
messages.push(event.data)
|
||||
|
||||
if (event.data == 'DONE') {
|
||||
worker.terminate();
|
||||
|
||||
// Fire message to the test_basic_worker.html.
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
alert(messages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
function is(a, b, msg) {
|
||||
postMessage((a == b ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
var store;
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
store = stores[0];
|
||||
postMessage('DONE');
|
||||
});
|
||||
|
||||
onclose = function() {
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
store.get(123);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
[DEFAULT]
|
||||
skip-if = (buildapp != 'b2g' && buildapp != 'mulet')
|
||||
support-files =
|
||||
file_app_install.html
|
||||
file_readonly.html
|
||||
file_basic.html
|
||||
file_basic_worker.html
|
||||
file_basic_worker.js
|
||||
file_changes.html
|
||||
file_changes2.html
|
||||
file_app.sjs
|
||||
file_app.template.webapp
|
||||
file_app2.template.webapp
|
||||
file_arrays.html
|
||||
file_sync.html
|
||||
file_sync_worker.html
|
||||
file_sync_worker.js
|
||||
file_bug924104.html
|
||||
file_certifiedApp.html
|
||||
file_keys.html
|
||||
file_duplicate.html
|
||||
file_bug976311.html
|
||||
file_bug976311.template.webapp
|
||||
file_bug986056.html
|
||||
file_bug986056.template.webapp
|
||||
file_bug1058108.html
|
||||
file_event_maker.html
|
||||
file_event_receiver.html
|
||||
file_transactions.html
|
||||
file_basic_common.js
|
||||
file_sync_common.js
|
||||
file_bug1008044.html
|
||||
file_bug957086.html
|
||||
file_notify_system_message.html
|
||||
file_worker_close.html
|
||||
file_worker_close.js
|
||||
|
||||
[test_app_install.html]
|
||||
skip-if = toolkit == 'gonk' # embed-apps doesn't work in the mochitest app
|
||||
[test_readonly.html]
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
|
||||
[test_basic.html]
|
||||
[test_basic_worker.html]
|
||||
[test_changes.html]
|
||||
[test_arrays.html]
|
||||
[test_oop.html]
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
|
||||
[test_sync.html]
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
|
||||
[test_sync_worker.html]
|
||||
[test_bug924104.html]
|
||||
[test_certifiedApp.html]
|
||||
[test_keys.html]
|
||||
[test_duplicate.html]
|
||||
[test_bug976311.html]
|
||||
[test_bug986056.html]
|
||||
[test_oop_events.html]
|
||||
[test_transactions.html]
|
||||
[test_bug1008044.html]
|
||||
[test_bug957086.html]
|
||||
[test_bug1058108.html]
|
||||
[test_notify_system_message.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || toolkit == 'win' #bug 1053662 - Timeout prone
|
||||
[test_worker_close.html]
|
||||
@@ -1,128 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - sync</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_sync.html';
|
||||
var gApp;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
gApp = request.result;
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
|
||||
},
|
||||
|
||||
// Preferences
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
|
||||
["dom.datastore.sysMsgOnChangeShortTimeoutSec", 1],
|
||||
["dom.datastore.sysMsgOnChangeLongTimeoutSec", 3],
|
||||
["dom.testing.ignore_ipc_principal", true],
|
||||
["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set":[["dom.mozBrowserFramesEnabled", true]]}, runTest);
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,128 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - sync</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_sync_worker.html';
|
||||
var gApp;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
gApp = request.result;
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
|
||||
},
|
||||
|
||||
// Preferences
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
|
||||
["dom.datastore.sysMsgOnChangeShortTimeoutSec", 1],
|
||||
["dom.datastore.sysMsgOnChangeLongTimeoutSec", 3],
|
||||
["dom.testing.ignore_ipc_principal", true],
|
||||
["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set":[["dom.mozBrowserFramesEnabled", true]]}, runTest)
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -188,10 +188,6 @@ const kEventConstructors = {
|
||||
return e;
|
||||
},
|
||||
},
|
||||
DataStoreChangeEvent: { create: function (aName, aProps) {
|
||||
return new DataStoreChangeEvent(aProps);
|
||||
},
|
||||
},
|
||||
DeviceLightEvent: { create: function (aName, aProps) {
|
||||
return new DeviceLightEvent(aName, aProps);
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
BEGIN_FMRADIO_NAMESPACE
|
||||
|
||||
class FMRadioReplyRunnable : public nsRunnable
|
||||
class FMRadioReplyRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
FMRadioReplyRunnable() : mResponseType(SuccessResponse()) {}
|
||||
|
||||
@@ -208,31 +208,6 @@ IDBFactory::CreateForMainThreadJS(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::CreateForDatastore(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
IDBFactory** aFactory)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// There should be a null principal pushed here, but it's still chrome...
|
||||
MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsAutoPtr<PrincipalInfo> principalInfo(
|
||||
new PrincipalInfo(SystemPrincipalInfo()));
|
||||
|
||||
nsresult rv =
|
||||
CreateForMainThreadJSInternal(aCx, aOwningObject, principalInfo, aFactory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!principalInfo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::CreateForWorker(JSContext* aCx,
|
||||
|
||||
@@ -90,11 +90,6 @@ public:
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static nsresult
|
||||
CreateForDatastore(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static nsresult
|
||||
CreateForWorker(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
|
||||
@@ -95,9 +95,4 @@ interface nsIAppsService : nsISupports
|
||||
* Available only in the parent process.
|
||||
*/
|
||||
bool isExtensionResource(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Reads the manifest file for this app and update the DataStore map
|
||||
*/
|
||||
void updateDataStoreEntriesFromLocalId(in unsigned long localId);
|
||||
};
|
||||
|
||||
@@ -191,7 +191,6 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "DomainPolicy.h"
|
||||
#include "mozilla/dom/DataStoreService.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#include "mozilla/dom/telephony/PTelephonyChild.h"
|
||||
#include "mozilla/dom/time/DateCacheCleaner.h"
|
||||
@@ -1187,24 +1186,6 @@ NS_IMETHODIMP MemoryReportRequestChild::Run()
|
||||
finished, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvDataStoreNotify(const uint32_t& aAppId,
|
||||
const nsString& aName,
|
||||
const nsString& aManifestURL)
|
||||
{
|
||||
RefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
|
||||
if (NS_WARN_IF(!service)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = service->EnableDataStore(aAppId, aName, aManifestURL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
|
||||
{
|
||||
|
||||
@@ -250,10 +250,6 @@ public:
|
||||
const FileDescriptor& aGCLog,
|
||||
const FileDescriptor& aCCLog) override;
|
||||
|
||||
virtual bool
|
||||
RecvDataStoreNotify(const uint32_t& aAppId, const nsString& aName,
|
||||
const nsString& aManifestURL) override;
|
||||
|
||||
virtual PTestShellChild* AllocPTestShellChild() override;
|
||||
|
||||
virtual bool DeallocPTestShellChild(PTestShellChild*) override;
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "mozilla/DataStorage.h"
|
||||
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
|
||||
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
|
||||
#include "mozilla/dom/DataStoreService.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "mozilla/dom/DOMStorageIPC.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@@ -2290,7 +2289,6 @@ ContentParent::InitializeMembers()
|
||||
mIsAlive = true;
|
||||
mMetamorphosed = false;
|
||||
mSendPermissionUpdates = false;
|
||||
mSendDataStoreInfos = false;
|
||||
mCalledClose = false;
|
||||
mCalledCloseWithError = false;
|
||||
mCalledKillHard = false;
|
||||
@@ -2945,27 +2943,6 @@ ContentParent::RecvAudioChannelServiceStatus(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvDataStoreGetStores(
|
||||
const nsString& aName,
|
||||
const nsString& aOwner,
|
||||
const IPC::Principal& aPrincipal,
|
||||
InfallibleTArray<DataStoreSetting>* aValue)
|
||||
{
|
||||
RefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
|
||||
if (NS_WARN_IF(!service)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = service->GetDataStoresFromIPC(aName, aOwner, aPrincipal, aValue);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mSendDataStoreInfos = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::ForkNewProcess(bool aBlocking)
|
||||
{
|
||||
|
||||
@@ -328,11 +328,6 @@ public:
|
||||
return mSendPermissionUpdates;
|
||||
}
|
||||
|
||||
bool NeedsDataStoreInfos() const
|
||||
{
|
||||
return mSendDataStoreInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill our subprocess and make sure it dies. Should only be used
|
||||
* in emergency situations since it bypasses the normal shutdown
|
||||
@@ -980,12 +975,6 @@ private:
|
||||
|
||||
virtual bool RecvGetLookAndFeelCache(nsTArray<LookAndFeelInt>* aLookAndFeelIntCache) override;
|
||||
|
||||
virtual bool RecvDataStoreGetStores(
|
||||
const nsString& aName,
|
||||
const nsString& aOwner,
|
||||
const IPC::Principal& aPrincipal,
|
||||
InfallibleTArray<DataStoreSetting>* aValue) override;
|
||||
|
||||
virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) override;
|
||||
|
||||
virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) override;
|
||||
@@ -1147,7 +1136,6 @@ private:
|
||||
bool mMetamorphosed;
|
||||
|
||||
bool mSendPermissionUpdates;
|
||||
bool mSendDataStoreInfos;
|
||||
bool mIsForBrowser;
|
||||
bool mIsNuwaProcess;
|
||||
bool mHasGamepadListener;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
class CallNuwaSpawn: public nsRunnable
|
||||
class CallNuwaSpawn: public Runnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
@@ -94,7 +94,7 @@ NuwaFork()
|
||||
sNuwaForking = true;
|
||||
|
||||
MessageLoop* ioloop = XRE_GetIOMessageLoop();
|
||||
ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
|
||||
ioloop->PostTask(NewRunnableFunction(RunNuwaFork));
|
||||
}
|
||||
|
||||
} // Anonymous namespace.
|
||||
@@ -185,7 +185,7 @@ GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
|
||||
*aInfoSize = i;
|
||||
}
|
||||
|
||||
class RunAddNewIPCProcess : public nsRunnable
|
||||
class RunAddNewIPCProcess : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
RunAddNewIPCProcess(pid_t aPid,
|
||||
|
||||
@@ -290,14 +290,6 @@ struct DataStorageItem {
|
||||
DataStorageType type;
|
||||
};
|
||||
|
||||
struct DataStoreSetting {
|
||||
nsString name;
|
||||
nsString originURL;
|
||||
nsString manifestURL;
|
||||
bool readOnly;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
// Note: Any changes to this structure should also be changed in
|
||||
// FileSystemUpdate below.
|
||||
struct VolumeInfo {
|
||||
@@ -491,9 +483,6 @@ child:
|
||||
*/
|
||||
async BidiKeyboardNotify(bool isLangRTL);
|
||||
|
||||
async DataStoreNotify(uint32_t aAppId, nsString aName,
|
||||
nsString aManifestURL);
|
||||
|
||||
/**
|
||||
* Dump this process's GC and CC logs to the provided files.
|
||||
*
|
||||
@@ -946,9 +935,6 @@ parent:
|
||||
|
||||
async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
|
||||
|
||||
sync DataStoreGetStores(nsString aName, nsString aOwner, Principal aPrincipal)
|
||||
returns (DataStoreSetting[] dataStores);
|
||||
|
||||
async FilePathUpdateNotify(nsString aType,
|
||||
nsString aStorageName,
|
||||
nsString aFilepath,
|
||||
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
void NuwaFork();
|
||||
|
||||
// initialization off the critical path of app startup.
|
||||
CancelableTask* mPreallocateAppProcessTask;
|
||||
CancelableRunnable* mPreallocateAppProcessTask;
|
||||
|
||||
// The array containing the preallocated processes. 4 as the inline storage size
|
||||
// should be enough so we don't need to grow the AutoTArray.
|
||||
@@ -243,7 +243,7 @@ PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CancelableTask> task = NewRunnableMethod(
|
||||
RefPtr<CancelableRunnable> task = NewRunnableMethod(
|
||||
this, &PreallocatedProcessManagerImpl::DelayedNuwaFork);
|
||||
mPreallocateAppProcessTask = task;
|
||||
MessageLoop::current()->PostDelayedTask(task.forget(),
|
||||
|
||||
@@ -14,10 +14,6 @@ Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionsTable.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionSettings.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
|
||||
"@mozilla.org/datastore-service;1",
|
||||
"nsIDataStoreService");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SystemMessagePermissionsChecker",
|
||||
"SystemMessagePermissionsTable"];
|
||||
|
||||
@@ -185,34 +181,6 @@ this.SystemMessagePermissionsChecker = {
|
||||
return object
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the message is a datastore-update message
|
||||
* @param string aSysMsgName
|
||||
* The system messsage name.
|
||||
*/
|
||||
isDataStoreSystemMessage: function(aSysMsgName) {
|
||||
return aSysMsgName.indexOf('datastore-update-') === 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if this manifest can deliver this particular datastore message.
|
||||
*/
|
||||
canDeliverDataStoreSystemMessage: function(aSysMsgName, aManifestURL) {
|
||||
let store = aSysMsgName.substr('datastore-update-'.length);
|
||||
|
||||
// Get all the manifest URLs of the apps which can access the datastore.
|
||||
let manifestURLs = dataStoreService.getAppManifestURLsForDataStore(store);
|
||||
let enumerate = manifestURLs.enumerate();
|
||||
while (enumerate.hasMoreElements()) {
|
||||
let manifestURL = enumerate.getNext().QueryInterface(Ci.nsISupportsString);
|
||||
if (manifestURL == aManifestURL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the system message is permitted to be registered for the given
|
||||
* app at start-up based on the permissions claimed in the app's manifest.
|
||||
@@ -258,11 +226,6 @@ this.SystemMessagePermissionsChecker = {
|
||||
"aPageURL: " + aPageURL + ", " +
|
||||
"aManifestURL: " + aManifestURL);
|
||||
|
||||
if (this.isDataStoreSystemMessage(aSysMsgName) &&
|
||||
this.canDeliverDataStoreSystemMessage(aSysMsgName, aManifestURL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let permNames = this.getSystemMessagePermissions(aSysMsgName);
|
||||
if (permNames === null) {
|
||||
return false;
|
||||
|
||||
@@ -55,7 +55,6 @@ DIRS += [
|
||||
'crypto',
|
||||
'phonenumberutils',
|
||||
'alarm',
|
||||
'datastore',
|
||||
'devicestorage',
|
||||
'encoding',
|
||||
'events',
|
||||
|
||||
@@ -169,7 +169,7 @@ NfcConsumer::Send(const CommandOptions& aOptions)
|
||||
}
|
||||
|
||||
// Runnable used dispatch the NfcEventOptions on the main thread.
|
||||
class NfcConsumer::DispatchNfcEventRunnable final : public nsRunnable
|
||||
class NfcConsumer::DispatchNfcEventRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
DispatchNfcEventRunnable(NfcService* aNfcService, const EventOptions& aEvent)
|
||||
@@ -391,7 +391,7 @@ NfcConsumer::OnConnectSuccess(int aIndex)
|
||||
}
|
||||
}
|
||||
|
||||
class NfcConsumer::ShutdownServiceRunnable final : public nsRunnable
|
||||
class NfcConsumer::ShutdownServiceRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
ShutdownServiceRunnable(NfcService* aNfcService)
|
||||
@@ -463,7 +463,7 @@ NfcService::FactoryCreate()
|
||||
/**
|
||||
* |StartConsumerRunnable| calls |NfcConsumer::Start| on the NFC thread.
|
||||
*/
|
||||
class NfcService::StartConsumerRunnable final : public nsRunnable
|
||||
class NfcService::StartConsumerRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
StartConsumerRunnable(NfcConsumer* aNfcConsumer)
|
||||
@@ -516,7 +516,7 @@ NfcService::Start(nsINfcGonkEventListener* aListener)
|
||||
* thread on the main thread. This has to be down after shutting
|
||||
* down the NFC consumer on the NFC thread.
|
||||
*/
|
||||
class NfcService::CleanupRunnable final : public nsRunnable
|
||||
class NfcService::CleanupRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
CleanupRunnable(NfcConsumer* aNfcConsumer,
|
||||
@@ -550,7 +550,7 @@ private:
|
||||
* NFC thread. Optionally, it can dispatch a |CleanupRunnable| to
|
||||
* the main thread for cleaning up the NFC resources.
|
||||
*/
|
||||
class NfcService::ShutdownConsumerRunnable final : public nsRunnable
|
||||
class NfcService::ShutdownConsumerRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
ShutdownConsumerRunnable(NfcConsumer* aNfcConsumer, bool aCleanUp)
|
||||
@@ -601,7 +601,7 @@ NfcService::Shutdown()
|
||||
/**
|
||||
* |SendRunnable| calls |NfcConsumer::Send| on the NFC thread.
|
||||
*/
|
||||
class NfcService::SendRunnable final : public nsRunnable
|
||||
class NfcService::SendRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
SendRunnable(NfcConsumer* aNfcConsumer, const CommandOptions& aOptions)
|
||||
|
||||
@@ -98,8 +98,8 @@ CopySubscriptionKeyToArray(nsIPushSubscription* aSubscription,
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!aKey.SetLength(keyLen, fallible) ||
|
||||
!aKey.ReplaceElementsAt(0, keyLen, keyBuffer, keyLen, fallible)) {
|
||||
if (!aKey.SetCapacity(keyLen, fallible) ||
|
||||
!aKey.InsertElementsAt(0, keyBuffer, keyLen, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
@@ -341,13 +341,10 @@ PushSubscription::ToJSON(PushSubscriptionJSON& aJSON, ErrorResult& aRv)
|
||||
aJSON.mEndpoint.Construct();
|
||||
aJSON.mEndpoint.Value() = mEndpoint;
|
||||
|
||||
Base64URLEncodeOptions encodeOptions;
|
||||
encodeOptions.mPad = false;
|
||||
|
||||
aJSON.mKeys.mP256dh.Construct();
|
||||
nsresult rv = Base64URLEncode(mRawP256dhKey.Length(),
|
||||
mRawP256dhKey.Elements(),
|
||||
encodeOptions,
|
||||
Base64URLEncodePaddingPolicy::Omit,
|
||||
aJSON.mKeys.mP256dh.Value());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
@@ -356,7 +353,8 @@ PushSubscription::ToJSON(PushSubscriptionJSON& aJSON, ErrorResult& aRv)
|
||||
|
||||
aJSON.mKeys.mAuth.Construct();
|
||||
rv = Base64URLEncode(mAuthSecret.Length(), mAuthSecret.Elements(),
|
||||
encodeOptions, aJSON.mKeys.mAuth.Value());
|
||||
Base64URLEncodePaddingPolicy::Omit,
|
||||
aJSON.mKeys.mAuth.Value());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
|
||||
+14
-8
@@ -11,10 +11,20 @@ namespace dom {
|
||||
PushUtil::CopyArrayBufferToArray(const ArrayBuffer& aBuffer,
|
||||
nsTArray<uint8_t>& aArray)
|
||||
{
|
||||
MOZ_ASSERT(aArray.IsEmpty());
|
||||
aBuffer.ComputeLengthAndData();
|
||||
return aArray.SetLength(aBuffer.Length(), fallible) &&
|
||||
aArray.ReplaceElementsAt(0, aBuffer.Length(), aBuffer.Data(),
|
||||
aBuffer.Length(), fallible);
|
||||
return aArray.SetCapacity(aBuffer.Length(), fallible) &&
|
||||
aArray.InsertElementsAt(0, aBuffer.Data(), aBuffer.Length(), fallible);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PushUtil::CopyArrayBufferViewToArray(const ArrayBufferView& aView,
|
||||
nsTArray<uint8_t>& aArray)
|
||||
{
|
||||
MOZ_ASSERT(aArray.IsEmpty());
|
||||
aView.ComputeLengthAndData();
|
||||
return aArray.SetCapacity(aView.Length(), fallible) &&
|
||||
aArray.InsertElementsAt(0, aView.Data(), aView.Length(), fallible);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
@@ -25,11 +35,7 @@ PushUtil::CopyBufferSourceToArray(
|
||||
return CopyArrayBufferToArray(aSource.GetAsArrayBuffer(), aArray);
|
||||
}
|
||||
if (aSource.IsArrayBufferView()) {
|
||||
const ArrayBufferView& view = aSource.GetAsArrayBufferView();
|
||||
view.ComputeLengthAndData();
|
||||
return aArray.SetLength(view.Length(), fallible) &&
|
||||
aArray.ReplaceElementsAt(0, view.Length(), view.Data(),
|
||||
view.Length(), fallible);
|
||||
return CopyArrayBufferViewToArray(aSource.GetAsArrayBufferView(), aArray);
|
||||
}
|
||||
MOZ_CRASH("Uninitialized union: expected buffer or view");
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
#ifndef mozilla_dom_PushUtil_h
|
||||
#define mozilla_dom_PushUtil_h
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@@ -20,6 +24,10 @@ public:
|
||||
CopyArrayBufferToArray(const ArrayBuffer& aBuffer,
|
||||
nsTArray<uint8_t>& aArray);
|
||||
|
||||
static bool
|
||||
CopyArrayBufferViewToArray(const ArrayBufferView& aView,
|
||||
nsTArray<uint8_t>& aArray);
|
||||
|
||||
static bool
|
||||
CopyBufferSourceToArray(const OwningArrayBufferViewOrArrayBuffer& aSource,
|
||||
nsTArray<uint8_t>& aArray);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user