import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1246051 - have MediaQueue<T>::Peek/PeekFront return a RefPtr<> to avoid dangling pointers per comment 0. r=gerald. (00f334efb1)
- Bug 1264199: P1. Perform audio conversion in the MSDM taskqueue and ahead of use. r=kinetik (001936e3ea)
- Bug 1267983 - include MediaQueue.h; r=jwwang (036107d765)
- Bug 1264199: P0. Fix nsDequeue/MediaQueue methods constness. r=jwwang (9aa33dfcb5)
- Bug 1264199: P0.1. Export SaferMultDiv method. r=gerald (0b7a35ae4d)
- Bug 1264199: P2. Ensure the AudioStream only ever receive the same content format. r=kinetik (a180d09279)
- Bug 1264199: P3. Attempt to minimize audio quality loss and unnecessary processing. r=kinetik (29d57b5a33)
- Bug 1264199: P4. Add mono to stereo upmix to AudioConverter. r=rillian (49c029bd86)
- Bug 1264199: P5. Perform all downmixing operations in DecodedAudioDataSink. r=kinetik (05a479f095)
- Bug 1264199: P6. Drain resampler when changing format or reaching the end. r=kinetik (8639102a94)
- Bug 1264199: P8. Handle potential resampling errors. r=kinetik (1267e4e73d)
- Bug 1264199: P9. Include pending frames in HasUnplayedFrames calculation. r=jwwang (ce7097fc90)
- Bug 1263496 - Part 1: fix for @mozilla.org/nullprincipal;1 r=bholley (c4c462a1bc)
- Bug 1263496 - Part 2: fix for NS_NULLPRINCIPAL_CONTRACTID. r=bholley (c1504240ec)
- Bug 1263496 - Part 3: fix for nsNullPrincipal::Create (0196a5a3ce)
- Bug 1261009 - Remove the Data Store API, r=fabrice (b22e580107)
- Bug 1261405 - Rename PushPermissionDescriptor.userVisible to `userVisibleOnly`. r=baku (4de70267cc)
- Bug 1266821 - Remove PushPermissionDescriptor from the Permissions API. r=baku (196cd83442)
- Bug 1268393 - Some compilation issues in ServiceWorker code, r=ehsan (d9c2f2554b)
- Merge branch 'dev' of https://github.com/rmottola/Arctic-Fox into dev (6f6c606911)
- Bug 1267733 P1 Treat last-update-time as infinitely in the past when checking for service worker update after restart. r=jdm (255da0a9e2)
- 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)
- Bug 1267568 part 1 - Add a weak ptr to nsGlobalChromeWindow to remember the pres shell we set the fullscreen change flag. r=smaug (83995d5296)
- Bug 1267568 part 2 - Add helper method to nsIPresShell to get the RefreshDriver. r=smaug (c60589fb40)
- Bug 1267568 part 3 - Use an individual method for check whether resize should be delayed. r=smaug (f0ab5156d1)
- Bug 1267568 part 4 - Replace InFullscreenChange flag of PresShell with IsResizeSuppressed flag in RefreshDriver. r=smaug (0a54f5a08b)
- Bug 1267568 part 5 - Replace the old FullscreenChangePrepare class with a single function. r=smaug (4196e82852)
- Bug 1267568 part 6 - Send fullscreen message before triggering any potential reflow. r=dao (fe9133ca2d)
- Bug 1243352 - attribute a value for ProxyHandlerInfo::mPrefAction in ProxyHandlerInfo::SetPreferredAction. r=blassey (577c23e4cb)
- Bug 1266433 - Send Push observer notifications to parent and content processes. f=janx r=dragana (768c173c2c)
- Bug 1267493 - Replace isURIPotentiallyTrustworthy usage in Push with a testing pref. r=dragana (96434b90d9)
- Bug 1266433 - Send an observer notification when a push subscription is lost. f=janx r=dragana (a7c7277e02)
- Bug 1247685 - Send subscription keys to the Push server. r=mt (651fc0cad3)
- Bug 1266540 - Stub out Push error reporting for the GCM and H2 backends. r=wchen (fd00c311aa)
- Bug 1266623 - Up/down mix WASAPI capture streams when stream formats don't match. r=padenot (ca92ec20ab)
- Bug 1267930 - When the wasapi rendering loop is stuck and we're shuttin down, leak the thread and continue the shutdown process. r=kinetik (04419ad94d)
- Bug 1269692 - Update cubeb to revision 17e3048d0afa1152776fb1867cdb61c49fae69e4. (3de098f4bb)
- Bug 1251502 - Update cubeb's udpate.sh script to account for new files. r=kinetik (a3ae5f27c1)
- Bug 1243234 - Hide MP4Metadata behind an impl pointer. r=giles (1543bedf28)
- Bug 1243234 - Update rust mp4parse telemetry reporting. r=kinetik (bb5c999c06)
- Bug 1242807 - Fix mp4parse-rust's error reporting via telemetry. r=giles (a3ca1b133b)
- Bug 1243234 - Move mp4parse-rust code into MP4MetadataRust impl. r=giles (ec4d6bcf0e)
- Bug 1243234 - Remove now-unnecessary StagefrightPrivate wrapper. r=giles (1e2c54232b)
- Bug 1243234 - Move mp4parse-rust initialization into constructor and clean up try_rust. r=giles (291c01f45a)
- Bug 1243234 - Update rust mp4parse to v0.2.1. r=kinetik (d2774346cd)
- Bug 1264622: [MP4] Resync stagefright's updateAudioTrackInfoFromESDS_MPEG4Audio with upstream. r=kentuckyfriedtakahe (b4b596507b)
- Bug 1254721: Ensure consistency between Cenc offsets and sizes table. r=gerald (59bd7122d1)
- Bug 1151202 - libstagefright: Fix compilation for systems without <sys/cdefs.h>. r=cpearce (e219658c31)
- Bug 1255866 - stagefright: Fix unused variable warnings. r=ajones (62afc26384)
- Bug 1251821: increase UDP socket send buffer on Win 7 r=jdm,jesup (e0d6e545f4)
- Bug 929977: Add support for RFC 7675 ICE consent freshness. r=bwc,mt (ea8a565a65)
- Bug 1231981 - Part 1: Very basic test TURN server for running in CI. r=ahal,drno (c98a79810b)
- Bug 1231981 - Part 2: A websocket-to-process bridge script that can be used by JS to launch an ICE server for testing. r=ahal (5bdb00dfd1)
- Bug 1231981 - Part 2.1: Only run the websocket/process bridge for media tests. r=ahal (86f97e2eb6)
- Bug 1225729: Whitelist specific bad RTCP timestamp value r=drno (f0c8402fd0)
- Bug 1193045 - Check selected attribute for all calls. r=bwc (7eb4095c34)
- Bug 1213056 - update tests to use maplike getStats. r=bwc (d27f997290)
- Bug 1231981 - Part 3: Set up TURN server for webrtc mochitests, when configured to. r=drno (38e4455eec)
- Bug 1231975 - Part 1: Basic audio mochitests for NAT scenarios. r=drno (16efaf581e)
- Bug 1231975 - Part 2: Break a reference cycle between NrTcpSocketIpc and TCPSocketChild, in the same manner as the UDP case. r=mcmanus (1fa55e3e5f)
This commit is contained in:
2024-08-28 22:57:14 +08:00
parent 8aa2e840a6
commit 4c9d88c9a4
372 changed files with 6225 additions and 14309 deletions
-7
View File
@@ -914,13 +914,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);
+33 -6
View File
@@ -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');
@@ -1138,22 +1137,50 @@ window.addEventListener('ContentStart', function update_onContentStart() {
updatePrompt.wrappedJSObject.handleContentStart(shell);
});
/* 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);
-4
View File
@@ -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
+21 -30
View File
@@ -131,22 +131,7 @@ var FullScreen = {
let topWin = event.target.ownerDocument.defaultView.top;
browser = gBrowser.getBrowserForContentWindow(topWin);
}
if (!browser || !this.enterDomFullscreen(browser)) {
if (document.fullscreenElement) {
// MozDOMFullscreen:Entered is dispatched synchronously in
// fullscreen change, hence we have to avoid calling this
// method synchronously here.
setTimeout(() => document.exitFullscreen(), 0);
}
break;
}
// If it is a remote browser, send a message to ask the content
// to enter fullscreen state. We don't need to do so if it is an
// in-process browser, since all related document should have
// entered fullscreen state at this point.
if (this._isRemoteBrowser(browser)) {
browser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
}
this.enterDomFullscreen(browser);
break;
}
case "MozDOMFullscreen:Exited":
@@ -178,22 +163,30 @@ var FullScreen = {
},
enterDomFullscreen : function(aBrowser) {
if (!document.fullscreenElement)
return false;
if (!document.fullscreenElement) {
return;
}
// If we've received a fullscreen notification, we have to ensure that the
// element that's requesting fullscreen belongs to the browser that's currently
// active. If not, we exit fullscreen since the "full-screen document" isn't
// actually visible now.
if (gBrowser.selectedBrowser != aBrowser) {
return false;
if (!aBrowser || gBrowser.selectedBrowser != aBrowser ||
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
Services.focus.activeWindow != window) {
// This function is called synchronously in fullscreen change, so
// we have to avoid calling exitFullscreen synchronously here.
setTimeout(() => document.exitFullscreen(), 0);
return;
}
let focusManager = Services.focus;
if (focusManager.activeWindow != window) {
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
return false;
// If it is a remote browser, send a message to ask the content
// to enter fullscreen state. We don't need to do so if it is an
// in-process browser, since all related document should have
// entered fullscreen state at this point.
if (this._isRemoteBrowser(aBrowser)) {
aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
}
document.documentElement.setAttribute("inDOMFullscreen", true);
@@ -210,8 +203,6 @@ var FullScreen = {
// If a fullscreen window loses focus, we show a warning when the
// fullscreen window is refocused.
window.addEventListener("activate", this);
return true;
},
cleanup: function () {
@@ -224,6 +215,9 @@ var FullScreen = {
},
cleanupDomFullscreen: function () {
window.messageManager
.broadcastAsyncMessage("DOMFullscreen:CleanUp");
this._WarningBox.close();
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
@@ -231,9 +225,6 @@ var FullScreen = {
window.removeEventListener("activate", this);
document.documentElement.removeAttribute("inDOMFullscreen");
window.messageManager
.broadcastAsyncMessage("DOMFullscreen:CleanUp");
},
_isRemoteBrowser: function (aBrowser) {
+22 -12
View File
@@ -887,12 +887,16 @@ FeedWriter.prototype = {
* The window of the document invoking the BrowserFeedWriter
*/
_getOriginalURI(aWindow) {
let chan = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let chan = docShell.currentDocumentChannel;
let nullPrincipal = Cc["@mozilla.org/nullprincipal;1"].
createInstance(Ci.nsIPrincipal);
// We probably need to call InheritFromDocShellToDoc for this, but right now
// we can't call it from JS.
let attrs = docShell.getOriginAttributes();
let ssm = Services.scriptSecurityManager;
let nullPrincipal = ssm.createNullPrincipal(attrs);
let resolvedURI = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
@@ -1185,13 +1189,19 @@ FeedWriter.prototype = {
}
let faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
let self = this;
let usePrivateBrowsing = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing;
let nullPrincipal = Cc["@mozilla.org/nullprincipal;1"]
.createInstance(Ci.nsIPrincipal);
let docShell = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let usePrivateBrowsing = docShell.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing;
// We probably need to call InheritFromDocShellToDoc for this, but right now
// we can't call it from JS.
let attrs = docShell.getOriginAttributes();
let ssm = Services.scriptSecurityManager;
let nullPrincipal = ssm.createNullPrincipal(attrs);
this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
usePrivateBrowsing ? this._faviconService.FAVICON_LOAD_PRIVATE
: this._faviconService.FAVICON_LOAD_NON_PRIVATE,
+3 -2
View File
@@ -1720,13 +1720,14 @@ Experiments.ExperimentEntry.prototype = {
_runFilterFunction: Task.async(function* (jsfilter) {
this._log.trace("runFilterFunction() - filter: " + jsfilter);
const nullprincipal = Cc["@mozilla.org/nullprincipal;1"].createInstance(Ci.nsIPrincipal);
let ssm = Services.scriptSecurityManager;
const nullPrincipal = ssm.createNullPrincipal({});
let options = {
sandboxName: "telemetry experiments jsfilter sandbox",
wantComponents: false,
};
let sandbox = Cu.Sandbox(nullprincipal, options);
let sandbox = Cu.Sandbox(nullPrincipal, options);
try {
Cu.evalInSandbox(jsfilter, sandbox);
} catch (e) {
-4
View File
@@ -838,10 +838,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
+2 -2
View File
@@ -553,7 +553,7 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttrib
&inheritsPrincipal);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(rv) || inheritsPrincipal) {
return nsNullPrincipal::Create();
return nsNullPrincipal::Create(aAttrs);
}
// Check whether the URI knows what its principal is supposed to be.
@@ -562,7 +562,7 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttrib
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (!principal) {
return nsNullPrincipal::Create();
return nsNullPrincipal::Create(aAttrs);
}
RefPtr<BasePrincipal> concrete = Cast(principal);
return concrete.forget();
+54 -25
View File
@@ -123,6 +123,32 @@ nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader,
return ReadKnownPrincipalType(aCx, aReader, tag, aOutPrincipals);
}
static bool
ReadSuffixAndSpec(JSStructuredCloneReader* aReader,
PrincipalOriginAttributes& aAttrs,
nsACString& aSpec)
{
uint32_t suffixLength, specLength;
if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) {
return false;
}
nsAutoCString suffix;
suffix.SetLength(suffixLength);
if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) {
return false;
}
aAttrs.PopulateFromSuffix(suffix);
aSpec.SetLength(specLength);
if (!JS_ReadBytes(aReader, aSpec.BeginWriting(), specLength)) {
return false;
}
return true;
}
static bool
ReadPrincipalInfo(JSStructuredCloneReader* aReader,
uint32_t aTag,
@@ -131,7 +157,12 @@ ReadPrincipalInfo(JSStructuredCloneReader* aReader,
if (aTag == SCTAG_DOM_SYSTEM_PRINCIPAL) {
aInfo = SystemPrincipalInfo();
} else if (aTag == SCTAG_DOM_NULL_PRINCIPAL) {
aInfo = NullPrincipalInfo();
PrincipalOriginAttributes attrs;
nsAutoCString dummy;
if (!ReadSuffixAndSpec(aReader, attrs, dummy)) {
return false;
}
aInfo = NullPrincipalInfo(attrs);
} else if (aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) {
uint32_t length, unused;
if (!JS_ReadUint32Pair(aReader, &length, &unused)) {
@@ -155,25 +186,12 @@ ReadPrincipalInfo(JSStructuredCloneReader* aReader,
aInfo = expanded;
} else if (aTag == SCTAG_DOM_CONTENT_PRINCIPAL) {
uint32_t suffixLength, specLength;
if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) {
return false;
}
nsAutoCString suffix;
suffix.SetLength(suffixLength);
if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) {
return false;
}
nsAutoCString spec;
spec.SetLength(specLength);
if (!JS_ReadBytes(aReader, spec.BeginWriting(), specLength)) {
return false;
}
PrincipalOriginAttributes attrs;
attrs.PopulateFromSuffix(suffix);
nsAutoCString spec;
if (!ReadSuffixAndSpec(aReader, attrs, spec)) {
return false;
}
aInfo = ContentPrincipalInfo(attrs, spec);
} else {
MOZ_CRASH("unexpected principal structured clone tag");
@@ -214,11 +232,26 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
return true;
}
static bool
WriteSuffixAndSpec(JSStructuredCloneWriter* aWriter,
const PrincipalOriginAttributes& aAttrs,
const nsCString& aSpec)
{
nsAutoCString suffix;
aAttrs.CreateSuffix(suffix);
return JS_WriteUint32Pair(aWriter, suffix.Length(), aSpec.Length()) &&
JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
JS_WriteBytes(aWriter, aSpec.get(), aSpec.Length());
}
static bool
WritePrincipalInfo(JSStructuredCloneWriter* aWriter, const PrincipalInfo& aInfo)
{
if (aInfo.type() == PrincipalInfo::TNullPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0);
const NullPrincipalInfo& nullInfo = aInfo;
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0) &&
WriteSuffixAndSpec(aWriter, nullInfo.attrs(), EmptyCString());
}
if (aInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0);
@@ -240,12 +273,8 @@ WritePrincipalInfo(JSStructuredCloneWriter* aWriter, const PrincipalInfo& aInfo)
MOZ_ASSERT(aInfo.type() == PrincipalInfo::TContentPrincipalInfo);
const ContentPrincipalInfo& cInfo = aInfo;
nsAutoCString suffix;
cInfo.attrs().CreateSuffix(suffix);
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) &&
JS_WriteUint32Pair(aWriter, suffix.Length(), cInfo.spec().Length()) &&
JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length());
WriteSuffixAndSpec(aWriter, cInfo.attrs(), cInfo.spec());
}
bool
+16 -2
View File
@@ -12,6 +12,7 @@
#include "mozilla/ArrayUtils.h"
#include "nsDocShell.h"
#include "nsNullPrincipal.h"
#include "nsNullPrincipalURI.h"
#include "nsMemory.h"
@@ -40,7 +41,20 @@ nsNullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
{
RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
nsresult rv = nullPrin->Init(Cast(aInheritFrom)->OriginAttributesRef());
return NS_SUCCEEDED(rv) ? nullPrin.forget() : nullptr;
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
return nullPrin.forget();
}
/* static */ already_AddRefed<nsNullPrincipal>
nsNullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell)
{
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(nsDocShell::Cast(aDocShell)->GetOriginAttributes(), nullptr);
RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
nsresult rv = nullPrin->Init(attrs);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
return nullPrin.forget();
}
/* static */ already_AddRefed<nsNullPrincipal>
@@ -48,7 +62,7 @@ nsNullPrincipal::Create(const PrincipalOriginAttributes& aOriginAttributes)
{
RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
nsresult rv = nullPrin->Init(aOriginAttributes);
NS_ENSURE_SUCCESS(rv, nullptr);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
return nullPrin.forget();
}
+4 -3
View File
@@ -20,6 +20,7 @@
#include "mozilla/BasePrincipal.h"
class nsIDocShell;
class nsIURI;
#define NS_NULLPRINCIPAL_CID \
@@ -47,10 +48,10 @@ public:
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
// Returns null on failure.
static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal *aInheritFrom);
static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIDocShell* aDocShell);
// Returns null on failure.
static already_AddRefed<nsNullPrincipal>
Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
-3
View File
@@ -366,14 +366,12 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
if (loadInfo->LoadingPrincipal()) {
prin =
nsNullPrincipal::CreateWithInheritedAttributes(loadInfo->LoadingPrincipal());
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
} else {
NeckoOriginAttributes nAttrs;
loadInfo->GetOriginAttributes(&nAttrs);
PrincipalOriginAttributes pAttrs;
pAttrs.InheritFromNecko(nAttrs);
prin = nsNullPrincipal::Create(pAttrs);
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
}
prin.forget(aPrincipal);
return NS_OK;
@@ -1212,7 +1210,6 @@ nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttrib
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(attrs);
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
prin.forget(aPrincipal);
return NS_OK;
}
+6 -2
View File
@@ -120,8 +120,12 @@ function createDummyDocument() {
});
let docShell = getDocShell(frame);
let eventTarget = docShell.chromeEventHandler;
docShell.createAboutBlankContentViewer(Cc["@mozilla.org/nullprincipal;1"]
.createInstance(Ci.nsIPrincipal));
let ssm = Services.scriptSecurityManager;
// We probably need to call InheritFromDocShellToDoc to get the correct origin
// attributes, but right now we can't call it from JS.
let nullPrincipal = ssm.createNullPrincipal(docShell.getOriginAttributes());
docShell.createAboutBlankContentViewer(nullPrincipal);
let window = docShell.contentViewer.DOMDocument.defaultView;
window.location = "data:text/html,<html></html>";
let deferred = promise.defer();
+10 -10
View File
@@ -1481,8 +1481,8 @@ nsDocShell::LoadURI(nsIURI* aURI,
// for in InternalLoad is data:, javascript:, and about:blank
// URIs. For other URIs this would all be dead wrong!
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
if (owner && mItemType != typeChrome) {
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
if (nsContentUtils::IsSystemPrincipal(ownerPrincipal)) {
if (ownerIsExplicit) {
return NS_ERROR_DOM_SECURITY_ERR;
@@ -1495,7 +1495,10 @@ nsDocShell::LoadURI(nsIURI* aURI,
}
// Don't inherit from the current page. Just do the safe thing
// and pretend that we were loaded by a nullprincipal.
owner = nsNullPrincipal::Create();
//
// We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
// have origin attributes.
owner = nsNullPrincipal::CreateWithInheritedAttributes(this);
inheritOwner = false;
}
}
@@ -1506,7 +1509,9 @@ nsDocShell::LoadURI(nsIURI* aURI,
if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_OWNER) {
inheritOwner = false;
owner = nsNullPrincipal::Create();
owner = ownerPrincipal ?
nsNullPrincipal::CreateWithInheritedAttributes(ownerPrincipal) :
nsNullPrincipal::CreateWithInheritedAttributes(this);
}
uint32_t flags = 0;
@@ -7967,7 +7972,6 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
nsCOMPtr<nsIPrincipal> principal;
if (mSandboxFlags & SANDBOXED_ORIGIN) {
principal = nsNullPrincipal::CreateWithInheritedAttributes(aPrincipal);
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
} else {
principal = aPrincipal;
}
@@ -12153,7 +12157,6 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
if (loadInfo->LoadingPrincipal()) {
owner = nsNullPrincipal::CreateWithInheritedAttributes(
loadInfo->LoadingPrincipal());
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
} else {
// get the OriginAttributes
NeckoOriginAttributes nAttrs;
@@ -12162,7 +12165,6 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
pAttrs.InheritFromNecko(nAttrs);
owner = nsNullPrincipal::Create(pAttrs);
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
}
} else if (loadInfo->GetForceInheritPrincipal()) {
owner = loadInfo->TriggeringPrincipal();
@@ -12337,8 +12339,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
// Ensure that we have an owner. Otherwise javascript: URIs will
// pick it up from the about:blank page we just loaded, and we
// don't really want even that in this case.
owner = nsNullPrincipal::Create();
NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
owner = nsNullPrincipal::CreateWithInheritedAttributes(this);
}
}
@@ -14026,8 +14027,7 @@ nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
if (!print || !print->IsInitializedForPrintPreview()) {
Stop(nsIWebNavigation::STOP_ALL);
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
NS_ENSURE_STATE(principal);
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
nsresult rv = CreateAboutBlankContentViewer(principal, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
print = do_QueryInterface(mContentViewer);
-4
View File
@@ -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])
}
-4
View File
@@ -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!");
}
}
-76
View File
@@ -147,10 +147,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");
@@ -450,18 +446,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;
@@ -813,52 +797,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.
//
@@ -1969,8 +1911,6 @@ this.DOMApplicationRegistry = {
manifestURL: app.manifestURL },
true);
}
this.updateDataStore(this.webapps[id].localId, app.origin,
app.manifestURL, newManifest);
MessageBroadcaster.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: newManifest,
@@ -2419,9 +2359,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();
@@ -3076,9 +3013,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",
@@ -3217,9 +3151,6 @@ this.DOMApplicationRegistry = {
}, true);
}
this.updateDataStore(this.webapps[aId].localId, aNewApp.origin,
aNewApp.manifestURL, aManifest);
if (aInstallSuccessCallback) {
yield aInstallSuccessCallback(aNewApp, aManifest, zipFile.path);
}
@@ -4755,13 +4686,6 @@ this.DOMApplicationRegistry = {
return AppsUtils.areAnyAppsInstalled(this.webapps);
},
updateDataStoreEntriesFromLocalId: function(aLocalId) {
let app = appsService.getAppByLocalId(aLocalId);
if (app) {
this.updateDataStoreForApp(app.id);
}
},
_notifyCategoryAndObservers: function(subject, topic, data, msg) {
const serviceMarker = "service,";
+1 -1
View File
@@ -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>
+22 -2
View File
@@ -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;
-3
View File
@@ -352,7 +352,6 @@ DOMParser::Init(nsIPrincipal* principal, nsIURI* documentURI,
// Don't give DOMParsers the system principal. Use a null
// principal instead.
mPrincipal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_FAILURE);
if (!mDocumentURI) {
rv = mPrincipal->GetURI(getter_AddRefs(mDocumentURI));
@@ -468,8 +467,6 @@ DOMParser::SetUpDocument(DocumentFlavor aFlavor, nsIDOMDocument** aResult)
AttemptedInitMarker marker(&mAttemptedInit);
nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create();
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
rv = Init(prin, nullptr, nullptr, scriptHandlingObject);
NS_ENSURE_SUCCESS(rv, rv);
}
-102
View File
@@ -96,7 +96,6 @@
#endif
#include "nsIDOMGlobalPropertyInitializer.h"
#include "mozilla/dom/DataStoreService.h"
#include "nsJSUtils.h"
#include "nsScriptNameSpaceManager.h"
@@ -1504,38 +1503,6 @@ Navigator::GetDeprecatedBattery(ErrorResult& aRv)
return mBatteryManager;
}
/* static */ already_AddRefed<Promise>
Navigator::GetDataStores(nsPIDOMWindowInner* 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)
{
@@ -2295,75 +2262,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<nsPIDOMWindowInner> 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
-13
View File
@@ -164,11 +164,6 @@ public:
Promise* GetBattery(ErrorResult& aRv);
battery::BatteryManager* GetDeprecatedBattery(ErrorResult& aRv);
static already_AddRefed<Promise> GetDataStores(nsPIDOMWindowInner* 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
+1 -2
View File
@@ -4506,8 +4506,7 @@ nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
{
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), "about:blank");
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
nsCOMPtr<nsIDOMDocument> domDocument;
nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
EmptyString(),
+14 -26
View File
@@ -3063,37 +3063,25 @@ nsDOMWindowUtils::RemoteFrameFullscreenReverted()
return NS_OK;
}
class MOZ_STACK_CLASS FullscreenChangePrepare
static void
PrepareForFullscreenChange(nsIPresShell* aPresShell, const nsSize& aSize,
nsSize* aOldSize = nullptr)
{
public:
FullscreenChangePrepare(nsIPresShell* aPresShell,
const nsSize& aSize, nsSize* aOldSize = nullptr)
: mPresShell(aPresShell)
{
if (mPresShell) {
mPresShell->SetIsInFullscreenChange(true);
}
if (aSize.IsEmpty()) {
return;
}
if (nsViewManager* viewManager = mPresShell->GetViewManager()) {
if (!aPresShell) {
return;
}
if (nsRefreshDriver* rd = aPresShell->GetRefreshDriver()) {
rd->SetIsResizeSuppressed();
}
if (!aSize.IsEmpty()) {
if (nsViewManager* viewManager = aPresShell->GetViewManager()) {
if (aOldSize) {
viewManager->GetWindowDimensions(&aOldSize->width, &aOldSize->height);
}
viewManager->SetWindowDimensions(aSize.width, aSize.height);
}
}
~FullscreenChangePrepare()
{
if (mPresShell) {
mPresShell->SetIsInFullscreenChange(false);
}
}
private:
nsCOMPtr<nsIPresShell> mPresShell;
};
}
class OldWindowSize : public LinkedListElement<OldWindowSize>
{
@@ -3166,7 +3154,7 @@ nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal)
presContext->DeviceContext()->GetRect(screenRect);
}
nsSize oldSize;
FullscreenChangePrepare prepare(GetPresShell(), screenRect.Size(), &oldSize);
PrepareForFullscreenChange(GetPresShell(), screenRect.Size(), &oldSize);
OldWindowSize::Set(doc->GetWindow(), oldSize);
*aRetVal = nsIDocument::HandlePendingFullscreenRequests(doc);
@@ -3190,7 +3178,7 @@ nsDOMWindowUtils::ExitFullscreen()
// set the window dimensions in advance. Since the resize message
// comes after the fullscreen change call, doing so could avoid an
// extra resize reflow after this point.
FullscreenChangePrepare prepare(GetPresShell(), oldSize);
PrepareForFullscreenChange(GetPresShell(), oldSize);
nsIDocument::ExitFullscreenInDocTree(doc);
return NS_OK;
}
+21 -12
View File
@@ -6415,13 +6415,6 @@ nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
}
}
// If we didn't setup the widget, we may need to manually set this
// flag, or the assertion in FinishFullscreenChange is violated.
if (nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell()) {
if (!presShell->IsInFullscreenChange()) {
presShell->SetIsInFullscreenChange(true);
}
}
FinishFullscreenChange(aFullScreen);
return NS_OK;
}
@@ -6435,8 +6428,18 @@ nsGlobalWindow::SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen
MOZ_ASSERT(!AsOuter()->GetFrameElementInternal(), "Content window should not call this");
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell()) {
presShell->SetIsInFullscreenChange(true);
if (!NS_WARN_IF(!IsChromeWindow())) {
auto chromeWin = static_cast<nsGlobalChromeWindow*>(this);
if (!NS_WARN_IF(chromeWin->mFullscreenPresShell)) {
if (nsIPresShell* shell = mDocShell->GetPresShell()) {
if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
chromeWin->mFullscreenPresShell = do_GetWeakReference(shell);
MOZ_ASSERT(chromeWin->mFullscreenPresShell);
rd->SetIsResizeSuppressed();
rd->Freeze();
}
}
}
}
nsresult rv = aReason == FullscreenReason::ForFullscreenMode ?
// If we enter fullscreen for fullscreen mode, we want
@@ -6478,9 +6481,15 @@ nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
// respond visually if we are kicked into full screen mode
DispatchCustomEvent(NS_LITERAL_STRING("fullscreen"));
if (nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell()) {
MOZ_ASSERT(presShell->IsInFullscreenChange());
presShell->SetIsInFullscreenChange(false);
if (!NS_WARN_IF(!IsChromeWindow())) {
auto chromeWin = static_cast<nsGlobalChromeWindow*>(this);
if (nsCOMPtr<nsIPresShell> shell =
do_QueryReferent(chromeWin->mFullscreenPresShell)) {
if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
rd->Thaw();
}
chromeWin->mFullscreenPresShell = nullptr;
}
}
if (!mWakeLock && mFullScreen) {
+4
View File
@@ -1986,6 +1986,10 @@ public:
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
nsInterfaceHashtable<nsStringHashKey, nsIMessageBroadcaster> mGroupMessageManagers;
// A weak pointer to the nsPresShell that we are doing fullscreen for.
// The pointer being set indicates we've set the IsInFullscreenChange
// flag on this pres shell.
nsWeakPtr mFullscreenPresShell;
};
/*
-1
View File
@@ -182,7 +182,6 @@ nsNodeInfoManager::Init(nsIDocument *aDocument)
"Being inited when we already have a principal?");
mPrincipal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_FAILURE);
if (aDocument) {
mBindingManager = new nsBindingManager(aDocument);
+1 -2
View File
@@ -1524,8 +1524,7 @@ nsTreeSanitizer::InitializeStatics()
sAttributesMathML->PutEntry(*kAttributesMathML[i]);
}
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
principal.forget(&sNullPrincipal);
}
@@ -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);
-23
View File
@@ -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,
@@ -1612,10 +1593,6 @@ DOMInterfaces = {
},
},
'WorkerNavigator': {
'implicitJSContext': ['getDataStores'],
},
'XMLHttpRequest': [
{
'nativeType': 'nsXMLHttpRequest',
-3
View File
@@ -99,9 +99,6 @@ SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
nsCOMPtr<nsIPrincipal> principal;
if (NS_IsMainThread()) {
principal = nsNullPrincipal::Create();
if (!principal) {
return nullptr;
}
}
JS::Rooted<JSObject*> global(cx,
@@ -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());
+32 -20
View File
@@ -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
+20 -19
View File
@@ -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);
}
+6 -5
View File
@@ -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());
+30 -23
View File
@@ -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
+2 -2
View File
@@ -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!");
}
+1 -1
View File
@@ -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))) {
+2 -2
View File
@@ -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)
+4 -6
View File
@@ -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);
-196
View File
@@ -1,196 +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/Navigator.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Preferences.h"
#include "AccessCheck.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
NS_IMPL_ADDREF_INHERITED(DataStore, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(DataStore, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DataStore)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(DataStore, DOMEventTargetHelper, mStore)
DataStore::DataStore(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow)
{
}
DataStore::~DataStore()
{
}
already_AddRefed<DataStore>
DataStore::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<DataStore> store = new DataStore(window);
return store.forget();
}
JSObject*
DataStore::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return DataStoreBinding::Wrap(aCx, this, aGivenProto);
}
/*static*/ bool
DataStore::EnabledForScope(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
// Only expose the interface when it is:
// 1. enabled by the preference and
// 2. accessed by the chrome codes in Gecko.
return (Navigator::HasDataStoreSupport(aCx, aObj) &&
nsContentUtils::ThreadsafeIsCallerChrome());
}
void
DataStore::GetName(nsAString& aName, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
nsAutoString name;
mStore->GetName(name, aRv);
aName.Assign(name);
}
void
DataStore::GetOwner(nsAString& aOwner, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
nsAutoString owner;
mStore->GetOwner(owner, aRv);
aOwner.Assign(owner);
}
bool
DataStore::GetReadOnly(ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->GetReadOnly(aRv);
}
already_AddRefed<Promise>
DataStore::Get(const Sequence<OwningStringOrUnsignedLong>& aId,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Get(aId, aRv);
}
already_AddRefed<Promise>
DataStore::Put(JSContext* aCx,
JS::Handle<JS::Value> aObj,
const StringOrUnsignedLong& aId,
const nsAString& aRevisionId,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Put(aObj, aId, aRevisionId, aRv);
}
already_AddRefed<Promise>
DataStore::Add(JSContext* aCx,
JS::Handle<JS::Value> aObj,
const Optional<StringOrUnsignedLong>& aId,
const nsAString& aRevisionId,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Add(aObj, aId, aRevisionId, aRv);
}
already_AddRefed<Promise>
DataStore::Remove(const StringOrUnsignedLong& aId,
const nsAString& aRevisionId,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Remove(aId, aRevisionId, aRv);
}
already_AddRefed<Promise>
DataStore::Clear(const nsAString& aRevisionId, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Clear(aRevisionId, aRv);
}
void
DataStore::GetRevisionId(nsAString& aRevisionId, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
nsAutoString revisionId;
mStore->GetRevisionId(revisionId, aRv);
aRevisionId.Assign(revisionId);
}
already_AddRefed<Promise>
DataStore::GetLength(ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->GetLength(aRv);
}
already_AddRefed<DataStoreCursor>
DataStore::Sync(const nsAString& aRevisionId, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStore);
return mStore->Sync(aRevisionId, aRv);
}
void
DataStore::SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mStore);
mStore = &aStore;
mStore->SetEventTarget(*this, aRv);
}
} //namespace dom
} //namespace mozilla
-96
View File
@@ -1,96 +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_DataStore_h
#define mozilla_dom_DataStore_h
#include "mozilla/DOMEventTargetHelper.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class Promise;
class DataStoreCursor;
class DataStoreImpl;
class StringOrUnsignedLong;
class OwningStringOrUnsignedLong;
class DataStore final : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataStore,
DOMEventTargetHelper)
explicit DataStore(nsPIDOMWindowInner* aWindow);
// WebIDL (internal functions)
static already_AddRefed<DataStore> Constructor(GlobalObject& aGlobal,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
static bool EnabledForScope(JSContext* aCx, JS::Handle<JSObject*> aObj);
// WebIDL (public APIs)
void GetName(nsAString& aName, ErrorResult& aRv);
void GetOwner(nsAString& aOwner, ErrorResult& aRv);
bool GetReadOnly(ErrorResult& aRv);
already_AddRefed<Promise> Get(const Sequence<OwningStringOrUnsignedLong>& aId,
ErrorResult& aRv);
already_AddRefed<Promise> Put(JSContext* aCx,
JS::Handle<JS::Value> aObj,
const StringOrUnsignedLong& aId,
const nsAString& aRevisionId,
ErrorResult& aRv);
already_AddRefed<Promise> Add(JSContext* aCx,
JS::Handle<JS::Value> aObj,
const Optional<StringOrUnsignedLong>& aId,
const nsAString& aRevisionId,
ErrorResult& aRv);
already_AddRefed<Promise> Remove(const StringOrUnsignedLong& aId,
const nsAString& aRevisionId,
ErrorResult& aRv);
already_AddRefed<Promise> Clear(const nsAString& aRevisionId,
ErrorResult& aRv);
void GetRevisionId(nsAString& aRevisionId, ErrorResult& aRv);
already_AddRefed<Promise> GetLength(ErrorResult& aRv);
already_AddRefed<DataStoreCursor> Sync(const nsAString& aRevisionId,
ErrorResult& aRv);
IMPL_EVENT_HANDLER(change)
// This internal function (ChromeOnly) is aimed to make the DataStore keep a
// reference to the DataStoreImpl which really implements the API's logic in
// JS. We also need to let the DataStoreImpl implementation keep the event
// target of DataStore, so that it can know where to fire the events.
void SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv);
private:
~DataStore();
RefPtr<DataStoreImpl> mStore;
};
} //namespace dom
} //namespace mozilla
#endif
-2
View File
@@ -1,2 +0,0 @@
component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js
contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2}
-54
View File
@@ -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
-223
View File
@@ -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();
-79
View File
@@ -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
-59
View File
@@ -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
-444
View File
@@ -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);
}
};
-442
View File
@@ -1,442 +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 "DataStoreDB.h"
#include "DataStoreCallbacks.h"
#include "jsapi.h"
#include "mozilla/dom/IDBDatabaseBinding.h"
#include "mozilla/dom/IDBDatabase.h"
#include "mozilla/dom/IDBEvents.h"
#include "mozilla/dom/IDBFactory.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/IDBIndex.h"
#include "mozilla/dom/IDBObjectStore.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
#include "mozilla/dom/IDBRequest.h"
#include "mozilla/dom/IDBTransaction.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsIDOMEvent.h"
#include "nsIPrincipal.h"
#include "nsIXPConnect.h"
#include "nsNullPrincipal.h"
#define DATASTOREDB_VERSION 1
#define DATASTOREDB_NAME "DataStoreDB"
#define DATASTOREDB_REVISION_INDEX "revisionIndex"
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
class VersionChangeListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
explicit VersionChangeListener(IDBDatabase* aDatabase)
: mDatabase(aDatabase)
{}
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override
{
nsString type;
nsresult rv = aEvent->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!type.EqualsASCII("versionchange")) {
MOZ_ASSERT_UNREACHABLE("Expected a versionchange event");
return NS_ERROR_FAILURE;
}
rv = mDatabase->RemoveEventListener(NS_LITERAL_STRING("versionchange"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
#ifdef DEBUG
nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent);
MOZ_ASSERT(event);
Nullable<uint64_t> version = event->GetNewVersion();
MOZ_ASSERT(version.IsNull());
#endif
mDatabase->Close();
return NS_OK;
}
private:
IDBDatabase* mDatabase;
~VersionChangeListener() {}
};
NS_IMPL_ISUPPORTS(VersionChangeListener, nsIDOMEventListener)
NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener)
DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName)
: mState(Inactive)
, mCreatedSchema(false)
{
mDatabaseName.Assign(aName);
mDatabaseName.Append('|');
mDatabaseName.Append(aManifestURL);
}
DataStoreDB::~DataStoreDB()
{
}
nsresult
DataStoreDB::CreateFactoryIfNeeded()
{
if (!mFactory) {
nsresult rv;
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
if (!principal) {
return NS_ERROR_FAILURE;
}
nsIXPConnect* xpc = nsContentUtils::XPConnect();
MOZ_ASSERT(xpc);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> global(cx);
rv = xpc->CreateSandbox(cx, principal, global.address());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// The CreateSandbox call returns a proxy to the actual sandbox object. We
// don't need a proxy here.
global = js::UncheckedUnwrap(global);
JSAutoCompartment ac(cx, global);
rv = IDBFactory::CreateForDatastore(cx, global, getter_AddRefs(mFactory));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
DataStoreDB::Open(IDBTransactionMode aMode, const Sequence<nsString>& aDbs,
DataStoreDBCallback* aCallback)
{
MOZ_ASSERT(mState == Inactive);
nsresult rv = CreateFactoryIfNeeded();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// We only need a JSContext here to get a stack from, so just init our
// AutoJSAPI without a global.
AutoJSAPI jsapi;
jsapi.Init();
ErrorResult error;
mRequest = mFactory->Open(jsapi.cx(), mDatabaseName, DATASTOREDB_VERSION,
error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
rv = AddEventListeners();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mState = Active;
mTransactionMode = aMode;
mObjectStores = aDbs;
mCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
DataStoreDB::HandleEvent(nsIDOMEvent* aEvent)
{
nsString type;
nsresult rv = aEvent->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (type.EqualsASCII("success")) {
RemoveEventListeners();
mState = Inactive;
rv = DatabaseOpened();
if (NS_WARN_IF(NS_FAILED(rv))) {
mCallback->Run(this, DataStoreDBCallback::Error);
} else {
mCallback->Run(this, mCreatedSchema
? DataStoreDBCallback::CreatedSchema :
DataStoreDBCallback::Success);
}
mRequest = nullptr;
return NS_OK;
}
if (type.EqualsASCII("upgradeneeded")) {
return UpgradeSchema(aEvent);
}
if (type.EqualsASCII("error") || type.EqualsASCII("blocked")) {
RemoveEventListeners();
mState = Inactive;
mCallback->Run(this, DataStoreDBCallback::Error);
mRequest = nullptr;
return NS_OK;
}
MOZ_CRASH("This should not happen");
}
nsresult
DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent)
{
MOZ_ASSERT(NS_IsMainThread());
// This DB has been just created and we have to inform the callback about
// this.
mCreatedSchema = true;
#ifdef DEBUG
nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent);
MOZ_ASSERT(event);
Nullable<uint64_t> version = event->GetNewVersion();
MOZ_ASSERT(!version.IsNull());
MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION);
#endif
ErrorResult error;
JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
mRequest->GetResult(&result, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
MOZ_ASSERT(result.isObject());
IDBDatabase* database = nullptr;
nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
if (NS_FAILED(rv)) {
NS_WARNING("Didn't get the object we expected!");
return rv;
}
{
IDBObjectStoreParameters params;
params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }"));
RefPtr<IDBObjectStore> store =
database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_NAME),
params, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
RefPtr<IDBObjectStore> store;
{
IDBObjectStoreParameters params;
params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }"));
store =
database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION),
params, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
{
IDBIndexParameters params;
params.Init(NS_LITERAL_STRING("{ \"unique\": true }"));
RefPtr<IDBIndex> index =
store->CreateIndex(NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX),
NS_LITERAL_STRING("revisionId"), params, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
return NS_OK;
}
nsresult
DataStoreDB::DatabaseOpened()
{
MOZ_ASSERT(NS_IsMainThread());
ErrorResult error;
JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
mRequest->GetResult(&result, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
MOZ_ASSERT(result.isObject());
nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase);
if (NS_FAILED(rv)) {
NS_WARNING("Didn't get the object we expected!");
return rv;
}
RefPtr<VersionChangeListener> listener =
new VersionChangeListener(mDatabase);
rv = mDatabase->EventTarget::AddEventListener(
NS_LITERAL_STRING("versionchange"), listener, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
StringOrStringSequence objectStores;
if (!objectStores.RawSetAsStringSequence().AppendElements(mObjectStores,
fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// We init with the global of our result, just for consistency.
AutoJSAPI jsapi;
if (!jsapi.Init(&result.toObject())) {
return NS_ERROR_UNEXPECTED;
}
RefPtr<IDBTransaction> txn;
error = mDatabase->Transaction(jsapi.cx(),
objectStores,
mTransactionMode,
getter_AddRefs(txn));
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
mTransaction = txn.forget();
return NS_OK;
}
nsresult
DataStoreDB::Delete()
{
MOZ_ASSERT(mState == Inactive);
nsresult rv = CreateFactoryIfNeeded();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mTransaction = nullptr;
if (mDatabase) {
mDatabase->Close();
mDatabase = nullptr;
}
// We only need a JSContext here to get a stack from, so just init our
// AutoJSAPI without a global.
AutoJSAPI jsapi;
jsapi.Init();
ErrorResult error;
RefPtr<IDBOpenDBRequest> request =
mFactory->DeleteDatabase(jsapi.cx(), mDatabaseName, IDBOpenDBOptions(),
error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
return NS_OK;
}
IDBTransaction*
DataStoreDB::Transaction() const
{
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mTransaction->IsOpen());
return mTransaction;
}
nsresult
DataStoreDB::AddEventListeners()
{
nsresult rv;
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("upgradeneeded"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("error"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("blocked"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
DataStoreDB::RemoveEventListeners()
{
nsresult rv;
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("success"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("upgradeneeded"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("error"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("blocked"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla
-80
View File
@@ -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
-118
View File
@@ -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');
}
}
-549
View File
@@ -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]);
-100
View File
@@ -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
-50
View File
@@ -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
File diff suppressed because it is too large Load Diff
-119
View File
@@ -1,119 +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_DataStoreService_h
#define mozilla_dom_DataStoreService_h
#include "mozilla/dom/PContent.h"
#include "nsClassHashtable.h"
#include "nsIDataStoreService.h"
#include "nsIObserver.h"
#include "nsRefPtrHashtable.h"
class nsIPrincipal;
class nsIUUIDGenerator;
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
class DataStoreInfo;
class FirstRevisionIdCallback;
class PendingRequest;
class Promise;
class RetrieveRevisionsCounter;
class RevisionAddedEnableStoreCallback;
class DataStoreService final : public nsIDataStoreService
, public nsIObserver
{
friend class ContentChild;
friend class FirstRevisionIdCallback;
friend class RetrieveRevisionsCounter;
friend class RevisionAddedEnableStoreCallback;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIDATASTORESERVICE
// Returns the DataStoreService singleton. Only to be called from main
// thread.
static already_AddRefed<DataStoreService> GetOrCreate();
static already_AddRefed<DataStoreService> Get();
static void Shutdown();
static bool CheckPermission(nsIPrincipal* principal);
nsresult GenerateUUID(nsAString& aID);
nsresult GetDataStoresFromIPC(const nsAString& aName,
const nsAString& aOwner,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreSetting>* aValue);
void HomeScreenPrefChanged();
private:
DataStoreService();
~DataStoreService();
nsresult Init();
typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp;
nsresult AddPermissions(uint32_t aAppId, const nsAString& aName,
const nsAString& aOriginURL,
const nsAString& aManifestURL,
bool aReadOnly);
nsresult AddAccessPermissions(uint32_t aAppId, const nsAString& aName,
const nsAString& aOriginURL,
const nsAString& aManifestURL,
bool aReadOnly);
nsresult CreateFirstRevisionId(uint32_t aAppId, const nsAString& aName,
const nsAString& aManifestURL);
void GetDataStoresCreate(nsPIDOMWindowInner* aWindow, Promise* aPromise,
const nsTArray<DataStoreInfo>& aStores);
void GetDataStoresResolve(nsPIDOMWindowInner* aWindow, Promise* aPromise,
const nsTArray<DataStoreInfo>& aStores);
nsresult GetDataStoreInfos(const nsAString& aName, const nsAString& aOwner,
uint32_t aAppId, nsIPrincipal* aPrincipal,
nsTArray<DataStoreInfo>& aStores);
void DeleteDataStores(uint32_t aAppId);
nsresult EnableDataStore(uint32_t aAppId, const nsAString& aName,
const nsAString& aManifestURL);
already_AddRefed<RetrieveRevisionsCounter> GetCounter(uint32_t aId) const;
void RemoveCounter(uint32_t aId);
void DeleteDataStoresIfNotAllowed(const nsAString& aManifestURL);
void AddDataStoresIfAllowed(const nsAString& aManifestURL);
nsClassHashtable<nsStringHashKey, HashApp> mStores;
nsClassHashtable<nsStringHashKey, HashApp> mAccessStores;
typedef nsTArray<PendingRequest> PendingRequests;
nsClassHashtable<nsStringHashKey, PendingRequests> mPendingRequests;
nsRefPtrHashtable<nsUint32HashKey, RetrieveRevisionsCounter> mPendingCounters;
nsCOMPtr<nsIUUIDGenerator> mUUIDGenerator;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DataStoreService_h
-50
View File
@@ -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']
-23
View File
@@ -1,23 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
interface mozIDOMWindow;
// NOTE: This is a temporary interface.
// It will be removed in the next patches for rewriting DataStore in C++.
[scriptable, uuid(14f4bae7-dd01-4d1d-81e1-f8fd1e463b5f)]
interface nsIDataStore : nsISupports
{
void init(in mozIDOMWindow window,
in DOMString name,
in DOMString manifestURL,
in boolean readOnly);
attribute jsval exposedObject;
void retrieveRevisionId(in jsval cb);
};
-34
View File
@@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
interface mozIDOMWindow;
interface nsIPrincipal;
interface nsIArray;
[scriptable, uuid(44a8de94-d3dd-4a3a-a582-41027d36ceb5)]
interface nsIDataStoreService : nsISupports
{
void installDataStore(in unsigned long appId,
in DOMString name,
in DOMString originURL,
in DOMString manifestURL,
in boolean readOnly);
void installAccessDataStore(in unsigned long appId,
in DOMString name,
in DOMString originURL,
in DOMString manifestURL,
in boolean readOnly);
nsISupports getDataStores(in mozIDOMWindow window,
in DOMString name,
in DOMString owner);
nsIArray getAppManifestURLsForDataStore(in DOMString name);
boolean checkPermission(in nsIPrincipal principal);
};
-55
View File
@@ -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" }
}
}
-91
View File
@@ -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>
-110
View File
@@ -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>
-31
View File
@@ -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>
-119
View File
@@ -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>
-19
View File
@@ -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();
-46
View File
@@ -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>
-40
View File
@@ -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>
-77
View File
@@ -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>
-34
View File
@@ -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>
-88
View File
@@ -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" }
}
}
-26
View File
@@ -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>
-148
View File
@@ -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>
-51
View File
@@ -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>
-75
View File
@@ -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>
-32
View File
@@ -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>
-161
View File
@@ -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>
-72
View File
@@ -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>
-31
View File
@@ -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>
-461
View File
@@ -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();
}
-30
View File
@@ -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>
-19
View File
@@ -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();

Some files were not shown because too many files have changed in this diff Show More