зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c, a=merge
This commit is contained in:
Коммит
713c41b609
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1061489: Updated moz.build requires CLOBBER
|
||||
Bug 1047076: at least Windows needed a clobber for some unknown reason
|
||||
|
|
|
@ -2253,6 +2253,15 @@ let E10SUINotification = {
|
|||
CURRENT_NOTICE_COUNT: 0,
|
||||
|
||||
checkStatus: function() {
|
||||
let skipE10sChecks = false;
|
||||
try {
|
||||
skipE10sChecks = Services.prefs.getBoolPref("browser.tabs.remote.autostart.disabled-because-using-a11y");
|
||||
} catch(e) {}
|
||||
|
||||
if (skipE10sChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Services.appinfo.browserTabsRemoteAutostart) {
|
||||
let notice = 0;
|
||||
try {
|
||||
|
@ -2263,13 +2272,22 @@ let E10SUINotification = {
|
|||
if (!activationNoticeShown) {
|
||||
this._showE10sActivatedNotice();
|
||||
}
|
||||
|
||||
// e10s doesn't work with accessibility, so we prompt to disable
|
||||
// e10s if a11y is enabled, now or in the future.
|
||||
Services.obs.addObserver(this, "a11y-init-or-shutdown", true);
|
||||
if (Services.appinfo.accessibilityEnabled) {
|
||||
this._showE10sAccessibilityWarning();
|
||||
}
|
||||
} else {
|
||||
let e10sPromptShownCount = 0;
|
||||
try {
|
||||
e10sPromptShownCount = Services.prefs.getIntPref("browser.displayedE10SPrompt");
|
||||
} catch(e) {}
|
||||
|
||||
if (!Services.appinfo.inSafeMode && e10sPromptShownCount < 5) {
|
||||
if (!Services.appinfo.inSafeMode &&
|
||||
!Services.appinfo.accessibilityEnabled &&
|
||||
e10sPromptShownCount < 5) {
|
||||
Services.tm.mainThread.dispatch(() => {
|
||||
try {
|
||||
this._showE10SPrompt();
|
||||
|
@ -2282,6 +2300,14 @@ let E10SUINotification = {
|
|||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic == "a11y-init-or-shutdown" && data == "1") {
|
||||
this._showE10sAccessibilityWarning();
|
||||
}
|
||||
},
|
||||
|
||||
_showE10sActivatedNotice: function() {
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
if (!win)
|
||||
|
@ -2344,6 +2370,56 @@ let E10SUINotification = {
|
|||
|
||||
win.PopupNotifications.show(browser, "enable_e10s", promptMessage, null, mainAction, secondaryActions, options);
|
||||
},
|
||||
|
||||
_warnedAboutAccessibility: false,
|
||||
|
||||
_showE10sAccessibilityWarning: function() {
|
||||
Services.prefs.setBoolPref("browser.tabs.remote.autostart.disabled-because-using-a11y", true);
|
||||
|
||||
if (this._warnedAboutAccessibility) {
|
||||
return;
|
||||
}
|
||||
this._warnedAboutAccessibility = true;
|
||||
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
if (!win) {
|
||||
// Just restart immediately.
|
||||
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
|
||||
let promptMessage = "Multiprocess Nightly (e10s) does not yet support accessibility features. Multiprocessing will be disabled if you restart Firefox. Would you like to restart?";
|
||||
let mainAction = {
|
||||
label: "Disable and Restart",
|
||||
accessKey: "R",
|
||||
callback: function () {
|
||||
// Restart the app
|
||||
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
|
||||
if (cancelQuit.data)
|
||||
return; // somebody canceled our quit request
|
||||
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
|
||||
}
|
||||
};
|
||||
let secondaryActions = [
|
||||
{
|
||||
label: "Don't Disable",
|
||||
accessKey: "D",
|
||||
callback: function () {
|
||||
Services.prefs.setBoolPref("browser.tabs.remote.autostart.disabled-because-using-a11y", false);
|
||||
}
|
||||
}
|
||||
];
|
||||
let options = {
|
||||
popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
|
||||
learnMoreURL: "https://wiki.mozilla.org/Electrolysis",
|
||||
persistWhileVisible: true
|
||||
};
|
||||
|
||||
win.PopupNotifications.show(browser, "a11y_enabled_with_e10s", promptMessage, null, mainAction, secondaryActions, options);
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ support-files =
|
|||
file_disableScript.html
|
||||
|
||||
[test_bug995943.xul]
|
||||
skip-if = os == "mac" && !debug # bug 1008481
|
||||
[test_disableScript.xul]
|
||||
[test_principal_jarprefix_origin_appid_appstatus.html]
|
||||
# jarPrefix test doesn't work on Windows, see bug 776296.
|
||||
|
|
|
@ -26,10 +26,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
|
|||
/** Test for CAPS file:// URI prefs. **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestCompleteLog();
|
||||
if (Services.appinfo.OS == "Darwin") // See bug 1067022
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
|
||||
var profileDir = "file://" + Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get("ProfD", Ci.nsILocalFile).path;
|
||||
var rootdir = Services.appinfo.OS == "WINNT" ? "file:///C:" : "file:///";
|
||||
|
||||
function checkLoadFileURI(domain, shouldLoad) {
|
||||
debug("Invoking checkLoadFileURI with domain: " + domain + ", shouldLoad: " + shouldLoad);
|
||||
|
@ -45,7 +45,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
|
|||
}
|
||||
$('ifr').addEventListener('load', l2);
|
||||
try {
|
||||
window[0].wrappedJSObject.location = profileDir;
|
||||
window[0].wrappedJSObject.location = rootdir;
|
||||
debug("Successfully navigated for " + domain);
|
||||
} catch (e) {
|
||||
ok(!shouldLoad && /denied|insecure/.test(e),
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsDOMMultipartFile;
|
||||
class nsIFile;
|
||||
|
@ -64,6 +65,7 @@ class DOMFile MOZ_FINAL : public nsIDOMFile
|
|||
, public nsIXHRSendable
|
||||
, public nsIMutable
|
||||
, public nsIJSNativeInitializer
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIDOMBLOB
|
||||
|
@ -190,9 +192,9 @@ public:
|
|||
virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) = 0;
|
||||
|
||||
nsresult Slice(int64_t aStart, int64_t aEnd, const nsAString& aContentType,
|
||||
uint8_t aArgc, nsIDOMBlob **aBlob);
|
||||
uint8_t aArgc, DOMFileImpl** aBlobImpl);
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) = 0;
|
||||
|
||||
|
@ -321,7 +323,7 @@ public:
|
|||
|
||||
virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) MOZ_OVERRIDE;
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -464,7 +466,7 @@ public:
|
|||
|
||||
virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -551,7 +553,7 @@ public:
|
|||
|
||||
virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -573,7 +575,7 @@ private:
|
|||
nsString mContentType;
|
||||
};
|
||||
|
||||
class DOMFileImplFile MOZ_FINAL : public DOMFileImplBase
|
||||
class DOMFileImplFile : public DOMFileImplBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -690,6 +692,9 @@ public:
|
|||
|
||||
void SetPath(const nsAString& aFullPath);
|
||||
|
||||
protected:
|
||||
virtual ~DOMFileImplFile() {}
|
||||
|
||||
private:
|
||||
// Create slice
|
||||
DOMFileImplFile(const DOMFileImplFile* aOther, uint64_t aStart,
|
||||
|
@ -719,9 +724,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
~DOMFileImplFile() {}
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ namespace mozilla {
|
|||
class CSSStyleSheet;
|
||||
class ErrorResult;
|
||||
class EventStates;
|
||||
class SVGAttrAnimationRuleProcessor;
|
||||
|
||||
namespace css {
|
||||
class Loader;
|
||||
|
@ -925,6 +926,16 @@ public:
|
|||
return mStyleAttrStyleSheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this document's SVG Animation rule processor. May return null
|
||||
* if there isn't one.
|
||||
*/
|
||||
mozilla::SVGAttrAnimationRuleProcessor*
|
||||
GetSVGAttrAnimationRuleProcessor() const
|
||||
{
|
||||
return mSVGAttrAnimationRuleProcessor;
|
||||
}
|
||||
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) = 0;
|
||||
|
||||
/**
|
||||
|
@ -2443,6 +2454,7 @@ protected:
|
|||
nsRefPtr<mozilla::css::ImageLoader> mStyleImageLoader;
|
||||
nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
|
||||
nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
|
||||
nsRefPtr<mozilla::SVGAttrAnimationRuleProcessor> mSVGAttrAnimationRuleProcessor;
|
||||
|
||||
// The set of all object, embed, applet, video/audio elements or
|
||||
// nsIObjectLoadingContent or nsIDocumentActivity for which this is the
|
||||
|
|
|
@ -1576,7 +1576,8 @@ Element::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
|
|||
if (doc) {
|
||||
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
||||
if (shell) {
|
||||
shell->RestyleForAnimation(this, eRestyle_Self);
|
||||
shell->RestyleForAnimation(this,
|
||||
eRestyle_StyleAttribute | eRestyle_ChangeAnimationPhase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ DOMMultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
|
|||
return CallQueryInterface(stream, aStream);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<DOMFileImpl>
|
||||
DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
|
@ -77,18 +77,17 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
|||
if (skipStart < l) {
|
||||
uint64_t upperBound = std::min<uint64_t>(l - skipStart, length);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> firstBlob;
|
||||
rv = blobImpl->Slice(skipStart, skipStart + upperBound,
|
||||
aContentType, 3,
|
||||
getter_AddRefs(firstBlob));
|
||||
nsRefPtr<DOMFileImpl> firstImpl;
|
||||
rv = blobImpl->Slice(skipStart, skipStart + upperBound, aContentType, 3,
|
||||
getter_AddRefs(firstImpl));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
// Avoid wrapping a single blob inside an DOMMultipartFileImpl
|
||||
if (length == upperBound) {
|
||||
return firstBlob.forget();
|
||||
return firstImpl.forget();
|
||||
}
|
||||
|
||||
blobImpls.AppendElement(static_cast<DOMFile*>(firstBlob.get())->Impl());
|
||||
blobImpls.AppendElement(firstImpl);
|
||||
length -= upperBound;
|
||||
i++;
|
||||
break;
|
||||
|
@ -105,12 +104,12 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
|||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
if (length < l) {
|
||||
nsCOMPtr<nsIDOMBlob> lastBlob;
|
||||
nsRefPtr<DOMFileImpl> lastBlob;
|
||||
rv = blobImpl->Slice(0, length, aContentType, 3,
|
||||
getter_AddRefs(lastBlob));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
blobImpls.AppendElement(static_cast<DOMFile*>(lastBlob.get())->Impl());
|
||||
blobImpls.AppendElement(lastBlob);
|
||||
} else {
|
||||
blobImpls.AppendElement(blobImpl);
|
||||
}
|
||||
|
@ -118,9 +117,9 @@ DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
|||
}
|
||||
|
||||
// we can create our blob now
|
||||
nsCOMPtr<nsIDOMBlob> blob =
|
||||
new DOMFile(new DOMMultipartFileImpl(blobImpls, aContentType));
|
||||
return blob.forget();
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new DOMMultipartFileImpl(blobImpls, aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
uint32_t aArgc,
|
||||
JS::Value* aArgv);
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMFile)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, IsFile())
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !(IsFile()))
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -298,7 +299,10 @@ already_AddRefed<nsIDOMBlob>
|
|||
DOMFile::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
return mImpl->CreateSlice(aStart, aLength, aContentType);
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
mImpl->CreateSlice(aStart, aLength, aContentType);
|
||||
nsRefPtr<DOMFile> slice = new DOMFile(impl);
|
||||
return slice.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -400,7 +404,17 @@ DOMFile::Slice(int64_t aStart, int64_t aEnd,
|
|||
nsIDOMBlob **aBlob)
|
||||
{
|
||||
MOZ_ASSERT(mImpl);
|
||||
return mImpl->Slice(aStart, aEnd, aContentType, aArgc, aBlob);
|
||||
nsRefPtr<DOMFileImpl> impl;
|
||||
nsresult rv = mImpl->Slice(aStart, aEnd, aContentType, aArgc,
|
||||
getter_AddRefs(impl));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<DOMFile> blob = new DOMFile(impl);
|
||||
blob.forget(aBlob);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -460,9 +474,9 @@ DOMFile::IsMemoryFile()
|
|||
nsresult
|
||||
DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
|
||||
const nsAString& aContentType, uint8_t aArgc,
|
||||
nsIDOMBlob **aBlob)
|
||||
DOMFileImpl** aBlobImpl)
|
||||
{
|
||||
*aBlob = nullptr;
|
||||
*aBlobImpl = nullptr;
|
||||
|
||||
// Truncate aStart and aEnd so that we stay within this file.
|
||||
uint64_t thisLength;
|
||||
|
@ -475,12 +489,15 @@ DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
|
|||
|
||||
ParseSize((int64_t)thisLength, aStart, aEnd);
|
||||
|
||||
// Create the new file
|
||||
nsCOMPtr<nsIDOMBlob> blob =
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
CreateSlice((uint64_t)aStart, (uint64_t)(aEnd - aStart), aContentType);
|
||||
|
||||
blob.forget(aBlob);
|
||||
return *aBlob ? NS_OK : NS_ERROR_UNEXPECTED;
|
||||
if (!impl) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
impl.forget(aBlobImpl);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -575,7 +592,7 @@ DOMFileImplBase::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<DOMFileImpl>
|
||||
DOMFileImplBase::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
|
@ -724,13 +741,13 @@ DOMFileImplBase::SetMutable(bool aMutable)
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// DOMFileImplFile implementation
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<DOMFileImpl>
|
||||
DOMFileImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMBlob> blob =
|
||||
new DOMFile(new DOMFileImplFile(this, aStart, aLength, aContentType));
|
||||
return blob.forget();
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new DOMFileImplFile(this, aStart, aLength, aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -832,7 +849,8 @@ DOMFileImplFile::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
|
|||
const uint32_t sFileStreamFlags =
|
||||
nsIFileInputStream::CLOSE_ON_EOF |
|
||||
nsIFileInputStream::REOPEN_ON_REWIND |
|
||||
nsIFileInputStream::DEFER_OPEN;
|
||||
nsIFileInputStream::DEFER_OPEN |
|
||||
nsIFileInputStream::SHARE_DELETE;
|
||||
|
||||
nsresult
|
||||
DOMFileImplFile::GetInternalStream(nsIInputStream** aStream)
|
||||
|
@ -857,13 +875,13 @@ DOMFileImplFile::SetPath(const nsAString& aPath)
|
|||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplMemory, DOMFileImpl)
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<DOMFileImpl>
|
||||
DOMFileImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMBlob> blob =
|
||||
new DOMFile(new DOMFileImplMemory(this, aStart, aLength, aContentType));
|
||||
return blob.forget();
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new DOMFileImplMemory(this, aStart, aLength, aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -982,17 +1000,17 @@ DOMFileImplMemory::DataOwner::EnsureMemoryReporterRegistered()
|
|||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplTemporaryFileBlob, DOMFileImpl)
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<DOMFileImpl>
|
||||
DOMFileImplTemporaryFileBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
if (aStart + aLength > mLength)
|
||||
return nullptr;
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob =
|
||||
new DOMFile(new DOMFileImplTemporaryFileBlob(this, aStart + mStartPos,
|
||||
aLength, aContentType));
|
||||
return blob.forget();
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new DOMFileImplTemporaryFileBlob(this, aStart + mStartPos, aLength,
|
||||
aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -153,7 +153,6 @@
|
|||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
||||
#include "nsSMILAnimationController.h"
|
||||
|
@ -168,6 +167,7 @@
|
|||
#include "nsCSPService.h"
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
#include "nsHTMLCSSStyleSheet.h"
|
||||
#include "SVGAttrAnimationRuleProcessor.h"
|
||||
#include "mozilla/dom/DOMImplementation.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/Comment.h"
|
||||
|
@ -2449,6 +2449,11 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
|
|||
mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet();
|
||||
}
|
||||
|
||||
if (!mSVGAttrAnimationRuleProcessor) {
|
||||
mSVGAttrAnimationRuleProcessor =
|
||||
new mozilla::SVGAttrAnimationRuleProcessor();
|
||||
}
|
||||
|
||||
// Now set up our style sets
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
if (shell) {
|
||||
|
@ -8511,13 +8516,6 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
|||
}
|
||||
}
|
||||
|
||||
// Check if we have running offline storage transactions
|
||||
quota::QuotaManager* quotaManager =
|
||||
win ? quota::QuotaManager::Get() : nullptr;
|
||||
if (quotaManager && quotaManager->HasOpenTransactions(win)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
// Check if we have active GetUserMedia use
|
||||
if (MediaManager::Exists() && win &&
|
||||
|
@ -12169,6 +12167,12 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
|||
mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
|
||||
0;
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mSVGAttrAnimationRuleProcessor ?
|
||||
mSVGAttrAnimationRuleProcessor->DOMSizeOfIncludingThis(
|
||||
aWindowSizes->mMallocSizeOf) :
|
||||
0;
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mStyledLinks.SizeOfExcludingThis(nullptr, aWindowSizes->mMallocSizeOf);
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
#include "mozilla/dom/PBlobChild.h"
|
||||
#include "mozilla/dom/PBlobParent.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "JavaScriptChild.h"
|
||||
#include "JavaScriptParent.h"
|
||||
#include "mozilla/dom/DOMStringList.h"
|
||||
|
|
|
@ -905,6 +905,12 @@ nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
|||
aRuleWalker->Forward(mContentStyleRule);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGElement::WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
// Update & walk the animated content style rule, to include style from
|
||||
// animated mapped attributes. But first, get nsPresContext to check
|
||||
// whether this is a "no-animation restyle". (This should match the check
|
||||
|
@ -919,7 +925,8 @@ nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
|||
// want that to happen from SMIL-animated value of mapped attrs, so
|
||||
// ignore animated value for now, and request an animation restyle to
|
||||
// get our animated value noticed.
|
||||
shell->RestyleForAnimation(this, eRestyle_Self);
|
||||
shell->RestyleForAnimation(this,
|
||||
eRestyle_SVGAttrAnimations | eRestyle_ChangeAnimationPhase);
|
||||
} else {
|
||||
// Ok, this is an animation restyle -- go ahead and update/walk the
|
||||
// animated content style rule.
|
||||
|
@ -933,8 +940,6 @@ nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
|||
aRuleWalker->Forward(animContentStyleRule);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
|
|
|
@ -113,6 +113,7 @@ public:
|
|||
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
|
||||
void WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker);
|
||||
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -396,16 +396,15 @@ ArchiveZipFileImpl::Traverse(nsCycleCollectionTraversalCallback &cb)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArchiveReader);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
already_AddRefed<mozilla::dom::DOMFileImpl>
|
||||
ArchiveZipFileImpl::CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMBlob> t =
|
||||
new DOMFile(new ArchiveZipFileImpl(mFilename, mContentType,
|
||||
aStart, mLength, mCentral,
|
||||
mArchiveReader));
|
||||
return t.forget();
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new ArchiveZipFileImpl(mFilename, mContentType, aStart, mLength, mCentral,
|
||||
mArchiveReader);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(ArchiveZipFileImpl, DOMFileImpl)
|
||||
|
|
|
@ -71,7 +71,7 @@ protected:
|
|||
MOZ_COUNT_DTOR(ArchiveZipFileImpl);
|
||||
}
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart,
|
||||
virtual already_AddRefed<DOMFileImpl> CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -3004,16 +3005,20 @@ nsDOMWindowUtils::AreDialogsEnabled(bool* aResult)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
|
||||
int64_t* aResult)
|
||||
int64_t* _retval)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
if (!aFile.isPrimitive()) {
|
||||
if (aFile.isPrimitive()) {
|
||||
*_retval = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSObject* obj = aFile.toObjectOrNull();
|
||||
|
||||
indexedDB::IDBMutableFile* mutableFile = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(IDBMutableFile, obj, mutableFile))) {
|
||||
*aResult = mutableFile->GetFileId();
|
||||
*_retval = mutableFile->GetFileId();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3022,12 +3027,43 @@ nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
|
|||
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
|
||||
if (blob) {
|
||||
*aResult = blob->GetFileId();
|
||||
*_retval = blob->GetFileId();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetFilePath(JS::HandleValue aFile, JSContext* aCx,
|
||||
nsAString& _retval)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
if (aFile.isPrimitive()) {
|
||||
_retval.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aResult = -1;
|
||||
JSObject* obj = aFile.toObjectOrNull();
|
||||
|
||||
nsISupports* nativeObj =
|
||||
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(nativeObj);
|
||||
if (file) {
|
||||
nsString filePath;
|
||||
nsresult rv = file->GetMozFullPathInternal(filePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
_retval = filePath;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
_retval.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,6 @@
|
|||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
|
||||
|
@ -1562,12 +1561,6 @@ nsGlobalWindow::FreeInnerObjects()
|
|||
// Kill all of the workers for this window.
|
||||
mozilla::dom::workers::CancelWorkersForWindow(this);
|
||||
|
||||
// Close all offline storages for this window.
|
||||
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
|
||||
if (quotaManager) {
|
||||
quotaManager->AbortCloseStoragesForWindow(this);
|
||||
}
|
||||
|
||||
ClearAllTimeouts();
|
||||
|
||||
if (mIdleTimer) {
|
||||
|
@ -10581,9 +10574,11 @@ GetIndexedDBEnabledForAboutURI(nsIURI *aURI)
|
|||
return flags & nsIAboutModule::ENABLE_INDEXED_DB;
|
||||
}
|
||||
|
||||
indexedDB::IDBFactory*
|
||||
mozilla::dom::indexedDB::IDBFactory*
|
||||
nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
|
||||
{
|
||||
using mozilla::dom::indexedDB::IDBFactory;
|
||||
|
||||
if (!mIndexedDB) {
|
||||
// If the document has the sandboxed origin flag set
|
||||
// don't allow access to indexedDB.
|
||||
|
@ -10630,8 +10625,7 @@ nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
|
|||
}
|
||||
|
||||
// This may be null if being created from a file.
|
||||
aError = indexedDB::IDBFactory::Create(this, nullptr,
|
||||
getter_AddRefs(mIndexedDB));
|
||||
aError = IDBFactory::CreateForWindow(this, getter_AddRefs(mIndexedDB));
|
||||
}
|
||||
|
||||
return mIndexedDB;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsIDOMFile.h"
|
||||
|
@ -17,7 +16,13 @@
|
|||
#include "nsTObserverArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobChild;
|
||||
class BlobParent;
|
||||
}
|
||||
namespace ipc {
|
||||
class UnixSocketConsumer;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ObexBase.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIOutputStream;
|
||||
class nsIInputStream;
|
||||
class nsIVolumeMountLock;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocket;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "mozilla/ipc/DBusUtils.h"
|
||||
#include "mozilla/ipc/RawDBusConnection.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ObexBase.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIOutputStream;
|
||||
class nsIInputStream;
|
||||
class nsIVolumeMountLock;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocket;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
|
||||
#include "BluetoothChild.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsISettingsService.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsIDOMFile.h"
|
||||
|
@ -17,7 +16,13 @@
|
|||
#include "nsTObserverArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobChild;
|
||||
class BlobParent;
|
||||
}
|
||||
namespace ipc {
|
||||
class UnixSocketConsumer;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ObexBase.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIOutputStream;
|
||||
class nsIInputStream;
|
||||
class nsIVolumeMountLock;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocket;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ObexBase.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
#include "BluetoothProfileManagerBase.h"
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIOutputStream;
|
||||
class nsIInputStream;
|
||||
class nsIVolumeMountLock;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BlobParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocket;
|
||||
|
|
|
@ -7,15 +7,22 @@
|
|||
#include "DataStoreDB.h"
|
||||
|
||||
#include "DataStoreCallbacks.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/IDBDatabaseBinding.h"
|
||||
#include "mozilla/dom/IDBFactoryBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBEvents.h"
|
||||
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
||||
#include "mozilla/dom/indexedDB/IDBIndex.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#define DATASTOREDB_VERSION 1
|
||||
#define DATASTOREDB_NAME "DataStoreDB"
|
||||
|
@ -63,7 +70,9 @@ public:
|
|||
MOZ_ASSERT(version.IsNull());
|
||||
#endif
|
||||
|
||||
return mDatabase->Close();
|
||||
mDatabase->Close();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -93,7 +102,36 @@ nsresult
|
|||
DataStoreDB::CreateFactoryIfNeeded()
|
||||
{
|
||||
if (!mFactory) {
|
||||
nsresult rv = IDBFactory::Create(nullptr, getter_AddRefs(mFactory));
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
MOZ_ASSERT(xpc);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
|
||||
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, globalHolder->GetJSObject());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
@ -301,11 +339,7 @@ DataStoreDB::Delete()
|
|||
mTransaction = nullptr;
|
||||
|
||||
if (mDatabase) {
|
||||
rv = mDatabase->Close();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDatabase->Close();
|
||||
mDatabase = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
#include "DataStoreCallbacks.h"
|
||||
#include "DataStoreService.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/indexedDB/IDBCursor.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
@ -137,7 +137,7 @@
|
|||
|
||||
// Uninstall the apps
|
||||
function() { uninstallApp(gApps[0]); },
|
||||
function() { uninstallApp(gApps[1]); },
|
||||
function() { uninstallApp(gApps[1]); }
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "DeviceStorageFileDescriptor.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "nsIMIMEService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "ContentParent.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "AppProcessChecker.h"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
#include "FileHelper.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/InputStreamParams.h"
|
||||
#include "MutableFile.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
|
@ -16,6 +18,10 @@
|
|||
#include "nsISeekableStream.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsXULAppAPI.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -127,7 +133,8 @@ FileInputStreamWrapper::FileInputStreamWrapper(nsISupports* aFileStream,
|
|||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(FileInputStreamWrapper,
|
||||
FileStreamWrapper,
|
||||
nsIInputStream)
|
||||
nsIInputStream,
|
||||
nsIIPCSerializableInputStream)
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileInputStreamWrapper::Close()
|
||||
|
@ -230,6 +237,26 @@ FileInputStreamWrapper::IsNonBlocking(bool* _retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FileInputStreamWrapper::Serialize(InputStreamParams& aParams,
|
||||
FileDescriptorArray& /* aFDs */)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIInputStream> thisStream = do_QueryObject(this);
|
||||
|
||||
aParams = mozilla::ipc::SameProcessInputStreamParams(
|
||||
reinterpret_cast<intptr_t>(thisStream.forget().take()));
|
||||
}
|
||||
|
||||
bool
|
||||
FileInputStreamWrapper::Deserialize(const InputStreamParams& /* aParams */,
|
||||
const FileDescriptorArray& /* aFDs */)
|
||||
{
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
FileOutputStreamWrapper::FileOutputStreamWrapper(nsISupports* aFileStream,
|
||||
FileHelper* aFileHelper,
|
||||
uint64_t aOffset,
|
||||
|
|
|
@ -11,8 +11,13 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class InputStreamParams;
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
|
||||
class FileHelper;
|
||||
|
@ -46,11 +51,15 @@ protected:
|
|||
};
|
||||
|
||||
class FileInputStreamWrapper : public FileStreamWrapper,
|
||||
public nsIInputStream
|
||||
public nsIInputStream,
|
||||
public nsIIPCSerializableInputStream
|
||||
{
|
||||
typedef mozilla::ipc::InputStreamParams InputStreamParams;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIINPUTSTREAM
|
||||
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
|
||||
|
||||
FileInputStreamWrapper(nsISupports* aFileStream,
|
||||
FileHelper* aFileHelper,
|
||||
|
|
|
@ -28,6 +28,8 @@ UNIFIED_SOURCES += [
|
|||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../base',
|
||||
]
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "mozilla/dom/FileSystemBase.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PContent.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsDOMFile.h"
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/FileSystemRequestParent.h"
|
||||
#include "mozilla/dom/PFileSystemRequestChild.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
|
||||
class nsIDOMFile;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class BlobParent;
|
||||
class FileSystemBase;
|
||||
class FileSystemParams;
|
||||
class Promise;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "mozilla/dom/FileSystemBase.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/dom/FileSystemBase.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,627 @@
|
|||
/* 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_indexeddb_actorschild_h__
|
||||
#define mozilla_dom_indexeddb_actorschild_h__
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIEventTarget;
|
||||
struct PRThread;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class BackgroundChildImpl;
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class FileInfo;
|
||||
class IDBCursor;
|
||||
class IDBDatabase;
|
||||
class IDBFactory;
|
||||
class IDBMutableFile;
|
||||
class IDBOpenDBRequest;
|
||||
class IDBRequest;
|
||||
class IDBTransaction;
|
||||
class Key;
|
||||
class PBackgroundIDBFileChild;
|
||||
class PermissionRequestChild;
|
||||
class PermissionRequestParent;
|
||||
class SerializedStructuredCloneReadInfo;
|
||||
|
||||
class BackgroundFactoryChild MOZ_FINAL
|
||||
: public PBackgroundIDBFactoryChild
|
||||
{
|
||||
friend class mozilla::ipc::BackgroundChildImpl;
|
||||
friend class IDBFactory;
|
||||
|
||||
IDBFactory* mFactory;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
#endif
|
||||
|
||||
public:
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
IDBFactory*
|
||||
GetDOMObject() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mFactory;
|
||||
}
|
||||
|
||||
private:
|
||||
// Only created by IDBFactory.
|
||||
BackgroundFactoryChild(IDBFactory* aFactory);
|
||||
|
||||
// Only destroyed by mozilla::ipc::BackgroundChildImpl.
|
||||
~BackgroundFactoryChild();
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBFactoryRequestChild*
|
||||
AllocPBackgroundIDBFactoryRequestChild(const FactoryRequestParams& aParams)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBFactoryRequestChild(
|
||||
PBackgroundIDBFactoryRequestChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBDatabaseChild*
|
||||
AllocPBackgroundIDBDatabaseChild(const DatabaseSpec& aSpec,
|
||||
PBackgroundIDBFactoryRequestChild* aRequest)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
SendDeleteMe() MOZ_DELETE;
|
||||
};
|
||||
|
||||
class BackgroundDatabaseChild;
|
||||
|
||||
class BackgroundRequestChildBase
|
||||
{
|
||||
protected:
|
||||
nsRefPtr<IDBRequest> mRequest;
|
||||
|
||||
private:
|
||||
bool mActorDestroyed;
|
||||
|
||||
public:
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
IDBRequest*
|
||||
GetDOMObject() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mRequest;
|
||||
}
|
||||
|
||||
bool
|
||||
IsActorDestroyed() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mActorDestroyed;
|
||||
}
|
||||
|
||||
protected:
|
||||
BackgroundRequestChildBase(IDBRequest* aRequest);
|
||||
|
||||
virtual
|
||||
~BackgroundRequestChildBase();
|
||||
|
||||
void
|
||||
NoteActorDestroyed();
|
||||
};
|
||||
|
||||
class BackgroundFactoryRequestChild MOZ_FINAL
|
||||
: public BackgroundRequestChildBase
|
||||
, public PBackgroundIDBFactoryRequestChild
|
||||
{
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
|
||||
friend class IDBFactory;
|
||||
friend class BackgroundFactoryChild;
|
||||
friend class BackgroundDatabaseChild;
|
||||
friend class PermissionRequestChild;
|
||||
friend class PermissionRequestParent;
|
||||
|
||||
nsRefPtr<IDBFactory> mFactory;
|
||||
const uint64_t mRequestedVersion;
|
||||
const PersistenceType mPersistenceType;
|
||||
const bool mIsDeleteOp;
|
||||
|
||||
public:
|
||||
IDBOpenDBRequest*
|
||||
GetOpenDBRequest() const;
|
||||
|
||||
private:
|
||||
// Only created by IDBFactory.
|
||||
BackgroundFactoryRequestChild(IDBFactory* aFactory,
|
||||
IDBOpenDBRequest* aOpenRequest,
|
||||
bool aIsDeleteOp,
|
||||
uint64_t aRequestedVersion,
|
||||
PersistenceType aPersistenceType);
|
||||
|
||||
// Only destroyed by BackgroundFactoryChild.
|
||||
~BackgroundFactoryRequestChild();
|
||||
|
||||
bool
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const OpenDatabaseRequestResponse& aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const DeleteDatabaseRequestResponse& aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
Recv__delete__(const FactoryRequestResponse& aResponse) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPermissionChallenge(const PrincipalInfo& aPrincipalInfo) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvBlocked(const uint64_t& aCurrentVersion) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class BackgroundDatabaseChild MOZ_FINAL
|
||||
: public PBackgroundIDBDatabaseChild
|
||||
{
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
|
||||
friend class BackgroundFactoryChild;
|
||||
friend class BackgroundFactoryRequestChild;
|
||||
friend class IDBDatabase;
|
||||
|
||||
nsAutoPtr<DatabaseSpec> mSpec;
|
||||
nsRefPtr<IDBDatabase> mTemporaryStrongDatabase;
|
||||
BackgroundFactoryRequestChild* mOpenRequestActor;
|
||||
IDBDatabase* mDatabase;
|
||||
|
||||
PersistenceType mPersistenceType;
|
||||
|
||||
public:
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
{
|
||||
static_cast<BackgroundFactoryChild*>(Manager())->AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
const DatabaseSpec*
|
||||
Spec() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mSpec;
|
||||
}
|
||||
|
||||
IDBDatabase*
|
||||
GetDOMObject() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
private:
|
||||
// Only constructed by BackgroundFactoryChild.
|
||||
BackgroundDatabaseChild(const DatabaseSpec& aSpec,
|
||||
BackgroundFactoryRequestChild* aOpenRequest);
|
||||
|
||||
// Only destroyed by BackgroundFactoryChild.
|
||||
~BackgroundDatabaseChild();
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
void
|
||||
EnsureDOMObject();
|
||||
|
||||
void
|
||||
ReleaseDOMObject();
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBDatabaseFileChild*
|
||||
AllocPBackgroundIDBDatabaseFileChild(
|
||||
const BlobOrInputStream& aBlobOrInputStream)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBDatabaseFileChild(
|
||||
PBackgroundIDBDatabaseFileChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBTransactionChild*
|
||||
AllocPBackgroundIDBTransactionChild(
|
||||
const nsTArray<nsString>& aObjectStoreNames,
|
||||
const Mode& aMode)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBTransactionChild(PBackgroundIDBTransactionChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBVersionChangeTransactionChild*
|
||||
AllocPBackgroundIDBVersionChangeTransactionChild(
|
||||
const uint64_t& aCurrentVersion,
|
||||
const uint64_t& aRequestedVersion,
|
||||
const int64_t& aNextObjectStoreId,
|
||||
const int64_t& aNextIndexId)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPBackgroundIDBVersionChangeTransactionConstructor(
|
||||
PBackgroundIDBVersionChangeTransactionChild* aActor,
|
||||
const uint64_t& aCurrentVersion,
|
||||
const uint64_t& aRequestedVersion,
|
||||
const int64_t& aNextObjectStoreId,
|
||||
const int64_t& aNextIndexId)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBVersionChangeTransactionChild(
|
||||
PBackgroundIDBVersionChangeTransactionChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvVersionChange(const uint64_t& aOldVersion,
|
||||
const NullableVersion& aNewVersion)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvInvalidate() MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
SendDeleteMe() MOZ_DELETE;
|
||||
};
|
||||
|
||||
class BackgroundVersionChangeTransactionChild;
|
||||
|
||||
class BackgroundTransactionBase
|
||||
{
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
|
||||
// mTemporaryStrongTransaction is strong and is only valid until the end of
|
||||
// NoteComplete() member function or until the NoteActorDestroyed() member
|
||||
// function is called.
|
||||
nsRefPtr<IDBTransaction> mTemporaryStrongTransaction;
|
||||
|
||||
protected:
|
||||
// mTransaction is weak and is valid until the NoteActorDestroyed() member
|
||||
// function is called.
|
||||
IDBTransaction* mTransaction;
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
virtual void
|
||||
AssertIsOnOwningThread() const = 0;
|
||||
#else
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
{ }
|
||||
#endif
|
||||
|
||||
IDBTransaction*
|
||||
GetDOMObject() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
protected:
|
||||
BackgroundTransactionBase();
|
||||
BackgroundTransactionBase(IDBTransaction* aTransaction);
|
||||
|
||||
virtual
|
||||
~BackgroundTransactionBase();
|
||||
|
||||
void
|
||||
NoteActorDestroyed();
|
||||
|
||||
void
|
||||
NoteComplete();
|
||||
|
||||
private:
|
||||
// Only called by BackgroundVersionChangeTransactionChild.
|
||||
void
|
||||
SetDOMTransaction(IDBTransaction* aDOMObject);
|
||||
};
|
||||
|
||||
class BackgroundTransactionChild MOZ_FINAL
|
||||
: public BackgroundTransactionBase
|
||||
, public PBackgroundIDBTransactionChild
|
||||
{
|
||||
friend class BackgroundDatabaseChild;
|
||||
friend class IDBDatabase;
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
virtual void
|
||||
AssertIsOnOwningThread() const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
private:
|
||||
// Only created by IDBDatabase.
|
||||
BackgroundTransactionChild(IDBTransaction* aTransaction);
|
||||
|
||||
// Only destroyed by BackgroundDatabaseChild.
|
||||
~BackgroundTransactionChild();
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
RecvComplete(const nsresult& aResult) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBRequestChild*
|
||||
AllocPBackgroundIDBRequestChild(const RequestParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBCursorChild*
|
||||
AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
SendDeleteMe() MOZ_DELETE;
|
||||
};
|
||||
|
||||
class BackgroundVersionChangeTransactionChild MOZ_FINAL
|
||||
: public BackgroundTransactionBase
|
||||
, public PBackgroundIDBVersionChangeTransactionChild
|
||||
{
|
||||
friend class BackgroundDatabaseChild;
|
||||
|
||||
IDBOpenDBRequest* mOpenDBRequest;
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
virtual void
|
||||
AssertIsOnOwningThread() const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
private:
|
||||
// Only created by BackgroundDatabaseChild.
|
||||
BackgroundVersionChangeTransactionChild(IDBOpenDBRequest* aOpenDBRequest);
|
||||
|
||||
// Only destroyed by BackgroundDatabaseChild.
|
||||
~BackgroundVersionChangeTransactionChild();
|
||||
|
||||
// Only called by BackgroundDatabaseChild.
|
||||
void
|
||||
SetDOMTransaction(IDBTransaction* aDOMObject)
|
||||
{
|
||||
BackgroundTransactionBase::SetDOMTransaction(aDOMObject);
|
||||
}
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
RecvComplete(const nsresult& aResult) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBRequestChild*
|
||||
AllocPBackgroundIDBRequestChild(const RequestParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundIDBCursorChild*
|
||||
AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
SendDeleteMe() MOZ_DELETE;
|
||||
};
|
||||
|
||||
class BackgroundRequestChild MOZ_FINAL
|
||||
: public BackgroundRequestChildBase
|
||||
, public PBackgroundIDBRequestChild
|
||||
{
|
||||
friend class BackgroundTransactionChild;
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsTArray<nsRefPtr<FileInfo>> mFileInfos;
|
||||
|
||||
public:
|
||||
BackgroundRequestChild(IDBRequest* aRequest);
|
||||
|
||||
void
|
||||
HoldFileInfosUntilComplete(nsTArray<nsRefPtr<FileInfo>>& aFileInfos);
|
||||
|
||||
private:
|
||||
// Only destroyed by BackgroundTransactionChild or
|
||||
// BackgroundVersionChangeTransactionChild.
|
||||
~BackgroundRequestChild();
|
||||
|
||||
void
|
||||
MaybeFinishTransactionEarly();
|
||||
|
||||
bool
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const Key& aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const nsTArray<Key>& aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const SerializedStructuredCloneReadInfo& aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(const nsTArray<SerializedStructuredCloneReadInfo>& aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(JS::Handle<JS::Value> aResponse);
|
||||
|
||||
bool
|
||||
HandleResponse(uint64_t aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
Recv__delete__(const RequestResponse& aResponse) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class BackgroundCursorChild MOZ_FINAL
|
||||
: public PBackgroundIDBCursorChild
|
||||
{
|
||||
friend class BackgroundTransactionChild;
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
|
||||
class DelayedDeleteRunnable;
|
||||
|
||||
IDBRequest* mRequest;
|
||||
IDBTransaction* mTransaction;
|
||||
IDBObjectStore* mObjectStore;
|
||||
IDBIndex* mIndex;
|
||||
IDBCursor* mCursor;
|
||||
|
||||
// These are only set while a request is in progress.
|
||||
nsRefPtr<IDBRequest> mStrongRequest;
|
||||
nsRefPtr<IDBCursor> mStrongCursor;
|
||||
|
||||
Direction mDirection;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRThread* mOwningThread;
|
||||
#endif
|
||||
|
||||
public:
|
||||
BackgroundCursorChild(IDBRequest* aRequest,
|
||||
IDBObjectStore* aObjectStore,
|
||||
Direction aDirection);
|
||||
|
||||
BackgroundCursorChild(IDBRequest* aRequest,
|
||||
IDBIndex* aIndex,
|
||||
Direction aDirection);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void
|
||||
SendContinueInternal(const CursorRequestParams& aParams);
|
||||
|
||||
void
|
||||
SendDeleteMeInternal();
|
||||
|
||||
private:
|
||||
// Only destroyed by BackgroundTransactionChild or
|
||||
// BackgroundVersionChangeTransactionChild.
|
||||
~BackgroundCursorChild();
|
||||
|
||||
void
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
void
|
||||
HandleResponse(const void_t& aResponse);
|
||||
|
||||
void
|
||||
HandleResponse(const ObjectStoreCursorResponse& aResponse);
|
||||
|
||||
void
|
||||
HandleResponse(const ObjectStoreKeyCursorResponse& aResponse);
|
||||
|
||||
void
|
||||
HandleResponse(const IndexCursorResponse& aResponse);
|
||||
|
||||
void
|
||||
HandleResponse(const IndexKeyCursorResponse& aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvResponse(const CursorResponse& aResponse) MOZ_OVERRIDE;
|
||||
|
||||
// Force callers to use SendContinueInternal.
|
||||
bool
|
||||
SendContinue(const CursorRequestParams& aParams) MOZ_DELETE;
|
||||
|
||||
bool
|
||||
SendDeleteMe() MOZ_DELETE;
|
||||
};
|
||||
|
||||
// XXX This doesn't belong here. However, we're not yet porting MutableFile
|
||||
// stuff to PBackground so this is necessary for the time being.
|
||||
void
|
||||
DispatchMutableFileResult(IDBRequest* aRequest,
|
||||
nsresult aResultCode,
|
||||
IDBMutableFile* aMutableFile);
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_actorschild_h__
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,67 @@
|
|||
/* 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_indexeddb_actorsparent_h__
|
||||
#define mozilla_dom_indexeddb_actorsparent_h__
|
||||
|
||||
template <class> struct already_AddRefed;
|
||||
class nsCString;
|
||||
class nsIPrincipal;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class PBackgroundParent;
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
|
||||
class TabParent;
|
||||
|
||||
namespace quota {
|
||||
|
||||
class Client;
|
||||
|
||||
} // namespace quota
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class OptionalWindowId;
|
||||
class PBackgroundIDBFactoryParent;
|
||||
class PIndexedDBPermissionRequestParent;
|
||||
|
||||
PBackgroundIDBFactoryParent*
|
||||
AllocPBackgroundIDBFactoryParent(mozilla::ipc::PBackgroundParent* aManager,
|
||||
const OptionalWindowId& aOptionalWindowId);
|
||||
|
||||
bool
|
||||
RecvPBackgroundIDBFactoryConstructor(mozilla::ipc::PBackgroundParent* aManager,
|
||||
PBackgroundIDBFactoryParent* aActor,
|
||||
const OptionalWindowId& aOptionalWindowId);
|
||||
|
||||
bool
|
||||
DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor);
|
||||
|
||||
PIndexedDBPermissionRequestParent*
|
||||
AllocPIndexedDBPermissionRequestParent(nsPIDOMWindow* aWindow,
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
bool
|
||||
RecvPIndexedDBPermissionRequestConstructor(
|
||||
PIndexedDBPermissionRequestParent* aActor);
|
||||
|
||||
bool
|
||||
DeallocPIndexedDBPermissionRequestParent(
|
||||
PIndexedDBPermissionRequestParent* aActor);
|
||||
|
||||
already_AddRefed<mozilla::dom::quota::Client>
|
||||
CreateQuotaClient();
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_actorsparent_h__
|
|
@ -1,710 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
||||
#include "IDBEvents.h"
|
||||
#include "IDBTransaction.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "ProfilerHelpers.h"
|
||||
#include "ReportInternalError.h"
|
||||
#include "TransactionThreadPool.h"
|
||||
|
||||
#include "ipc/IndexedDBChild.h"
|
||||
#include "ipc/IndexedDBParent.h"
|
||||
|
||||
using namespace mozilla;
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
|
||||
namespace {
|
||||
|
||||
IDBTransaction* gCurrentTransaction = nullptr;
|
||||
|
||||
const uint32_t kProgressHandlerGranularity = 1000;
|
||||
|
||||
class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
|
||||
explicit TransactionPoolEventTarget(IDBTransaction* aTransaction)
|
||||
: mTransaction(aTransaction)
|
||||
{ }
|
||||
|
||||
private:
|
||||
IDBTransaction* mTransaction;
|
||||
};
|
||||
|
||||
// This inline is just so that we always clear aBuffers appropriately even if
|
||||
// something fails.
|
||||
inline
|
||||
nsresult
|
||||
ConvertCloneReadInfosToArrayInternal(
|
||||
JSContext* aCx,
|
||||
nsTArray<StructuredCloneReadInfo>& aReadInfos,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
IDB_WARNING("Failed to make array!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
if (!aReadInfos.IsEmpty()) {
|
||||
if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
|
||||
IDB_WARNING("Failed to set array length!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
for (uint32_t index = 0, count = aReadInfos.Length(); index < count;
|
||||
index++) {
|
||||
StructuredCloneReadInfo& readInfo = aReadInfos[index];
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) {
|
||||
NS_WARNING("Failed to decode!");
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
if (!JS_SetElement(aCx, array, index, val)) {
|
||||
IDB_WARNING("Failed to set array element!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aResult.setObject(*array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
HelperBase::~HelperBase()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
IDBRequest* request;
|
||||
mRequest.forget(&request);
|
||||
|
||||
if (request) {
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
|
||||
|
||||
if (mainThread) {
|
||||
NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
HelperBase::WrapNative(JSContext* aCx,
|
||||
nsISupports* aNative,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
NS_ASSERTION(aNative, "Null pointer!");
|
||||
NS_ASSERTION(aResult.address(), "Null pointer!");
|
||||
NS_ASSERTION(mRequest, "Null request!");
|
||||
|
||||
nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult);
|
||||
IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HelperBase::ReleaseMainThreadObjects()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
mRequest = nullptr;
|
||||
}
|
||||
|
||||
AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase,
|
||||
IDBRequest* aRequest)
|
||||
: HelperBase(aRequest),
|
||||
mDatabase(aDatabase),
|
||||
mResultCode(NS_OK),
|
||||
mDispatched(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
}
|
||||
|
||||
AsyncConnectionHelper::AsyncConnectionHelper(IDBTransaction* aTransaction,
|
||||
IDBRequest* aRequest)
|
||||
: HelperBase(aRequest),
|
||||
mDatabase(aTransaction->mDatabase),
|
||||
mTransaction(aTransaction),
|
||||
mResultCode(NS_OK),
|
||||
mDispatched(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
}
|
||||
|
||||
AsyncConnectionHelper::~AsyncConnectionHelper()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
IDBDatabase* database;
|
||||
mDatabase.forget(&database);
|
||||
|
||||
IDBTransaction* transaction;
|
||||
mTransaction.forget(&transaction);
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
|
||||
|
||||
if (mainThread) {
|
||||
if (database) {
|
||||
NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(database));
|
||||
}
|
||||
if (transaction) {
|
||||
NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(transaction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable,
|
||||
mozIStorageProgressHandler)
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncConnectionHelper::Run()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "Run",
|
||||
js::ProfileEntry::Category::STORAGE);
|
||||
|
||||
if (mTransaction &&
|
||||
mTransaction->IsAborted()) {
|
||||
// Always fire a "error" event with ABORT_ERR if the transaction was
|
||||
// aborted, even if the request succeeded or failed with another error.
|
||||
mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
|
||||
}
|
||||
|
||||
IDBTransaction* oldTransaction = gCurrentTransaction;
|
||||
gCurrentTransaction = mTransaction;
|
||||
|
||||
ChildProcessSendResult sendResult =
|
||||
IndexedDatabaseManager::IsMainProcess() ?
|
||||
MaybeSendResponseToChildProcess(mResultCode) :
|
||||
Success_NotSent;
|
||||
|
||||
switch (sendResult) {
|
||||
case Success_Sent: {
|
||||
if (mRequest) {
|
||||
mRequest->NotifyHelperSentResultsToChildProcess(NS_OK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Success_NotSent: {
|
||||
if (mRequest) {
|
||||
nsresult rv = mRequest->NotifyHelperCompleted(this);
|
||||
if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
|
||||
mResultCode = rv;
|
||||
}
|
||||
|
||||
IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread "
|
||||
"response (rv = %lu)",
|
||||
"IDBRequest[%llu] MT Done",
|
||||
mRequest->GetSerialNumber(), mResultCode);
|
||||
}
|
||||
|
||||
// Call OnError if the database had an error or if the OnSuccess
|
||||
// handler has an error.
|
||||
if (NS_FAILED(mResultCode) ||
|
||||
NS_FAILED((mResultCode = OnSuccess()))) {
|
||||
OnError();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Success_ActorDisconnected: {
|
||||
// Nothing needs to be done here.
|
||||
break;
|
||||
}
|
||||
|
||||
case Error: {
|
||||
IDB_WARNING("MaybeSendResultsToChildProcess failed!");
|
||||
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
if (mRequest) {
|
||||
mRequest->NotifyHelperSentResultsToChildProcess(mResultCode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown value for ChildProcessSendResult!");
|
||||
}
|
||||
|
||||
NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
|
||||
gCurrentTransaction = oldTransaction;
|
||||
|
||||
if (mDispatched && mTransaction) {
|
||||
mTransaction->OnRequestFinished();
|
||||
}
|
||||
|
||||
ReleaseMainThreadObjects();
|
||||
|
||||
NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't "
|
||||
"call AsyncConnectionHelper::ReleaseMainThreadObjects!");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
|
||||
PROFILER_LABEL("AsyncConnectionHelper", "Run",
|
||||
js::ProfileEntry::Category::STORAGE);
|
||||
|
||||
IDB_PROFILER_MARK_IF(mRequest,
|
||||
"IndexedDB Request %llu: Beginning database work",
|
||||
"IDBRequest[%llu] DT Start",
|
||||
mRequest->GetSerialNumber());
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
|
||||
if (mTransaction) {
|
||||
rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ASSERTION(connection, "This should never be null!");
|
||||
}
|
||||
}
|
||||
|
||||
bool setProgressHandler = false;
|
||||
if (connection) {
|
||||
rv = connection->SetProgressHandler(kProgressHandlerGranularity, this,
|
||||
getter_AddRefs(mOldProgressHandler));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
setProgressHandler = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool hasSavepoint = false;
|
||||
if (mDatabase) {
|
||||
QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
|
||||
|
||||
// Make the first savepoint.
|
||||
if (mTransaction) {
|
||||
if (!(hasSavepoint = mTransaction->StartSavepoint())) {
|
||||
NS_WARNING("Failed to make savepoint!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mResultCode = DoDatabaseWork(connection);
|
||||
|
||||
if (mDatabase) {
|
||||
// Release or roll back the savepoint depending on the error code.
|
||||
if (hasSavepoint) {
|
||||
NS_ASSERTION(mTransaction, "Huh?!");
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mTransaction->ReleaseSavepoint();
|
||||
}
|
||||
else {
|
||||
mTransaction->RollbackSavepoint();
|
||||
}
|
||||
}
|
||||
|
||||
// Don't unset this until we're sure that all SQLite activity has
|
||||
// completed!
|
||||
QuotaManager::SetCurrentWindow(nullptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated"
|
||||
// and we should fail with RECOVERABLE_ERR.
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR;
|
||||
}
|
||||
else {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (setProgressHandler) {
|
||||
nsCOMPtr<mozIStorageProgressHandler> handler;
|
||||
rv = connection->RemoveProgressHandler(getter_AddRefs(handler));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!");
|
||||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)),
|
||||
"Mismatch!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IDB_PROFILER_MARK_IF(mRequest,
|
||||
"IndexedDB Request %llu: Finished database work "
|
||||
"(rv = %lu)",
|
||||
"IDBRequest[%llu] DT Done", mRequest->GetSerialNumber(),
|
||||
mResultCode);
|
||||
|
||||
return NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncConnectionHelper::OnProgress(mozIStorageConnection* aConnection,
|
||||
bool* _retval)
|
||||
{
|
||||
if (mDatabase && mDatabase->IsInvalidated()) {
|
||||
// Someone is trying to delete the database file. Exit lightningfast!
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mOldProgressHandler) {
|
||||
return mOldProgressHandler->OnProgress(aConnection, _retval);
|
||||
}
|
||||
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsresult rv = Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->OnNewRequest();
|
||||
}
|
||||
|
||||
mDispatched = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::DispatchToTransactionPool()
|
||||
{
|
||||
NS_ASSERTION(mTransaction, "Only ok to call this with a transaction!");
|
||||
TransactionPoolEventTarget target(mTransaction);
|
||||
return Dispatch(&target);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aTransaction || !gCurrentTransaction,
|
||||
"Stepping on another transaction!");
|
||||
|
||||
gCurrentTransaction = aTransaction;
|
||||
}
|
||||
|
||||
// static
|
||||
IDBTransaction*
|
||||
AsyncConnectionHelper::GetCurrentTransaction()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
return gCurrentTransaction;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::Init()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEvent>
|
||||
AsyncConnectionHelper::CreateSuccessEvent(mozilla::dom::EventTarget* aOwner)
|
||||
{
|
||||
return CreateGenericEvent(mRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR),
|
||||
eDoesNotBubble, eNotCancelable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::OnSuccess()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(mRequest, "Null request!");
|
||||
|
||||
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnSuccess",
|
||||
js::ProfileEntry::Category::STORAGE);
|
||||
|
||||
nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest);
|
||||
if (!event) {
|
||||
IDB_WARNING("Failed to create event!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
bool dummy;
|
||||
nsresult rv = mRequest->DispatchEvent(event, &dummy);
|
||||
IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
WidgetEvent* internalEvent = event->GetInternalNSEvent();
|
||||
NS_ASSERTION(internalEvent, "This should never be null!");
|
||||
|
||||
NS_ASSERTION(!mTransaction ||
|
||||
mTransaction->IsOpen() ||
|
||||
mTransaction->IsAborted(),
|
||||
"How else can this be closed?!");
|
||||
|
||||
if (internalEvent->mFlags.mExceptionHasBeenRisen &&
|
||||
mTransaction &&
|
||||
mTransaction->IsOpen()) {
|
||||
rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AsyncConnectionHelper::OnError()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(mRequest, "Null request!");
|
||||
|
||||
PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnError",
|
||||
js::ProfileEntry::Category::STORAGE);
|
||||
|
||||
// Make an error event and fire it at the target.
|
||||
nsRefPtr<nsIDOMEvent> event =
|
||||
CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble,
|
||||
eCancelable);
|
||||
if (!event) {
|
||||
NS_ERROR("Failed to create event!");
|
||||
return;
|
||||
}
|
||||
|
||||
bool doDefault;
|
||||
nsresult rv = mRequest->DispatchEvent(event, &doDefault);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ASSERTION(!mTransaction ||
|
||||
mTransaction->IsOpen() ||
|
||||
mTransaction->IsAborted(),
|
||||
"How else can this be closed?!");
|
||||
|
||||
WidgetEvent* internalEvent = event->GetInternalNSEvent();
|
||||
NS_ASSERTION(internalEvent, "This should never be null!");
|
||||
|
||||
if (internalEvent->mFlags.mExceptionHasBeenRisen &&
|
||||
mTransaction &&
|
||||
mTransaction->IsOpen() &&
|
||||
NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) {
|
||||
NS_WARNING("Failed to abort transaction!");
|
||||
}
|
||||
|
||||
if (doDefault &&
|
||||
mTransaction &&
|
||||
mTransaction->IsOpen() &&
|
||||
NS_FAILED(mTransaction->Abort(mRequest))) {
|
||||
NS_WARNING("Failed to abort transaction!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_WARNING("DispatchEvent failed!");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::GetSuccessResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
aVal.setUndefined();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AsyncConnectionHelper::ReleaseMainThreadObjects()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
mDatabase = nullptr;
|
||||
mTransaction = nullptr;
|
||||
|
||||
HelperBase::ReleaseMainThreadObjects();
|
||||
}
|
||||
|
||||
AsyncConnectionHelper::ChildProcessSendResult
|
||||
AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
|
||||
// If there's no request, there could never have been an actor, and so there
|
||||
// is nothing to do.
|
||||
if (!mRequest) {
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
IDBTransaction* trans = GetCurrentTransaction();
|
||||
// We may not have a transaction, e.g. for deleteDatabase
|
||||
if (!trans) {
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
// Are we shutting down the child?
|
||||
IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent();
|
||||
if (dbActor && dbActor->IsDisconnected()) {
|
||||
return Success_ActorDisconnected;
|
||||
}
|
||||
|
||||
IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
|
||||
if (!actor) {
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child "
|
||||
"process (rv = %lu)",
|
||||
"IDBRequest[%llu] MT Done",
|
||||
mRequest->GetSerialNumber(), aResultCode);
|
||||
|
||||
return SendResponseToChildProcess(aResultCode);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncConnectionHelper::OnParentProcessRequestComplete(
|
||||
const ResponseValue& aResponseValue)
|
||||
{
|
||||
NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
|
||||
if (aResponseValue.type() == ResponseValue::Tnsresult) {
|
||||
NS_ASSERTION(NS_FAILED(aResponseValue.get_nsresult()), "Huh?");
|
||||
SetError(aResponseValue.get_nsresult());
|
||||
}
|
||||
else {
|
||||
nsresult rv = UnpackResponseFromParentProcess(aResponseValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return Run();
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
AsyncConnectionHelper::ConvertToArrayAndCleanup(
|
||||
JSContext* aCx,
|
||||
nsTArray<StructuredCloneReadInfo>& aReadInfos,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
NS_ASSERTION(aResult.address(), "Null pointer!");
|
||||
|
||||
nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult);
|
||||
|
||||
for (uint32_t index = 0; index < aReadInfos.Length(); index++) {
|
||||
aReadInfos[index].mCloneBuffer.clear();
|
||||
}
|
||||
aReadInfos.Clear();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(MozExternalRefCountType)
|
||||
StackBasedEventTarget::AddRef()
|
||||
{
|
||||
NS_NOTREACHED("Don't call me!");
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(MozExternalRefCountType)
|
||||
StackBasedEventTarget::Release()
|
||||
{
|
||||
NS_NOTREACHED("Don't call me!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
StackBasedEventTarget::QueryInterface(REFNSIID aIID,
|
||||
void** aInstancePtr)
|
||||
{
|
||||
NS_NOTREACHED("Don't call me!");
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_ASSERTION(aRunnable, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||
DebugOnly<nsresult> rv =
|
||||
runnable->Run();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
||||
{
|
||||
*aIsOnCurrentThread = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_ASSERTION(aRunnable, "Null pointer!");
|
||||
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!");
|
||||
|
||||
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
|
||||
NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
||||
{
|
||||
*aIsOnCurrentThread = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> runnable = aRunnable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
||||
{
|
||||
*aIsOnCurrentThread = true;
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,257 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_asyncconnectionhelper_h__
|
||||
#define mozilla_dom_indexeddb_asyncconnectionhelper_h__
|
||||
|
||||
// Only meant to be included in IndexedDB source files, not exported.
|
||||
#include "DatabaseInfo.h"
|
||||
#include "IndexedDatabase.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBRequest.h"
|
||||
|
||||
#include "mozIStorageProgressHandler.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class AutoSetCurrentTransaction;
|
||||
class IDBTransaction;
|
||||
|
||||
namespace ipc {
|
||||
class ResponseValue;
|
||||
}
|
||||
|
||||
// A common base class for AsyncConnectionHelper and OpenDatabaseHelper that
|
||||
// IDBRequest can use.
|
||||
class HelperBase : public nsIRunnable
|
||||
{
|
||||
friend class IDBRequest;
|
||||
|
||||
public:
|
||||
|
||||
virtual nsresult GetResultCode() = 0;
|
||||
|
||||
virtual nsresult GetSuccessResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal) = 0;
|
||||
|
||||
IDBRequest* GetRequest() const
|
||||
{
|
||||
return mRequest;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit HelperBase(IDBRequest* aRequest)
|
||||
: mRequest(aRequest)
|
||||
{ }
|
||||
|
||||
virtual ~HelperBase();
|
||||
|
||||
/**
|
||||
* Helper to wrap a native into a jsval. Uses the global object of the request
|
||||
* to parent the native.
|
||||
*/
|
||||
nsresult WrapNative(JSContext* aCx,
|
||||
nsISupports* aNative,
|
||||
JS::MutableHandle<JS::Value> aResult);
|
||||
|
||||
/**
|
||||
* Gives the subclass a chance to release any objects that must be released
|
||||
* on the main thread, regardless of success or failure. Subclasses that
|
||||
* implement this method *MUST* call the base class implementation as well.
|
||||
*/
|
||||
virtual void ReleaseMainThreadObjects();
|
||||
|
||||
nsRefPtr<IDBRequest> mRequest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Must be subclassed. The subclass must implement DoDatabaseWork. It may then
|
||||
* choose to implement OnSuccess and OnError depending on the needs of the
|
||||
* subclass. If the default implementation of OnSuccess is desired then the
|
||||
* subclass can implement GetSuccessResult to properly set the result of the
|
||||
* success event. Call Dispatch to start the database operation. Must be created
|
||||
* and Dispatched from the main thread only. Target thread may not be the main
|
||||
* thread.
|
||||
*/
|
||||
class AsyncConnectionHelper : public HelperBase,
|
||||
public mozIStorageProgressHandler
|
||||
{
|
||||
friend class AutoSetCurrentTransaction;
|
||||
|
||||
public:
|
||||
typedef ipc::ResponseValue ResponseValue;
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_MOZISTORAGEPROGRESSHANDLER
|
||||
|
||||
virtual nsresult Dispatch(nsIEventTarget* aDatabaseThread);
|
||||
|
||||
// Only for transactions!
|
||||
nsresult DispatchToTransactionPool();
|
||||
|
||||
void SetError(nsresult aErrorCode)
|
||||
{
|
||||
NS_ASSERTION(NS_FAILED(aErrorCode), "Not a failure code!");
|
||||
mResultCode = aErrorCode;
|
||||
}
|
||||
|
||||
static IDBTransaction* GetCurrentTransaction();
|
||||
|
||||
bool HasTransaction() const
|
||||
{
|
||||
return !!mTransaction;
|
||||
}
|
||||
|
||||
IDBTransaction* GetTransaction() const
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
virtual nsresult GetResultCode() MOZ_OVERRIDE
|
||||
{
|
||||
return mResultCode;
|
||||
}
|
||||
|
||||
enum ChildProcessSendResult
|
||||
{
|
||||
// The result was successfully sent to the child process
|
||||
Success_Sent = 0,
|
||||
|
||||
// The result was not sent, because this is not an out-of-process request.
|
||||
Success_NotSent,
|
||||
|
||||
// The result was not sent, because the actor has been disconnected
|
||||
// (if the child process has shut down or crashed).
|
||||
Success_ActorDisconnected,
|
||||
|
||||
// An error occurred.
|
||||
Error
|
||||
};
|
||||
|
||||
ChildProcessSendResult
|
||||
MaybeSendResponseToChildProcess(nsresult aResultCode);
|
||||
|
||||
virtual nsresult OnParentProcessRequestComplete(
|
||||
const ResponseValue& aResponseValue);
|
||||
|
||||
virtual nsresult
|
||||
UnpackResponseFromParentProcess(const ResponseValue& aResponseValue) = 0;
|
||||
|
||||
protected:
|
||||
AsyncConnectionHelper(IDBDatabase* aDatabase,
|
||||
IDBRequest* aRequest);
|
||||
|
||||
AsyncConnectionHelper(IDBTransaction* aTransaction,
|
||||
IDBRequest* aRequest);
|
||||
|
||||
virtual ~AsyncConnectionHelper();
|
||||
|
||||
/**
|
||||
* This is called on the main thread after Dispatch is called but before the
|
||||
* runnable is actually dispatched to the database thread. Allows the subclass
|
||||
* to initialize itself.
|
||||
*/
|
||||
virtual nsresult Init();
|
||||
|
||||
/**
|
||||
* This callback is run on the database thread.
|
||||
*/
|
||||
virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection) = 0;
|
||||
|
||||
/**
|
||||
* This function returns the event to be dispatched at the request when
|
||||
* OnSuccess is called. A subclass can override this to fire an event other
|
||||
* than "success" at the request.
|
||||
*/
|
||||
virtual already_AddRefed<nsIDOMEvent> CreateSuccessEvent(
|
||||
mozilla::dom::EventTarget* aOwner);
|
||||
|
||||
/**
|
||||
* This callback is run on the main thread if DoDatabaseWork returned NS_OK.
|
||||
* The default implementation fires a "success" DOM event with its target set
|
||||
* to the request. Returning anything other than NS_OK from the OnSuccess
|
||||
* callback will trigger the OnError callback.
|
||||
*/
|
||||
virtual nsresult OnSuccess();
|
||||
|
||||
/**
|
||||
* This callback is run on the main thread if DoDatabaseWork or OnSuccess
|
||||
* returned an error code. The default implementation fires an "error" DOM
|
||||
* event with its target set to the request.
|
||||
*/
|
||||
virtual void OnError();
|
||||
|
||||
/**
|
||||
* This function is called by the request on the main thread when script
|
||||
* accesses the result property of the request.
|
||||
*/
|
||||
virtual nsresult GetSuccessResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Gives the subclass a chance to release any objects that must be released
|
||||
* on the main thread, regardless of success or failure. Subclasses that
|
||||
* implement this method *MUST* call the base class implementation as well.
|
||||
*/
|
||||
virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Helper to make a JS array object out of an array of clone buffers.
|
||||
*/
|
||||
static nsresult ConvertToArrayAndCleanup(
|
||||
JSContext* aCx,
|
||||
nsTArray<StructuredCloneReadInfo>& aReadInfos,
|
||||
JS::MutableHandle<JS::Value> aResult);
|
||||
|
||||
/**
|
||||
* This should only be called by AutoSetCurrentTransaction.
|
||||
*/
|
||||
static void SetCurrentTransaction(IDBTransaction* aTransaction);
|
||||
|
||||
/**
|
||||
* Allows the subclass to send its results to the child process. Will only
|
||||
* be called if all of the IPC infrastructure is available (there is an
|
||||
* actor, the child is stil alive and hasn't begun shutting down).
|
||||
*/
|
||||
virtual ChildProcessSendResult
|
||||
SendResponseToChildProcess(nsresult aResultCode) = 0;
|
||||
|
||||
protected:
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
private:
|
||||
nsCOMPtr<mozIStorageProgressHandler> mOldProgressHandler;
|
||||
nsresult mResultCode;
|
||||
bool mDispatched;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS StackBasedEventTarget : public nsIEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS ImmediateRunEventTarget : public StackBasedEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS NoDispatchEventTarget : public StackBasedEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_asyncconnectionhelper_h__
|
|
@ -1,220 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#include "CheckPermissionsHelper.h"
|
||||
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#include "CheckQuotaHelper.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "IndexedDatabaseManager.h"
|
||||
|
||||
#define PERMISSION_INDEXEDDB "indexedDB"
|
||||
#define TOPIC_PERMISSIONS_PROMPT "indexedDB-permissions-prompt"
|
||||
#define TOPIC_PERMISSIONS_RESPONSE "indexedDB-permissions-response"
|
||||
|
||||
// This is a little confusing, but our default behavior (UNKNOWN_ACTION) is to
|
||||
// allow access without a prompt. If the "indexedDB" permission is set to
|
||||
// ALLOW_ACTION then we will issue a prompt before allowing access. Otherwise
|
||||
// (DENY_ACTION) we deny access.
|
||||
#define PERMISSION_ALLOWED nsIPermissionManager::UNKNOWN_ACTION
|
||||
#define PERMISSION_DENIED nsIPermissionManager::DENY_ACTION
|
||||
#define PERMISSION_PROMPT nsIPermissionManager::ALLOW_ACTION
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::services;
|
||||
using mozilla::dom::quota::CheckQuotaHelper;
|
||||
|
||||
namespace {
|
||||
|
||||
inline
|
||||
uint32_t
|
||||
GetIndexedDBPermissions(nsIDOMWindow* aWindow)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(aWindow, "Chrome shouldn't check the permission!");
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(aWindow));
|
||||
NS_ENSURE_TRUE(sop, nsIPermissionManager::DENY_ACTION);
|
||||
|
||||
NS_ASSERTION(!nsContentUtils::IsSystemPrincipal(sop->GetPrincipal()),
|
||||
"Chrome windows shouldn't check the permission!");
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
|
||||
if (loadContext && loadContext->UsePrivateBrowsing()) {
|
||||
// TODO Support private browsing indexedDB?
|
||||
NS_WARNING("IndexedDB may not be used while in private browsing mode!");
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager = GetPermissionManager();
|
||||
NS_ENSURE_TRUE(permissionManager, PERMISSION_DENIED);
|
||||
|
||||
uint32_t permission;
|
||||
nsresult rv =
|
||||
permissionManager->TestPermissionFromPrincipal(sop->GetPrincipal(),
|
||||
PERMISSION_INDEXEDDB,
|
||||
&permission);
|
||||
NS_ENSURE_SUCCESS(rv, PERMISSION_DENIED);
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMPL_ISUPPORTS(CheckPermissionsHelper, nsIRunnable,
|
||||
nsIInterfaceRequestor,
|
||||
nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CheckPermissionsHelper::Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
uint32_t permission = mHasPrompted ?
|
||||
mPromptResult :
|
||||
GetIndexedDBPermissions(mWindow);
|
||||
|
||||
nsresult rv;
|
||||
if (mHasPrompted) {
|
||||
// Add permissions to the database, but only if we are in the parent
|
||||
// process (if we are in the child process, we have already
|
||||
// set the permission when the prompt was shown in the parent, as
|
||||
// we cannot set the permission from the child).
|
||||
if (permission != PERMISSION_PROMPT &&
|
||||
IndexedDatabaseManager::IsMainProcess()) {
|
||||
NS_ASSERTION(mWindow, "Null window!");
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(mWindow);
|
||||
NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
|
||||
|
||||
nsIPrincipal* windowPrincipal = sop->GetPrincipal();
|
||||
NS_ASSERTION(windowPrincipal, "Null principal!");
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager = GetPermissionManager();
|
||||
NS_ENSURE_STATE(permissionManager);
|
||||
|
||||
rv = permissionManager->AddFromPrincipal(windowPrincipal,
|
||||
PERMISSION_INDEXEDDB, permission,
|
||||
nsIPermissionManager::EXPIRE_NEVER,
|
||||
0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
else if (permission == PERMISSION_PROMPT && mPromptAllowed) {
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
rv = obs->NotifyObservers(static_cast<nsIRunnable*>(this),
|
||||
TOPIC_PERMISSIONS_PROMPT, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<OpenDatabaseHelper> helper;
|
||||
helper.swap(mHelper);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
window.swap(mWindow);
|
||||
|
||||
if (permission == PERMISSION_ALLOWED) {
|
||||
// If we're running from a window then we should check the quota permission
|
||||
// as well. If we don't have a window then we're opening a chrome database
|
||||
// and the quota will be unlimited already.
|
||||
if (window) {
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(window);
|
||||
NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
|
||||
|
||||
nsIPrincipal* windowPrincipal = sop->GetPrincipal();
|
||||
NS_ASSERTION(windowPrincipal, "Null principal!");
|
||||
|
||||
uint32_t quotaPermission =
|
||||
CheckQuotaHelper::GetQuotaPermission(windowPrincipal);
|
||||
|
||||
if (quotaPermission == nsIPermissionManager::ALLOW_ACTION) {
|
||||
helper->SetUnlimitedQuotaAllowed();
|
||||
}
|
||||
}
|
||||
|
||||
return helper->DispatchToIOThread();
|
||||
}
|
||||
|
||||
NS_ASSERTION(permission == PERMISSION_PROMPT ||
|
||||
permission == PERMISSION_DENIED,
|
||||
"Unknown permission!");
|
||||
|
||||
helper->SetError(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
|
||||
|
||||
return helper->RunImmediately();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CheckPermissionsHelper::GetInterface(const nsIID& aIID,
|
||||
void** aResult)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
if (aIID.Equals(NS_GET_IID(nsIObserver))) {
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
|
||||
return mWindow->QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CheckPermissionsHelper::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!strcmp(aTopic, TOPIC_PERMISSIONS_RESPONSE), "Bad topic!");
|
||||
NS_ASSERTION(mPromptAllowed, "How did we get here?");
|
||||
|
||||
mHasPrompted = true;
|
||||
|
||||
nsresult rv;
|
||||
uint32_t promptResult = nsDependentString(aData).ToInteger(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Have to convert the permission we got from the user to our weird reversed
|
||||
// permission type.
|
||||
switch (promptResult) {
|
||||
case nsIPermissionManager::ALLOW_ACTION:
|
||||
mPromptResult = PERMISSION_ALLOWED;
|
||||
break;
|
||||
case nsIPermissionManager::DENY_ACTION:
|
||||
mPromptResult = PERMISSION_DENIED;
|
||||
break;
|
||||
case nsIPermissionManager::UNKNOWN_ACTION:
|
||||
mPromptResult = PERMISSION_PROMPT;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unknown permission type!");
|
||||
mPromptResult = PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
rv = NS_DispatchToCurrentThread(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_checkpermissionshelper_h__
|
||||
#define mozilla_dom_indexeddb_checkpermissionshelper_h__
|
||||
|
||||
// Only meant to be included in IndexedDB source files, not exported.
|
||||
#include "OpenDatabaseHelper.h"
|
||||
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
class nsIDOMWindow;
|
||||
class nsIThread;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class CheckPermissionsHelper MOZ_FINAL : public nsIRunnable,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
CheckPermissionsHelper(OpenDatabaseHelper* aHelper,
|
||||
nsIDOMWindow* aWindow)
|
||||
: mHelper(aHelper),
|
||||
mWindow(aWindow),
|
||||
// If we're trying to delete the database, we should never prompt the user.
|
||||
// Anything that would prompt is translated to denied.
|
||||
mPromptAllowed(!aHelper->mForDeletion),
|
||||
mHasPrompted(false),
|
||||
mPromptResult(0)
|
||||
{
|
||||
NS_ASSERTION(aHelper, "Null pointer!");
|
||||
NS_ASSERTION(aHelper->mPersistenceType == quota::PERSISTENCE_TYPE_PERSISTENT,
|
||||
"Checking permission for non persistent databases?!");
|
||||
}
|
||||
|
||||
private:
|
||||
~CheckPermissionsHelper() {}
|
||||
|
||||
nsRefPtr<OpenDatabaseHelper> mHelper;
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
bool mPromptAllowed;
|
||||
bool mHasPrompted;
|
||||
uint32_t mPromptResult;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_checkpermissionshelper_h__
|
|
@ -1,369 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/quota/UsageInfo.h"
|
||||
#include "mozilla/dom/quota/Utilities.h"
|
||||
|
||||
#include "IDBDatabase.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "TransactionThreadPool.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::quota::AssertIsOnIOThread;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
GetDatabaseBaseFilename(const nsAString& aFilename,
|
||||
nsAString& aDatabaseBaseFilename)
|
||||
{
|
||||
NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!");
|
||||
|
||||
NS_NAMED_LITERAL_STRING(sqlite, ".sqlite");
|
||||
|
||||
if (!StringEndsWith(aFilename, sqlite)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aDatabaseBaseFilename =
|
||||
Substring(aFilename, 0, aFilename.Length() - sqlite.Length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// This needs to be fully qualified to not confuse trace refcnt assertions.
|
||||
NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
|
||||
NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
|
||||
|
||||
nsresult
|
||||
Client::InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||
const nsACString& aOrigin, UsageInfo* aUsageInfo)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv =
|
||||
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We need to see if there are any files in the directory already. If they
|
||||
// are database files then we need to cleanup stored files (if it's needed)
|
||||
// and also get the usage.
|
||||
|
||||
nsAutoTArray<nsString, 20> subdirsToProcess;
|
||||
nsAutoTArray<nsCOMPtr<nsIFile>, 20> unknownFiles;
|
||||
nsTHashtable<nsStringHashKey> validSubdirs(20);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && (!aUsageInfo || !aUsageInfo->Canceled())) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
|
||||
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isDirectory) {
|
||||
if (!validSubdirs.GetEntry(leafName)) {
|
||||
subdirsToProcess.AppendElement(leafName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nsString dbBaseFilename;
|
||||
if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) {
|
||||
unknownFiles.AppendElement(file);
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> fmDirectory;
|
||||
rv = directory->Clone(getter_AddRefs(fmDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = fmDirectory->Append(dbBaseFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = FileManager::InitDirectory(fmDirectory, file, aPersistenceType, aGroup,
|
||||
aOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aUsageInfo) {
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
||||
|
||||
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
|
||||
uint64_t usage;
|
||||
rv = FileManager::GetUsage(fmDirectory, &usage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aUsageInfo->AppendToFileUsage(usage);
|
||||
}
|
||||
|
||||
validSubdirs.PutEntry(dbBaseFilename);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) {
|
||||
const nsString& subdir = subdirsToProcess[i];
|
||||
if (!validSubdirs.GetEntry(subdir)) {
|
||||
NS_WARNING("Unknown subdirectory found!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < unknownFiles.Length(); i++) {
|
||||
nsCOMPtr<nsIFile>& unknownFile = unknownFiles[i];
|
||||
|
||||
// Some temporary SQLite files could disappear, so we have to check if the
|
||||
// unknown file still exists.
|
||||
bool exists;
|
||||
rv = unknownFile->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
nsString leafName;
|
||||
unknownFile->GetLeafName(leafName);
|
||||
|
||||
// The journal file may exists even after db has been correctly opened.
|
||||
if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
|
||||
NS_WARNING("Unknown file found!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup, const nsACString& aOrigin,
|
||||
UsageInfo* aUsageInfo)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
NS_ASSERTION(aUsageInfo, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv =
|
||||
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const OriginOrPatternString& aOriginOrPattern)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->InvalidateFileManagers(aPersistenceType, aOriginOrPattern);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Client::ReleaseIOThreadObjects()
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->InvalidateAllFileManagers();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Client::IsTransactionServiceActivated()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
return !!TransactionThreadPool::Get();
|
||||
}
|
||||
|
||||
void
|
||||
Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!");
|
||||
NS_ASSERTION(aCallback, "Passed null callback!");
|
||||
|
||||
TransactionThreadPool* pool = TransactionThreadPool::Get();
|
||||
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
|
||||
|
||||
nsTArray<nsRefPtr<IDBDatabase> > databases(aStorages.Length());
|
||||
for (uint32_t index = 0; index < aStorages.Length(); index++) {
|
||||
IDBDatabase* database = IDBDatabase::FromStorage(aStorages[index]);
|
||||
if (!database) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
databases.AppendElement(database);
|
||||
}
|
||||
|
||||
pool->WaitForDatabasesToComplete(databases, aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aStorage, "Passed null storage!");
|
||||
|
||||
TransactionThreadPool* pool = TransactionThreadPool::Get();
|
||||
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
|
||||
|
||||
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
|
||||
NS_ASSERTION(database, "This shouldn't be null!");
|
||||
|
||||
pool->AbortTransactionsForDatabase(database);
|
||||
}
|
||||
|
||||
bool
|
||||
Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
TransactionThreadPool* pool = TransactionThreadPool::Get();
|
||||
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
|
||||
|
||||
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
|
||||
NS_ASSERTION(database, "This shouldn't be null!");
|
||||
|
||||
return pool->HasTransactionsForDatabase(database);
|
||||
}
|
||||
|
||||
void
|
||||
Client::ShutdownTransactionService()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
TransactionThreadPool::Shutdown();
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetDirectory(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin, nsIFile** aDirectory)
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never fail!");
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = quotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(directory, "What?");
|
||||
|
||||
rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
directory.forget(aDirectory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||
UsageInfo* aUsageInfo,
|
||||
bool aDatabaseFiles)
|
||||
{
|
||||
NS_ASSERTION(aDirectory, "Null pointer!");
|
||||
NS_ASSERTION(aUsageInfo, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!entries) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && !aUsageInfo->Canceled()) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file(do_QueryInterface(entry));
|
||||
NS_ASSERTION(file, "Don't know what this is!");
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isDirectory) {
|
||||
if (aDatabaseFiles) {
|
||||
rv = GetUsageForDirectoryInternal(file, aUsageInfo, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
|
||||
NS_WARNING("Unknown directory found!");
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
||||
|
||||
if (aDatabaseFiles) {
|
||||
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
}
|
||||
else {
|
||||
aUsageInfo->AppendToFileUsage(uint64_t(fileSize));
|
||||
}
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_client_h__
|
||||
#define mozilla_dom_indexeddb_client_h__
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#include "mozilla/dom/quota/Client.h"
|
||||
|
||||
#define JOURNAL_DIRECTORY_NAME "journals"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class Client : public mozilla::dom::quota::Client
|
||||
{
|
||||
typedef mozilla::dom::quota::OriginOrPatternString OriginOrPatternString;
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
typedef mozilla::dom::quota::UsageInfo UsageInfo;
|
||||
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType)
|
||||
AddRef() MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD_(MozExternalRefCountType)
|
||||
Release() MOZ_OVERRIDE;
|
||||
|
||||
virtual Type
|
||||
GetType() MOZ_OVERRIDE
|
||||
{
|
||||
return IDB;
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
InitOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const OriginOrPatternString& aOriginOrPattern)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
ReleaseIOThreadObjects() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
AbortTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
HasTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
ShutdownTransactionService() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
~Client() {}
|
||||
|
||||
nsresult
|
||||
GetDirectory(PersistenceType aPersistenceType, const nsACString& aOrigin,
|
||||
nsIFile** aDirectory);
|
||||
|
||||
nsresult
|
||||
GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||
UsageInfo* aUsageInfo,
|
||||
bool aDatabaseFiles);
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_client_h__
|
|
@ -1,269 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#include "DatabaseInfo.h"
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
typedef nsDataHashtable<nsCStringHashKey, DatabaseInfo*>
|
||||
DatabaseHash;
|
||||
|
||||
DatabaseHash* gDatabaseHash = nullptr;
|
||||
|
||||
PLDHashOperator
|
||||
EnumerateObjectStoreNames(const nsAString& aKey,
|
||||
ObjectStoreInfo* aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsTArray<nsString>* array = static_cast<nsTArray<nsString>*>(aUserArg);
|
||||
if (!array->InsertElementSorted(aData->name)) {
|
||||
NS_ERROR("Out of memory?");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
CloneObjectStoreInfo(const nsAString& aKey,
|
||||
ObjectStoreInfo* aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg);
|
||||
|
||||
nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
|
||||
|
||||
hash->Put(aKey, newInfo);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DatabaseInfo::~DatabaseInfo()
|
||||
{
|
||||
// Clones are never in the hash.
|
||||
if (!cloned) {
|
||||
DatabaseInfo::Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther)
|
||||
: nextAutoIncrementId(aOther.nextAutoIncrementId),
|
||||
comittedAutoIncrementId(aOther.comittedAutoIncrementId)
|
||||
{
|
||||
*static_cast<ObjectStoreInfoGuts*>(this) =
|
||||
static_cast<ObjectStoreInfoGuts&>(aOther);
|
||||
|
||||
// Doesn't copy the refcount
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
||||
IndexInfo::IndexInfo()
|
||||
: id(INT64_MIN),
|
||||
keyPath(0),
|
||||
unique(false),
|
||||
multiEntry(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexInfo);
|
||||
}
|
||||
|
||||
IndexInfo::IndexInfo(const IndexInfo& aOther)
|
||||
: name(aOther.name),
|
||||
id(aOther.id),
|
||||
keyPath(aOther.keyPath),
|
||||
unique(aOther.unique),
|
||||
multiEntry(aOther.multiEntry)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexInfo);
|
||||
}
|
||||
|
||||
IndexInfo::~IndexInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(IndexInfo);
|
||||
}
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo()
|
||||
: nextAutoIncrementId(0),
|
||||
comittedAutoIncrementId(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
ObjectStoreInfo::~ObjectStoreInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
IndexUpdateInfo::IndexUpdateInfo()
|
||||
: indexId(0),
|
||||
indexUnique(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexUpdateInfo);
|
||||
}
|
||||
|
||||
IndexUpdateInfo::IndexUpdateInfo(const IndexUpdateInfo& aOther)
|
||||
: indexId(aOther.indexId),
|
||||
indexUnique(aOther.indexUnique),
|
||||
value(aOther.value)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexUpdateInfo);
|
||||
}
|
||||
|
||||
IndexUpdateInfo::~IndexUpdateInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(IndexUpdateInfo);
|
||||
}
|
||||
|
||||
#endif /* NS_BUILD_REFCNT_LOGGING */
|
||||
|
||||
// static
|
||||
bool
|
||||
DatabaseInfo::Get(const nsACString& aId,
|
||||
DatabaseInfo** aInfo)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aId.IsEmpty(), "Bad id!");
|
||||
|
||||
if (gDatabaseHash &&
|
||||
gDatabaseHash->Get(aId, aInfo)) {
|
||||
NS_IF_ADDREF(*aInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
DatabaseInfo::Put(DatabaseInfo* aInfo)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aInfo, "Null pointer!");
|
||||
|
||||
if (!gDatabaseHash) {
|
||||
nsAutoPtr<DatabaseHash> databaseHash(new DatabaseHash());
|
||||
gDatabaseHash = databaseHash.forget();
|
||||
}
|
||||
|
||||
if (gDatabaseHash->Get(aInfo->id, nullptr)) {
|
||||
NS_ERROR("Already know about this database!");
|
||||
return false;
|
||||
}
|
||||
|
||||
gDatabaseHash->Put(aInfo->id, aInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
DatabaseInfo::Remove(const nsACString& aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gDatabaseHash) {
|
||||
gDatabaseHash->Remove(aId);
|
||||
|
||||
if (!gDatabaseHash->Count()) {
|
||||
delete gDatabaseHash;
|
||||
gDatabaseHash = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
aNames.Clear();
|
||||
if (objectStoreHash) {
|
||||
objectStoreHash->EnumerateRead(EnumerateObjectStoreNames, &aNames);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::ContainsStoreName(const nsAString& aName)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
return objectStoreHash && objectStoreHash->Get(aName, nullptr);
|
||||
}
|
||||
|
||||
ObjectStoreInfo*
|
||||
DatabaseInfo::GetObjectStore(const nsAString& aName)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (objectStoreHash) {
|
||||
return objectStoreHash->GetWeak(aName);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::PutObjectStore(ObjectStoreInfo* aInfo)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aInfo, "Null pointer!");
|
||||
|
||||
if (!objectStoreHash) {
|
||||
nsAutoPtr<ObjectStoreInfoHash> hash(new ObjectStoreInfoHash());
|
||||
objectStoreHash = hash.forget();
|
||||
}
|
||||
|
||||
if (objectStoreHash->Get(aInfo->name, nullptr)) {
|
||||
NS_ERROR("Already have an entry for this objectstore!");
|
||||
return false;
|
||||
}
|
||||
|
||||
objectStoreHash->Put(aInfo->name, aInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DatabaseInfo::RemoveObjectStore(const nsAString& aName)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!");
|
||||
|
||||
if (objectStoreHash) {
|
||||
objectStoreHash->Remove(aName);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<DatabaseInfo>
|
||||
DatabaseInfo::Clone()
|
||||
{
|
||||
nsRefPtr<DatabaseInfo> dbInfo(new DatabaseInfo());
|
||||
|
||||
dbInfo->cloned = true;
|
||||
dbInfo->name = name;
|
||||
dbInfo->group = group;
|
||||
dbInfo->origin = origin;
|
||||
dbInfo->version = version;
|
||||
dbInfo->persistenceType = persistenceType;
|
||||
dbInfo->id = id;
|
||||
dbInfo->filePath = filePath;
|
||||
dbInfo->nextObjectStoreId = nextObjectStoreId;
|
||||
dbInfo->nextIndexId = nextIndexId;
|
||||
|
||||
if (objectStoreHash) {
|
||||
dbInfo->objectStoreHash = new ObjectStoreInfoHash();
|
||||
objectStoreHash->EnumerateRead(CloneObjectStoreInfo,
|
||||
dbInfo->objectStoreHash);
|
||||
}
|
||||
|
||||
return dbInfo.forget();
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_databaseinfo_h__
|
||||
#define mozilla_dom_indexeddb_databaseinfo_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
#include "mozilla/dom/indexedDB/KeyPath.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class IndexedDBDatabaseChild;
|
||||
struct ObjectStoreInfo;
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, ObjectStoreInfo>
|
||||
ObjectStoreInfoHash;
|
||||
|
||||
struct DatabaseInfoGuts
|
||||
{
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
|
||||
DatabaseInfoGuts()
|
||||
: nextObjectStoreId(1), nextIndexId(1)
|
||||
{ }
|
||||
|
||||
bool operator==(const DatabaseInfoGuts& aOther) const
|
||||
{
|
||||
return this->name == aOther.name &&
|
||||
this->group == aOther.group &&
|
||||
this->origin == aOther.origin &&
|
||||
this->version == aOther.version &&
|
||||
this->persistenceType == aOther.persistenceType &&
|
||||
this->nextObjectStoreId == aOther.nextObjectStoreId &&
|
||||
this->nextIndexId == aOther.nextIndexId;
|
||||
};
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
nsString name;
|
||||
nsCString group;
|
||||
nsCString origin;
|
||||
uint64_t version;
|
||||
PersistenceType persistenceType;
|
||||
int64_t nextObjectStoreId;
|
||||
int64_t nextIndexId;
|
||||
};
|
||||
|
||||
struct DatabaseInfo MOZ_FINAL : public DatabaseInfoGuts
|
||||
{
|
||||
DatabaseInfo()
|
||||
: cloned(false)
|
||||
{ }
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~DatabaseInfo();
|
||||
|
||||
public:
|
||||
static bool Get(const nsACString& aId,
|
||||
DatabaseInfo** aInfo);
|
||||
|
||||
static bool Put(DatabaseInfo* aInfo);
|
||||
|
||||
static void Remove(const nsACString& aId);
|
||||
|
||||
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
|
||||
bool ContainsStoreName(const nsAString& aName);
|
||||
|
||||
ObjectStoreInfo* GetObjectStore(const nsAString& aName);
|
||||
|
||||
bool PutObjectStore(ObjectStoreInfo* aInfo);
|
||||
|
||||
void RemoveObjectStore(const nsAString& aName);
|
||||
|
||||
already_AddRefed<DatabaseInfo> Clone();
|
||||
|
||||
nsCString id;
|
||||
nsString filePath;
|
||||
bool cloned;
|
||||
|
||||
nsAutoPtr<ObjectStoreInfoHash> objectStoreHash;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(DatabaseInfo)
|
||||
};
|
||||
|
||||
struct IndexInfo
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
IndexInfo();
|
||||
IndexInfo(const IndexInfo& aOther);
|
||||
~IndexInfo();
|
||||
#else
|
||||
IndexInfo()
|
||||
: id(INT64_MIN), keyPath(0), unique(false), multiEntry(false) { }
|
||||
#endif
|
||||
|
||||
bool operator==(const IndexInfo& aOther) const
|
||||
{
|
||||
return this->name == aOther.name &&
|
||||
this->id == aOther.id &&
|
||||
this->keyPath == aOther.keyPath &&
|
||||
this->unique == aOther.unique &&
|
||||
this->multiEntry == aOther.multiEntry;
|
||||
};
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
nsString name;
|
||||
int64_t id;
|
||||
KeyPath keyPath;
|
||||
bool unique;
|
||||
bool multiEntry;
|
||||
};
|
||||
|
||||
struct ObjectStoreInfoGuts
|
||||
{
|
||||
ObjectStoreInfoGuts()
|
||||
: id(0), keyPath(0), autoIncrement(false)
|
||||
{ }
|
||||
|
||||
bool operator==(const ObjectStoreInfoGuts& aOther) const
|
||||
{
|
||||
return this->name == aOther.name &&
|
||||
this->id == aOther.id;
|
||||
};
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
|
||||
// Constant members, can be gotten on any thread
|
||||
nsString name;
|
||||
int64_t id;
|
||||
KeyPath keyPath;
|
||||
bool autoIncrement;
|
||||
|
||||
// Main-thread only members. This must *not* be touched on the database
|
||||
// thread.
|
||||
nsTArray<IndexInfo> indexes;
|
||||
};
|
||||
|
||||
struct ObjectStoreInfo MOZ_FINAL : public ObjectStoreInfoGuts
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ObjectStoreInfo();
|
||||
#else
|
||||
ObjectStoreInfo()
|
||||
: nextAutoIncrementId(0), comittedAutoIncrementId(0) { }
|
||||
#endif
|
||||
|
||||
ObjectStoreInfo(ObjectStoreInfo& aOther);
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
~ObjectStoreInfo();
|
||||
#else
|
||||
~ObjectStoreInfo() {}
|
||||
#endif
|
||||
public:
|
||||
|
||||
// Database-thread members. After the ObjectStoreInfo has been initialized,
|
||||
// these can *only* be touced on the database thread.
|
||||
int64_t nextAutoIncrementId;
|
||||
int64_t comittedAutoIncrementId;
|
||||
|
||||
// This is threadsafe since the ObjectStoreInfos are created on the database
|
||||
// thread but then only used from the main thread. Ideal would be if we
|
||||
// could transfer ownership from the database thread to the main thread, but
|
||||
// we don't have that ability yet.
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ObjectStoreInfo)
|
||||
};
|
||||
|
||||
struct IndexUpdateInfo
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
IndexUpdateInfo();
|
||||
IndexUpdateInfo(const IndexUpdateInfo& aOther);
|
||||
~IndexUpdateInfo();
|
||||
#endif
|
||||
|
||||
bool operator==(const IndexUpdateInfo& aOther) const
|
||||
{
|
||||
return this->indexId == aOther.indexId &&
|
||||
this->indexUnique == aOther.indexUnique &&
|
||||
this->value == aOther.value;
|
||||
};
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
int64_t indexId;
|
||||
bool indexUnique;
|
||||
Key value;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_databaseinfo_h__
|
|
@ -5,68 +5,113 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FileInfo.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
#include "FileManager.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "nsError.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
using namespace mozilla::dom::quota;
|
||||
|
||||
namespace {
|
||||
|
||||
class CleanupFileRunnable MOZ_FINAL : public nsIRunnable
|
||||
template <typename IdType>
|
||||
class FileInfoImpl MOZ_FINAL
|
||||
: public FileInfo
|
||||
{
|
||||
~CleanupFileRunnable() {}
|
||||
IdType mFileId;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId);
|
||||
FileInfoImpl(FileManager* aFileManager, IdType aFileId)
|
||||
: FileInfo(aFileManager)
|
||||
, mFileId(aFileId)
|
||||
{
|
||||
MOZ_ASSERT(aFileManager);
|
||||
MOZ_ASSERT(aFileId > 0);
|
||||
}
|
||||
|
||||
private:
|
||||
~FileInfoImpl()
|
||||
{ }
|
||||
|
||||
virtual int64_t
|
||||
Id() const MOZ_OVERRIDE
|
||||
{
|
||||
return int64_t(mFileId);
|
||||
}
|
||||
};
|
||||
|
||||
class CleanupFileRunnable MOZ_FINAL
|
||||
: public nsRunnable
|
||||
{
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
int64_t mFileId;
|
||||
|
||||
public:
|
||||
static void
|
||||
DoCleanup(FileManager* aFileManager, int64_t aFileId);
|
||||
|
||||
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId)
|
||||
: mFileManager(aFileManager)
|
||||
, mFileId(aFileId)
|
||||
{
|
||||
MOZ_ASSERT(aFileManager);
|
||||
MOZ_ASSERT(aFileId > 0);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
private:
|
||||
~CleanupFileRunnable()
|
||||
{ }
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
FileInfo::FileInfo(FileManager* aFileManager)
|
||||
: mFileManager(aFileManager)
|
||||
{
|
||||
MOZ_ASSERT(aFileManager);
|
||||
}
|
||||
|
||||
FileInfo::~FileInfo()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
FileInfo*
|
||||
FileInfo::Create(FileManager* aFileManager, int64_t aId)
|
||||
{
|
||||
MOZ_ASSERT(aId > 0, "Wrong id!");
|
||||
MOZ_ASSERT(aFileManager);
|
||||
MOZ_ASSERT(aId > 0);
|
||||
|
||||
if (aId <= INT16_MAX) {
|
||||
return new FileInfo16(aFileManager, aId);
|
||||
return new FileInfoImpl<int16_t>(aFileManager, aId);
|
||||
}
|
||||
|
||||
if (aId <= INT32_MAX) {
|
||||
return new FileInfo32(aFileManager, aId);
|
||||
return new FileInfoImpl<int32_t>(aFileManager, aId);
|
||||
}
|
||||
|
||||
return new FileInfo64(aFileManager, aId);
|
||||
return new FileInfoImpl<int64_t>(aFileManager, aId);
|
||||
}
|
||||
|
||||
void
|
||||
FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
|
||||
FileInfo::GetReferences(int32_t* aRefCnt,
|
||||
int32_t* aDBRefCnt,
|
||||
int32_t* aSliceRefCnt)
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
NS_ERROR("Shouldn't be called after shutdown!");
|
||||
|
||||
if (aRefCnt) {
|
||||
*aRefCnt = -1;
|
||||
}
|
||||
|
||||
if (aDBRefCnt) {
|
||||
*aDBRefCnt = -1;
|
||||
}
|
||||
|
||||
if (aSliceRefCnt) {
|
||||
*aSliceRefCnt = -1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
|
||||
|
||||
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
|
||||
|
||||
|
@ -84,14 +129,31 @@ FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
|
|||
}
|
||||
|
||||
void
|
||||
FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
|
||||
int32_t aDelta, bool aClear)
|
||||
FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
|
||||
int32_t aDelta,
|
||||
bool aClear)
|
||||
{
|
||||
// XXX This can go away once DOM objects no longer hold FileInfo objects...
|
||||
// Looking at you, IDBMutableFile...
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
NS_ERROR("Shouldn't be called after shutdown!");
|
||||
MOZ_ASSERT(&aRefCount == &mRefCnt);
|
||||
MOZ_ASSERT(aDelta == 1 || aDelta == -1);
|
||||
MOZ_ASSERT(!aClear);
|
||||
|
||||
if (aDelta > 0) {
|
||||
++aRefCount;
|
||||
} else {
|
||||
nsrefcnt count = --aRefCount;
|
||||
if (!count) {
|
||||
mRefCnt = 1;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
|
||||
|
||||
bool needsCleanup;
|
||||
{
|
||||
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
|
||||
|
@ -117,40 +179,52 @@ FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
|
|||
void
|
||||
FileInfo::Cleanup()
|
||||
{
|
||||
nsRefPtr<CleanupFileRunnable> cleaner =
|
||||
new CleanupFileRunnable(mFileManager, Id());
|
||||
int64_t id = Id();
|
||||
|
||||
// IndexedDatabaseManager is main-thread only.
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(cleaner);
|
||||
nsRefPtr<CleanupFileRunnable> cleaner =
|
||||
new CleanupFileRunnable(mFileManager, id);
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(cleaner)));
|
||||
return;
|
||||
}
|
||||
|
||||
cleaner->Run();
|
||||
CleanupFileRunnable::DoCleanup(mFileManager, id);
|
||||
}
|
||||
|
||||
CleanupFileRunnable::CleanupFileRunnable(FileManager* aFileManager,
|
||||
int64_t aFileId)
|
||||
: mFileManager(aFileManager), mFileId(aFileId)
|
||||
// static
|
||||
void
|
||||
CleanupFileRunnable::DoCleanup(FileManager* aFileManager, int64_t aFileId)
|
||||
{
|
||||
}
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aFileManager);
|
||||
MOZ_ASSERT(aFileId > 0);
|
||||
|
||||
NS_IMPL_ISUPPORTS(CleanupFileRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CleanupFileRunnable::Run()
|
||||
{
|
||||
if (mozilla::dom::quota::QuotaManager::IsShuttingDown()) {
|
||||
return NS_OK;
|
||||
if (NS_WARN_IF(QuotaManager::IsShuttingDown())) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
|
||||
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, mFileId))) {
|
||||
if (NS_FAILED(mgr->AsyncDeleteFile(aFileManager, aFileId))) {
|
||||
NS_WARNING("Failed to delete file asynchronously!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(CleanupFileRunnable, nsRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CleanupFileRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DoCleanup(mFileManager, mFileId);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,112 +7,88 @@
|
|||
#ifndef mozilla_dom_indexeddb_fileinfo_h__
|
||||
#define mozilla_dom_indexeddb_fileinfo_h__
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "FileManager.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
class FileManager;
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
friend class FileManager;
|
||||
|
||||
public:
|
||||
explicit FileInfo(FileManager* aFileManager)
|
||||
: mFileManager(aFileManager)
|
||||
{ }
|
||||
|
||||
virtual ~FileInfo()
|
||||
{ }
|
||||
|
||||
static
|
||||
FileInfo* Create(FileManager* aFileManager, int64_t aId);
|
||||
|
||||
void AddRef()
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
++mRefCnt;
|
||||
}
|
||||
else {
|
||||
UpdateReferences(mRefCnt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
nsrefcnt count = --mRefCnt;
|
||||
if (count == 0) {
|
||||
mRefCnt = 1;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
else {
|
||||
UpdateReferences(mRefCnt, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateDBRefs(int32_t aDelta)
|
||||
{
|
||||
UpdateReferences(mDBRefCnt, aDelta);
|
||||
}
|
||||
|
||||
void ClearDBRefs()
|
||||
{
|
||||
UpdateReferences(mDBRefCnt, 0, true);
|
||||
}
|
||||
|
||||
void UpdateSliceRefs(int32_t aDelta)
|
||||
{
|
||||
UpdateReferences(mSliceRefCnt, aDelta);
|
||||
}
|
||||
|
||||
void GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
|
||||
int32_t* aSliceRefCnt);
|
||||
|
||||
FileManager* Manager() const
|
||||
{
|
||||
return mFileManager;
|
||||
}
|
||||
|
||||
virtual int64_t Id() const = 0;
|
||||
|
||||
private:
|
||||
void UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, int32_t aDelta,
|
||||
bool aClear = false);
|
||||
void Cleanup();
|
||||
|
||||
ThreadSafeAutoRefCnt mRefCnt;
|
||||
ThreadSafeAutoRefCnt mDBRefCnt;
|
||||
ThreadSafeAutoRefCnt mSliceRefCnt;
|
||||
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
|
||||
public:
|
||||
static
|
||||
FileInfo* Create(FileManager* aFileManager, int64_t aId);
|
||||
|
||||
explicit FileInfo(FileManager* aFileManager);
|
||||
|
||||
void
|
||||
AddRef()
|
||||
{
|
||||
UpdateReferences(mRefCnt, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Release()
|
||||
{
|
||||
UpdateReferences(mRefCnt, -1);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateDBRefs(int32_t aDelta)
|
||||
{
|
||||
UpdateReferences(mDBRefCnt, aDelta);
|
||||
}
|
||||
|
||||
void
|
||||
ClearDBRefs()
|
||||
{
|
||||
UpdateReferences(mDBRefCnt, 0, true);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateSliceRefs(int32_t aDelta)
|
||||
{
|
||||
UpdateReferences(mSliceRefCnt, aDelta);
|
||||
}
|
||||
|
||||
void
|
||||
GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt, int32_t* aSliceRefCnt);
|
||||
|
||||
FileManager*
|
||||
Manager() const
|
||||
{
|
||||
return mFileManager;
|
||||
}
|
||||
|
||||
virtual int64_t
|
||||
Id() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~FileInfo();
|
||||
|
||||
private:
|
||||
void
|
||||
UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
|
||||
int32_t aDelta,
|
||||
bool aClear = false);
|
||||
|
||||
void
|
||||
Cleanup();
|
||||
};
|
||||
|
||||
#define FILEINFO_SUBCLASS(_bits) \
|
||||
class FileInfo##_bits : public FileInfo \
|
||||
{ \
|
||||
public: \
|
||||
FileInfo##_bits(FileManager* aFileManager, int##_bits##_t aId) \
|
||||
: FileInfo(aFileManager), mId(aId) \
|
||||
{ } \
|
||||
\
|
||||
virtual int64_t Id() const \
|
||||
{ \
|
||||
return mId; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
int##_bits##_t mId; \
|
||||
};
|
||||
|
||||
FILEINFO_SUBCLASS(16)
|
||||
FILEINFO_SUBCLASS(32)
|
||||
FILEINFO_SUBCLASS(64)
|
||||
|
||||
#undef FILEINFO_SUBCLASS
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_fileinfo_h__
|
||||
|
|
|
@ -1,433 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set 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/. */
|
||||
|
||||
#include "FileManager.h"
|
||||
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include "mozilla/dom/quota/Utilities.h"
|
||||
#include "mozStorageCID.h"
|
||||
#include "mozStorageHelper.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "FileInfo.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "OpenDatabaseHelper.h"
|
||||
|
||||
#include "IndexedDatabaseInlines.h"
|
||||
#include <algorithm>
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::quota::AssertIsOnIOThread;
|
||||
|
||||
namespace {
|
||||
|
||||
PLDHashOperator
|
||||
EnumerateToTArray(const uint64_t& aKey,
|
||||
FileInfo* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
NS_ASSERTION(aUserArg, "Null pointer!");
|
||||
|
||||
nsTArray<FileInfo*>* array =
|
||||
static_cast<nsTArray<FileInfo*>*>(aUserArg);
|
||||
|
||||
array->AppendElement(aValue);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
GetDirectoryFor(const nsAString& aDirectoryPath)
|
||||
{
|
||||
nsCOMPtr<nsIFile> directory =
|
||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(directory, nullptr);
|
||||
|
||||
nsresult rv = directory->InitWithPath(aDirectoryPath);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return directory.forget();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
nsresult
|
||||
FileManager::Init(nsIFile* aDirectory,
|
||||
mozIStorageConnection* aConnection)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
NS_ASSERTION(aDirectory, "Null directory!");
|
||||
NS_ASSERTION(aConnection, "Null connection!");
|
||||
|
||||
bool exists;
|
||||
nsresult rv = aDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
bool isDirectory;
|
||||
rv = aDirectory->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
|
||||
}
|
||||
else {
|
||||
rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = aDirectory->GetPath(mDirectoryPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> journalDirectory;
|
||||
rv = aDirectory->Clone(getter_AddRefs(journalDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = journalDirectory->Append(NS_LITERAL_STRING(JOURNAL_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = journalDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
bool isDirectory;
|
||||
rv = journalDirectory->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
rv = journalDirectory->GetPath(mJournalDirectoryPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, refcount "
|
||||
"FROM file"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasResult;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
|
||||
int64_t id;
|
||||
rv = stmt->GetInt64(0, &id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t refcount;
|
||||
rv = stmt->GetInt32(1, &refcount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(refcount, "This shouldn't happen!");
|
||||
|
||||
nsRefPtr<FileInfo> fileInfo = FileInfo::Create(this, id);
|
||||
fileInfo->mDBRefCnt = refcount;
|
||||
|
||||
mFileInfos.Put(id, fileInfo);
|
||||
|
||||
mLastFileId = std::max(id, mLastFileId);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileManager::Invalidate()
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
NS_ERROR("Shouldn't be called after shutdown!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsTArray<FileInfo*> fileInfos;
|
||||
{
|
||||
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
|
||||
|
||||
NS_ASSERTION(!mInvalidated, "Invalidate more than once?!");
|
||||
mInvalidated = true;
|
||||
|
||||
fileInfos.SetCapacity(mFileInfos.Count());
|
||||
mFileInfos.EnumerateRead(EnumerateToTArray, &fileInfos);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < fileInfos.Length(); i++) {
|
||||
FileInfo* fileInfo = fileInfos.ElementAt(i);
|
||||
fileInfo->ClearDBRefs();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
FileManager::GetDirectory()
|
||||
{
|
||||
return GetDirectoryFor(mDirectoryPath);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
FileManager::GetJournalDirectory()
|
||||
{
|
||||
return GetDirectoryFor(mJournalDirectoryPath);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
FileManager::EnsureJournalDirectory()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsCOMPtr<nsIFile> journalDirectory = GetDirectoryFor(mJournalDirectoryPath);
|
||||
NS_ENSURE_TRUE(journalDirectory, nullptr);
|
||||
|
||||
bool exists;
|
||||
nsresult rv = journalDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
if (exists) {
|
||||
bool isDirectory;
|
||||
rv = journalDirectory->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
NS_ENSURE_TRUE(isDirectory, nullptr);
|
||||
}
|
||||
else {
|
||||
rv = journalDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
}
|
||||
|
||||
return journalDirectory.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<FileInfo>
|
||||
FileManager::GetFileInfo(int64_t aId)
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
NS_ERROR("Shouldn't be called after shutdown!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FileInfo* fileInfo = nullptr;
|
||||
{
|
||||
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
|
||||
fileInfo = mFileInfos.Get(aId);
|
||||
}
|
||||
nsRefPtr<FileInfo> result = fileInfo;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<FileInfo>
|
||||
FileManager::GetNewFileInfo()
|
||||
{
|
||||
if (IndexedDatabaseManager::IsClosed()) {
|
||||
NS_ERROR("Shouldn't be called after shutdown!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoPtr<FileInfo> fileInfo;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
|
||||
|
||||
int64_t id = mLastFileId + 1;
|
||||
|
||||
fileInfo = FileInfo::Create(this, id);
|
||||
|
||||
mFileInfos.Put(id, fileInfo);
|
||||
|
||||
mLastFileId = id;
|
||||
}
|
||||
|
||||
nsRefPtr<FileInfo> result = fileInfo.forget();
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIFile>
|
||||
FileManager::GetFileForId(nsIFile* aDirectory, int64_t aId)
|
||||
{
|
||||
NS_ASSERTION(aDirectory, "Null pointer!");
|
||||
|
||||
nsAutoString id;
|
||||
id.AppendInt(aId);
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = aDirectory->Clone(getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
rv = file->Append(id);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
FileManager::InitDirectory(nsIFile* aDirectory,
|
||||
nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
NS_ASSERTION(aDirectory, "Null directory!");
|
||||
NS_ASSERTION(aDatabaseFile, "Null database file!");
|
||||
|
||||
bool exists;
|
||||
nsresult rv = aDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!exists) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isDirectory;
|
||||
rv = aDirectory->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIFile> journalDirectory;
|
||||
rv = aDirectory->Clone(getter_AddRefs(journalDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = journalDirectory->Append(NS_LITERAL_STRING(JOURNAL_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = journalDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
rv = journalDirectory->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = journalDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasElements;
|
||||
rv = entries->HasMoreElements(&hasElements);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasElements) {
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
rv = OpenDatabaseHelper::CreateDatabaseConnection(aDatabaseFile,
|
||||
aDirectory, NullString(), aPersistenceType, aGroup, aOrigin,
|
||||
getter_AddRefs(connection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageTransaction transaction(connection, false);
|
||||
|
||||
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE VIRTUAL TABLE fs USING filesystem;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT name, (name IN (SELECT id FROM file)) FROM fs "
|
||||
"WHERE path = :path"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString path;
|
||||
rv = journalDirectory->GetPath(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("path"), path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasResult;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
|
||||
nsString name;
|
||||
rv = stmt->GetString(0, name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t flag = stmt->AsInt32(1);
|
||||
|
||||
if (!flag) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = aDirectory->Clone(getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = file->Append(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_FAILED(file->Remove(false))) {
|
||||
NS_WARNING("Failed to remove orphaned file!");
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> journalFile;
|
||||
rv = journalDirectory->Clone(getter_AddRefs(journalFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = journalFile->Append(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_FAILED(journalFile->Remove(false))) {
|
||||
NS_WARNING("Failed to remove journal file!");
|
||||
}
|
||||
}
|
||||
|
||||
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE fs;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
|
||||
bool exists;
|
||||
nsresult rv = aDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!exists) {
|
||||
*aUsage = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t usage = 0;
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
|
||||
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
quota::IncrementUsage(&usage, uint64_t(fileSize));
|
||||
}
|
||||
|
||||
*aUsage = usage;
|
||||
return NS_OK;
|
||||
}
|
|
@ -7,21 +7,23 @@
|
|||
#ifndef mozilla_dom_indexeddb_filemanager_h__
|
||||
#define mozilla_dom_indexeddb_filemanager_h__
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsIFile;
|
||||
class mozIStorageConnection;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class FileInfo;
|
||||
|
||||
// Implemented in ActorsParent.cpp.
|
||||
class FileManager MOZ_FINAL
|
||||
{
|
||||
friend class FileInfo;
|
||||
|
@ -29,79 +31,6 @@ class FileManager MOZ_FINAL
|
|||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
|
||||
public:
|
||||
FileManager(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||
const nsACString& aOrigin, StoragePrivilege aPrivilege,
|
||||
const nsAString& aDatabaseName)
|
||||
: mPersistenceType(aPersistenceType), mGroup(aGroup), mOrigin(aOrigin),
|
||||
mPrivilege(aPrivilege), mDatabaseName(aDatabaseName), mLastFileId(0),
|
||||
mInvalidated(false)
|
||||
{ }
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
|
||||
|
||||
PersistenceType Type()
|
||||
{
|
||||
return mPersistenceType;
|
||||
}
|
||||
|
||||
const nsACString& Group() const
|
||||
{
|
||||
return mGroup;
|
||||
}
|
||||
|
||||
const nsACString& Origin() const
|
||||
{
|
||||
return mOrigin;
|
||||
}
|
||||
|
||||
const StoragePrivilege& Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
|
||||
const nsAString& DatabaseName() const
|
||||
{
|
||||
return mDatabaseName;
|
||||
}
|
||||
|
||||
bool Invalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
nsresult Init(nsIFile* aDirectory,
|
||||
mozIStorageConnection* aConnection);
|
||||
|
||||
nsresult Invalidate();
|
||||
|
||||
already_AddRefed<nsIFile> GetDirectory();
|
||||
|
||||
already_AddRefed<nsIFile> GetJournalDirectory();
|
||||
|
||||
already_AddRefed<nsIFile> EnsureJournalDirectory();
|
||||
|
||||
already_AddRefed<FileInfo> GetFileInfo(int64_t aId);
|
||||
|
||||
already_AddRefed<FileInfo> GetNewFileInfo();
|
||||
|
||||
static already_AddRefed<nsIFile> GetFileForId(nsIFile* aDirectory,
|
||||
int64_t aId);
|
||||
|
||||
static nsresult InitDirectory(nsIFile* aDirectory,
|
||||
nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~FileManager()
|
||||
{
|
||||
}
|
||||
|
||||
PersistenceType mPersistenceType;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
|
@ -117,8 +46,92 @@ private:
|
|||
nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;
|
||||
|
||||
bool mInvalidated;
|
||||
|
||||
public:
|
||||
static already_AddRefed<nsIFile>
|
||||
GetFileForId(nsIFile* aDirectory, int64_t aId);
|
||||
|
||||
static nsresult
|
||||
InitDirectory(nsIFile* aDirectory,
|
||||
nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
static nsresult
|
||||
GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
|
||||
|
||||
FileManager(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
StoragePrivilege aPrivilege,
|
||||
const nsAString& aDatabaseName);
|
||||
|
||||
PersistenceType
|
||||
Type() const
|
||||
{
|
||||
return mPersistenceType;
|
||||
}
|
||||
|
||||
const nsACString&
|
||||
Group() const
|
||||
{
|
||||
return mGroup;
|
||||
}
|
||||
|
||||
const nsACString&
|
||||
Origin() const
|
||||
{
|
||||
return mOrigin;
|
||||
}
|
||||
|
||||
const StoragePrivilege&
|
||||
Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
|
||||
const nsAString&
|
||||
DatabaseName() const
|
||||
{
|
||||
return mDatabaseName;
|
||||
}
|
||||
|
||||
bool
|
||||
Invalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsIFile* aDirectory, mozIStorageConnection* aConnection);
|
||||
|
||||
nsresult
|
||||
Invalidate();
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
GetDirectory();
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
GetJournalDirectory();
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
EnsureJournalDirectory();
|
||||
|
||||
already_AddRefed<FileInfo>
|
||||
GetFileInfo(int64_t aId);
|
||||
|
||||
already_AddRefed<FileInfo>
|
||||
GetNewFileInfo();
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
|
||||
|
||||
private:
|
||||
~FileManager();
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_filemanager_h__
|
||||
|
|
|
@ -7,39 +7,56 @@
|
|||
#include "FileSnapshot.h"
|
||||
|
||||
#include "IDBFileHandle.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsDebug.h"
|
||||
#include "mozilla/dom/MetadataHelper.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsXULAppAPI.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, DOMFileImpl)
|
||||
|
||||
// Create as a stored file
|
||||
FileImplSnapshot::FileImplSnapshot(const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength, nsIFile* aFile,
|
||||
MetadataParameters* aMetadataParams,
|
||||
nsIFile* aFile,
|
||||
IDBFileHandle* aFileHandle,
|
||||
FileInfo* aFileInfo)
|
||||
: DOMFileImplBase(aName, aContentType, aLength),
|
||||
mFile(aFile), mFileHandle(aFileHandle), mWholeFile(true)
|
||||
: DOMFileImplBase(aName,
|
||||
aContentType,
|
||||
aMetadataParams->Size(),
|
||||
aMetadataParams->LastModified())
|
||||
, mFile(aFile)
|
||||
, mFileHandle(aFileHandle)
|
||||
, mWholeFile(true)
|
||||
{
|
||||
MOZ_ASSERT(mFile, "Null file!");
|
||||
MOZ_ASSERT(mFileHandle, "Null file handle!");
|
||||
AssertSanity();
|
||||
MOZ_ASSERT(aMetadataParams);
|
||||
MOZ_ASSERT(aMetadataParams->Size() != UINT64_MAX);
|
||||
MOZ_ASSERT(aMetadataParams->LastModified() != INT64_MAX);
|
||||
MOZ_ASSERT(aFile);
|
||||
MOZ_ASSERT(aFileHandle);
|
||||
MOZ_ASSERT(aFileInfo);
|
||||
|
||||
mFileInfos.AppendElement(aFileInfo);
|
||||
}
|
||||
|
||||
// Create slice
|
||||
FileImplSnapshot::FileImplSnapshot(const FileImplSnapshot* aOther,
|
||||
uint64_t aStart, uint64_t aLength,
|
||||
uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
: DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength),
|
||||
mFile(aOther->mFile), mFileHandle(aOther->mFileHandle),
|
||||
mWholeFile(false)
|
||||
: DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength)
|
||||
, mFile(aOther->mFile)
|
||||
, mFileHandle(aOther->mFileHandle)
|
||||
, mWholeFile(false)
|
||||
{
|
||||
MOZ_ASSERT(mFile, "Null file!");
|
||||
MOZ_ASSERT(mFileHandle, "Null file handle!");
|
||||
AssertSanity();
|
||||
MOZ_ASSERT(aOther);
|
||||
|
||||
FileInfo* fileInfo;
|
||||
|
||||
|
@ -57,9 +74,25 @@ FileImplSnapshot::~FileImplSnapshot()
|
|||
{
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// static
|
||||
void
|
||||
FileImplSnapshot::AssertSanity()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, DOMFileImpl)
|
||||
|
||||
void
|
||||
FileImplSnapshot::Unlink()
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
FileImplSnapshot* tmp = this;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileHandle);
|
||||
}
|
||||
|
@ -67,43 +100,80 @@ FileImplSnapshot::Unlink()
|
|||
void
|
||||
FileImplSnapshot::Traverse(nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
FileImplSnapshot* tmp = this;
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileHandle);
|
||||
}
|
||||
|
||||
bool
|
||||
FileImplSnapshot::IsCCed() const
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileImplSnapshot::GetInternalStream(nsIInputStream** aStream)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertSanity();
|
||||
|
||||
nsresult rv = mFileHandle->OpenInputStream(mWholeFile, mStart, mLength,
|
||||
aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
FileImplSnapshot::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
already_AddRefed<DOMFileImpl>
|
||||
FileImplSnapshot::CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertSanity();
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> t =
|
||||
new DOMFile(new FileImplSnapshot(this, aStart, aLength, aContentType));
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new FileImplSnapshot(this, aStart, aLength, aContentType);
|
||||
|
||||
return t.forget();
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileImplSnapshot::GetMozFullPathInternal(nsAString& aFilename)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(mIsFile, "Should only be called on files");
|
||||
AssertSanity();
|
||||
MOZ_ASSERT(mIsFile);
|
||||
|
||||
return mFile->GetPath(aFilename);
|
||||
}
|
||||
|
||||
bool
|
||||
FileImplSnapshot::IsStoredFile() const
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FileImplSnapshot::IsWholeFile() const
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
return mWholeFile;
|
||||
}
|
||||
|
||||
bool
|
||||
FileImplSnapshot::IsSnapshot() const
|
||||
{
|
||||
AssertSanity();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,26 +10,55 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMFile.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MetadataParameters;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class IDBFileHandle;
|
||||
|
||||
class FileImplSnapshot : public DOMFileImplBase
|
||||
class FileImplSnapshot MOZ_FINAL
|
||||
: public DOMFileImplBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
typedef mozilla::dom::MetadataParameters MetadataParameters;
|
||||
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
nsRefPtr<IDBFileHandle> mFileHandle;
|
||||
|
||||
bool mWholeFile;
|
||||
|
||||
public:
|
||||
// Create as a stored file
|
||||
FileImplSnapshot(const nsAString& aName, const nsAString& aContentType,
|
||||
uint64_t aLength, nsIFile* aFile, IDBFileHandle* aFileHandle,
|
||||
FileImplSnapshot(const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
MetadataParameters* aMetadataParams,
|
||||
nsIFile* aFile,
|
||||
IDBFileHandle* aFileHandle,
|
||||
FileInfo* aFileInfo);
|
||||
|
||||
// Overrides
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
private:
|
||||
// Create slice
|
||||
FileImplSnapshot(const FileImplSnapshot* aOther,
|
||||
uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType);
|
||||
|
||||
~FileImplSnapshot();
|
||||
|
||||
static void
|
||||
AssertSanity()
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
virtual nsresult
|
||||
GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -43,45 +72,21 @@ public:
|
|||
Traverse(nsCycleCollectionTraversalCallback &aCb) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsCCed() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
IsCCed() const MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
// Create slice
|
||||
FileImplSnapshot(const FileImplSnapshot* aOther, uint64_t aStart,
|
||||
uint64_t aLength, const nsAString& aContentType);
|
||||
|
||||
virtual ~FileImplSnapshot();
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
virtual already_AddRefed<DOMFileImpl>
|
||||
CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsStoredFile() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
IsStoredFile() const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsWholeFile() const MOZ_OVERRIDE
|
||||
{
|
||||
return mWholeFile;
|
||||
}
|
||||
IsWholeFile() const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsSnapshot() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
nsRefPtr<IDBFileHandle> mFileHandle;
|
||||
|
||||
bool mWholeFile;
|
||||
IsSnapshot() const MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,59 +7,38 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbcursor_h__
|
||||
#define mozilla_dom_indexeddb_idbcursor_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/IDBCursorBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
|
||||
class nsIRunnable;
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class OwningIDBObjectStoreOrIDBIndex;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace indexedDB {
|
||||
|
||||
class ContinueHelper;
|
||||
class ContinueObjectStoreHelper;
|
||||
class ContinueIndexHelper;
|
||||
class ContinueIndexObjectHelper;
|
||||
class BackgroundCursorChild;
|
||||
class IDBIndex;
|
||||
class IDBObjectStore;
|
||||
class IDBRequest;
|
||||
class IDBTransaction;
|
||||
class IndexedDBCursorChild;
|
||||
class IndexedDBCursorParent;
|
||||
|
||||
class IDBCursor MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class IDBCursor MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
friend class ContinueHelper;
|
||||
friend class ContinueObjectStoreHelper;
|
||||
friend class ContinueIndexHelper;
|
||||
friend class ContinueIndexObjectHelper;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
|
||||
|
||||
enum Type
|
||||
{
|
||||
OBJECTSTORE = 0,
|
||||
OBJECTSTOREKEY,
|
||||
INDEXKEY,
|
||||
INDEXOBJECT
|
||||
};
|
||||
|
||||
enum Direction
|
||||
{
|
||||
NEXT = 0,
|
||||
|
@ -71,112 +50,84 @@ public:
|
|||
DIRECTION_INVALID
|
||||
};
|
||||
|
||||
// For OBJECTSTORE cursors.
|
||||
static
|
||||
already_AddRefed<IDBCursor>
|
||||
Create(IDBRequest* aRequest,
|
||||
IDBTransaction* aTransaction,
|
||||
IDBObjectStore* aObjectStore,
|
||||
Direction aDirection,
|
||||
const Key& aRangeKey,
|
||||
const nsACString& aContinueQuery,
|
||||
const nsACString& aContinueToQuery,
|
||||
const Key& aKey,
|
||||
StructuredCloneReadInfo&& aCloneReadInfo);
|
||||
private:
|
||||
enum Type
|
||||
{
|
||||
Type_ObjectStore,
|
||||
Type_ObjectStoreKey,
|
||||
Type_Index,
|
||||
Type_IndexKey,
|
||||
};
|
||||
|
||||
// For OBJECTSTOREKEY cursors.
|
||||
static
|
||||
already_AddRefed<IDBCursor>
|
||||
Create(IDBRequest* aRequest,
|
||||
IDBTransaction* aTransaction,
|
||||
IDBObjectStore* aObjectStore,
|
||||
nsRefPtr<IDBObjectStore> mSourceObjectStore;
|
||||
nsRefPtr<IDBIndex> mSourceIndex;
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
BackgroundCursorChild* mBackgroundActor;
|
||||
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
|
||||
// These are cycle-collected!
|
||||
JS::Heap<JS::Value> mCachedKey;
|
||||
JS::Heap<JS::Value> mCachedPrimaryKey;
|
||||
JS::Heap<JS::Value> mCachedValue;
|
||||
|
||||
Key mKey;
|
||||
Key mPrimaryKey;
|
||||
StructuredCloneReadInfo mCloneInfo;
|
||||
|
||||
const Type mType;
|
||||
const Direction mDirection;
|
||||
|
||||
bool mHaveCachedKey : 1;
|
||||
bool mHaveCachedPrimaryKey : 1;
|
||||
bool mHaveCachedValue : 1;
|
||||
bool mRooted : 1;
|
||||
bool mContinueCalled : 1;
|
||||
bool mHaveValue : 1;
|
||||
|
||||
public:
|
||||
static already_AddRefed<IDBCursor>
|
||||
Create(IDBObjectStore* aObjectStore,
|
||||
BackgroundCursorChild* aBackgroundActor,
|
||||
Direction aDirection,
|
||||
const Key& aKey,
|
||||
StructuredCloneReadInfo&& aCloneInfo);
|
||||
|
||||
static already_AddRefed<IDBCursor>
|
||||
Create(IDBObjectStore* aObjectStore,
|
||||
BackgroundCursorChild* aBackgroundActor,
|
||||
Direction aDirection,
|
||||
const Key& aRangeKey,
|
||||
const nsACString& aContinueQuery,
|
||||
const nsACString& aContinueToQuery,
|
||||
const Key& aKey);
|
||||
|
||||
// For INDEXKEY cursors.
|
||||
static
|
||||
already_AddRefed<IDBCursor>
|
||||
Create(IDBRequest* aRequest,
|
||||
IDBTransaction* aTransaction,
|
||||
IDBIndex* aIndex,
|
||||
static already_AddRefed<IDBCursor>
|
||||
Create(IDBIndex* aIndex,
|
||||
BackgroundCursorChild* aBackgroundActor,
|
||||
Direction aDirection,
|
||||
const Key& aRangeKey,
|
||||
const nsACString& aContinueQuery,
|
||||
const nsACString& aContinueToQuery,
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey);
|
||||
const Key& aPrimaryKey,
|
||||
StructuredCloneReadInfo&& aCloneInfo);
|
||||
|
||||
// For INDEXOBJECT cursors.
|
||||
static
|
||||
already_AddRefed<IDBCursor>
|
||||
Create(IDBRequest* aRequest,
|
||||
IDBTransaction* aTransaction,
|
||||
IDBIndex* aIndex,
|
||||
static already_AddRefed<IDBCursor>
|
||||
Create(IDBIndex* aIndex,
|
||||
BackgroundCursorChild* aBackgroundActor,
|
||||
Direction aDirection,
|
||||
const Key& aRangeKey,
|
||||
const nsACString& aContinueQuery,
|
||||
const nsACString& aContinueToQuery,
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey,
|
||||
StructuredCloneReadInfo&& aCloneReadInfo);
|
||||
|
||||
IDBTransaction* Transaction() const
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
IDBRequest* Request() const
|
||||
{
|
||||
return mRequest;
|
||||
}
|
||||
const Key& aPrimaryKey);
|
||||
|
||||
static Direction
|
||||
ConvertDirection(IDBCursorDirection aDirection);
|
||||
|
||||
void
|
||||
SetActor(IndexedDBCursorChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void
|
||||
SetActor(IndexedDBCursorParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBCursorChild*
|
||||
GetActorChild() const
|
||||
{
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
IndexedDBCursorParent*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
void
|
||||
ContinueInternal(const Key& aKey, int32_t aCount,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
IDBTransaction*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const;
|
||||
|
||||
void
|
||||
GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
|
||||
|
@ -185,80 +136,79 @@ public:
|
|||
GetDirection() const;
|
||||
|
||||
void
|
||||
GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
GetKey(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
GetPrimaryKey(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
void
|
||||
GetValue(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Advance(uint32_t aCount, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
|
||||
already_AddRefed<IDBRequest>
|
||||
Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Delete(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv);
|
||||
Reset();
|
||||
|
||||
void
|
||||
Reset(Key&& aKey, StructuredCloneReadInfo&& aValue);
|
||||
|
||||
void
|
||||
Reset(Key&& aKey);
|
||||
|
||||
void
|
||||
Reset(Key&& aKey, Key&& aPrimaryKey, StructuredCloneReadInfo&& aValue);
|
||||
|
||||
void
|
||||
Reset(Key&& aKey, Key&& aPrimaryKey);
|
||||
|
||||
void
|
||||
ClearBackgroundActor()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mBackgroundActor = nullptr;
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
IDBCursor(Type aType,
|
||||
IDBObjectStore* aSourceObjectStore,
|
||||
IDBIndex* aSourceIndex,
|
||||
IDBTransaction* aTransaction,
|
||||
BackgroundCursorChild* aBackgroundActor,
|
||||
Direction aDirection,
|
||||
const Key& aKey);
|
||||
|
||||
protected:
|
||||
IDBCursor();
|
||||
~IDBCursor();
|
||||
|
||||
void DropJSObjects();
|
||||
|
||||
static
|
||||
already_AddRefed<IDBCursor>
|
||||
CreateCommon(IDBRequest* aRequest,
|
||||
IDBTransaction* aTransaction,
|
||||
IDBObjectStore* aObjectStore,
|
||||
Direction aDirection,
|
||||
const Key& aRangeKey,
|
||||
const nsACString& aContinueQuery,
|
||||
const nsACString& aContinueToQuery);
|
||||
|
||||
nsRefPtr<IDBRequest> mRequest;
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsRefPtr<IDBObjectStore> mObjectStore;
|
||||
nsRefPtr<IDBIndex> mIndex;
|
||||
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
|
||||
Type mType;
|
||||
Direction mDirection;
|
||||
nsCString mContinueQuery;
|
||||
nsCString mContinueToQuery;
|
||||
|
||||
// These are cycle-collected!
|
||||
JS::Heap<JS::Value> mCachedKey;
|
||||
JS::Heap<JS::Value> mCachedPrimaryKey;
|
||||
JS::Heap<JS::Value> mCachedValue;
|
||||
|
||||
Key mRangeKey;
|
||||
|
||||
Key mKey;
|
||||
Key mObjectKey;
|
||||
StructuredCloneReadInfo mCloneReadInfo;
|
||||
Key mContinueToKey;
|
||||
|
||||
IndexedDBCursorChild* mActorChild;
|
||||
IndexedDBCursorParent* mActorParent;
|
||||
|
||||
bool mHaveCachedKey;
|
||||
bool mHaveCachedPrimaryKey;
|
||||
bool mHaveCachedValue;
|
||||
bool mRooted;
|
||||
bool mContinueCalled;
|
||||
bool mHaveValue;
|
||||
void
|
||||
DropJSObjects();
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbcursor_h__
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,274 +7,302 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbdatabase_h__
|
||||
#define mozilla_dom_indexeddb_idbdatabase_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIOfflineStorage.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
#include "mozilla/dom/IDBTransactionBinding.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/FileManager.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/StorageTypeBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsIDocument;
|
||||
class nsIDOMBlob;
|
||||
class nsIWeakReference;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class EventChainPostVisitor;
|
||||
|
||||
namespace dom {
|
||||
class nsIContentParent;
|
||||
namespace quota {
|
||||
class Client;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
class DOMStringList;
|
||||
struct IDBObjectStoreParameters;
|
||||
template <typename> class Sequence;
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
struct DatabaseInfo;
|
||||
namespace indexedDB {
|
||||
|
||||
class BackgroundDatabaseChild;
|
||||
class DatabaseSpec;
|
||||
class FileManager;
|
||||
class IDBFactory;
|
||||
class IDBIndex;
|
||||
class IDBMutableFile;
|
||||
class IDBObjectStore;
|
||||
class IDBRequest;
|
||||
class IDBTransaction;
|
||||
class IndexedDatabaseManager;
|
||||
class IndexedDBDatabaseChild;
|
||||
class IndexedDBDatabaseParent;
|
||||
struct ObjectStoreInfoGuts;
|
||||
class PBackgroundIDBDatabaseFileChild;
|
||||
|
||||
class IDBDatabase MOZ_FINAL : public IDBWrapperCache,
|
||||
public nsIOfflineStorage
|
||||
class IDBDatabase MOZ_FINAL
|
||||
: public IDBWrapperCache
|
||||
{
|
||||
friend class AsyncConnectionHelper;
|
||||
friend class IndexedDatabaseManager;
|
||||
friend class IndexedDBDatabaseParent;
|
||||
friend class IndexedDBDatabaseChild;
|
||||
typedef mozilla::dom::StorageType StorageType;
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIOFFLINESTORAGE
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
|
||||
|
||||
static already_AddRefed<IDBDatabase>
|
||||
Create(IDBWrapperCache* aOwnerCache,
|
||||
IDBFactory* aFactory,
|
||||
already_AddRefed<DatabaseInfo> aDatabaseInfo,
|
||||
const nsACString& aASCIIOrigin,
|
||||
FileManager* aFileManager,
|
||||
mozilla::dom::nsIContentParent* aContentParent);
|
||||
|
||||
static IDBDatabase*
|
||||
FromStorage(nsIOfflineStorage* aStorage);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PostHandleEvent(
|
||||
EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
|
||||
DatabaseInfo* Info() const
|
||||
{
|
||||
return mDatabaseInfo;
|
||||
}
|
||||
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
const nsString& FilePath() const
|
||||
{
|
||||
return mFilePath;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocument> GetOwnerDocument()
|
||||
{
|
||||
if (!GetOwner()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
||||
return doc.forget();
|
||||
}
|
||||
|
||||
// Whether or not the database has been invalidated. If it has then no further
|
||||
// transactions for this database will be allowed to run. This function may be
|
||||
// called on any thread.
|
||||
bool IsInvalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
void DisconnectFromActorParent();
|
||||
|
||||
void CloseInternal(bool aIsDead);
|
||||
|
||||
void EnterSetVersionTransaction();
|
||||
void ExitSetVersionTransaction();
|
||||
|
||||
// Called when a versionchange transaction is aborted to reset the
|
||||
// DatabaseInfo.
|
||||
void RevertToPreviousState();
|
||||
|
||||
FileManager* Manager() const
|
||||
{
|
||||
return mFileManager;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBDatabaseChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBDatabaseParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBDatabaseChild*
|
||||
GetActorChild() const
|
||||
{
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
IndexedDBDatabaseParent*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
mozilla::dom::nsIContentParent*
|
||||
GetContentParent() const
|
||||
{
|
||||
return mContentParent;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
CreateObjectStoreInternal(IDBTransaction* aTransaction,
|
||||
const ObjectStoreInfoGuts& aInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IDBFactory*
|
||||
Factory() const
|
||||
{
|
||||
return mFactory;
|
||||
}
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
void
|
||||
GetName(nsString& aName) const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
aName.Assign(mName);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Version() const;
|
||||
|
||||
already_AddRefed<mozilla::dom::DOMStringList>
|
||||
GetObjectStoreNames(ErrorResult& aRv) const;
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
CreateObjectStore(JSContext* aCx, const nsAString& aName,
|
||||
const IDBObjectStoreParameters& aOptionalParameters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<indexedDB::IDBTransaction>
|
||||
Transaction(const nsAString& aStoreName, IDBTransactionMode aMode,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Sequence<nsString> list;
|
||||
list.AppendElement(aStoreName);
|
||||
return Transaction(list, aMode, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<indexedDB::IDBTransaction>
|
||||
Transaction(const Sequence<nsString>& aStoreNames, IDBTransactionMode aMode,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(abort)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(versionchange)
|
||||
|
||||
mozilla::dom::StorageType
|
||||
Storage() const
|
||||
{
|
||||
return PersistenceTypeToStorage(mPersistenceType);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
CreateMutableFile(const nsAString& aName, const Optional<nsAString>& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
MozCreateFileHandle(const nsAString& aName, const Optional<nsAString>& aType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return CreateMutableFile(aName, aType, aRv);
|
||||
}
|
||||
|
||||
virtual void LastRelease() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
explicit IDBDatabase(IDBWrapperCache* aOwnerCache);
|
||||
~IDBDatabase();
|
||||
|
||||
void OnUnlink();
|
||||
void InvalidateInternal(bool aIsDead);
|
||||
class Observer;
|
||||
friend class Observer;
|
||||
|
||||
// The factory must be kept alive when IndexedDB is used in multiple
|
||||
// processes. If it dies then the entire actor tree will be destroyed with it
|
||||
// and the world will explode.
|
||||
nsRefPtr<IDBFactory> mFactory;
|
||||
|
||||
nsRefPtr<DatabaseInfo> mDatabaseInfo;
|
||||
nsAutoPtr<DatabaseSpec> mSpec;
|
||||
|
||||
// Set to a copy of the existing DatabaseInfo when starting a versionchange
|
||||
// transaction.
|
||||
nsRefPtr<DatabaseInfo> mPreviousDatabaseInfo;
|
||||
nsCString mDatabaseId;
|
||||
nsString mName;
|
||||
nsString mFilePath;
|
||||
nsCString mASCIIOrigin;
|
||||
// Normally null except during a versionchange transaction.
|
||||
nsAutoPtr<DatabaseSpec> mPreviousSpec;
|
||||
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
|
||||
IndexedDBDatabaseChild* mActorChild;
|
||||
IndexedDBDatabaseParent* mActorParent;
|
||||
BackgroundDatabaseChild* mBackgroundActor;
|
||||
|
||||
mozilla::dom::nsIContentParent* mContentParent;
|
||||
nsTHashtable<nsPtrHashKey<IDBTransaction>> mTransactions;
|
||||
|
||||
nsRefPtr<mozilla::dom::quota::Client> mQuotaClient;
|
||||
nsDataHashtable<nsISupportsHashKey, PBackgroundIDBDatabaseFileChild*>
|
||||
mFileActors;
|
||||
|
||||
nsTHashtable<nsISupportsHashKey> mReceivedBlobs;
|
||||
|
||||
nsRefPtr<Observer> mObserver;
|
||||
|
||||
// Weak refs, IDBMutableFile strongly owns this IDBDatabase object.
|
||||
nsTArray<IDBMutableFile*> mLiveMutableFiles;
|
||||
|
||||
bool mInvalidated;
|
||||
bool mRegistered;
|
||||
bool mClosed;
|
||||
bool mRunningVersionChange;
|
||||
bool mInvalidated;
|
||||
|
||||
public:
|
||||
static already_AddRefed<IDBDatabase>
|
||||
Create(IDBWrapperCache* aOwnerCache,
|
||||
IDBFactory* aFactory,
|
||||
BackgroundDatabaseChild* aActor,
|
||||
DatabaseSpec* aSpec);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
const nsString&
|
||||
Name() const;
|
||||
|
||||
void
|
||||
GetName(nsAString& aName) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
aName = Name();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Version() const;
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
GetOwnerDocument() const;
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
CloseInternal();
|
||||
}
|
||||
|
||||
bool
|
||||
IsClosed() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
void
|
||||
Invalidate();
|
||||
|
||||
// Whether or not the database has been invalidated. If it has then no further
|
||||
// transactions for this database will be allowed to run.
|
||||
bool
|
||||
IsInvalidated() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
void
|
||||
EnterSetVersionTransaction(uint64_t aNewVersion);
|
||||
|
||||
void
|
||||
ExitSetVersionTransaction();
|
||||
|
||||
// Called when a versionchange transaction is aborted to reset the
|
||||
// DatabaseInfo.
|
||||
void
|
||||
RevertToPreviousState();
|
||||
|
||||
IDBFactory*
|
||||
Factory() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mFactory;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterTransaction(IDBTransaction* aTransaction);
|
||||
|
||||
void
|
||||
UnregisterTransaction(IDBTransaction* aTransaction);
|
||||
|
||||
void
|
||||
AbortTransactions();
|
||||
|
||||
PBackgroundIDBDatabaseFileChild*
|
||||
GetOrCreateFileActorForBlob(nsIDOMBlob* aBlob);
|
||||
|
||||
void
|
||||
NoteFinishedFileActor(PBackgroundIDBDatabaseFileChild* aFileActor);
|
||||
|
||||
void
|
||||
NoteReceivedBlob(nsIDOMBlob* aBlob);
|
||||
|
||||
void
|
||||
DelayedMaybeExpireFileActors();
|
||||
|
||||
// XXX This doesn't really belong here... It's only needed for IDBMutableFile
|
||||
// serialization and should be removed someday.
|
||||
nsresult
|
||||
GetQuotaInfo(nsACString& aOrigin, PersistenceType* aPersistenceType);
|
||||
|
||||
void
|
||||
NoteLiveMutableFile(IDBMutableFile* aMutableFile);
|
||||
|
||||
void
|
||||
NoteFinishedMutableFile(IDBMutableFile* aMutableFile);
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const;
|
||||
|
||||
already_AddRefed<DOMStringList>
|
||||
ObjectStoreNames() const;
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
CreateObjectStore(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
const IDBObjectStoreParameters& aOptionalParameters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBTransaction>
|
||||
Transaction(const nsAString& aStoreName,
|
||||
IDBTransactionMode aMode,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBTransaction>
|
||||
Transaction(const Sequence<nsString>& aStoreNames,
|
||||
IDBTransactionMode aMode,
|
||||
ErrorResult& aRv);
|
||||
|
||||
StorageType
|
||||
Storage() const;
|
||||
|
||||
IMPL_EVENT_HANDLER(abort)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(versionchange)
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
CreateMutableFile(const nsAString& aName,
|
||||
const Optional<nsAString>& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
MozCreateFileHandle(const nsAString& aName,
|
||||
const Optional<nsAString>& aType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return CreateMutableFile(aName, aType, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
ClearBackgroundActor()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mBackgroundActor = nullptr;
|
||||
}
|
||||
|
||||
const DatabaseSpec*
|
||||
Spec() const
|
||||
{
|
||||
return mSpec;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual void
|
||||
LastRelease() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
PostHandleEvent(EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
IDBDatabase(IDBWrapperCache* aOwnerCache,
|
||||
IDBFactory* aFactory,
|
||||
BackgroundDatabaseChild* aActor,
|
||||
DatabaseSpec* aSpec);
|
||||
|
||||
~IDBDatabase();
|
||||
|
||||
void
|
||||
CloseInternal();
|
||||
|
||||
void
|
||||
InvalidateInternal();
|
||||
|
||||
bool
|
||||
RunningVersionChangeTransaction() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return !!mPreviousSpec;
|
||||
}
|
||||
|
||||
void
|
||||
RefreshSpec(bool aMayDelete);
|
||||
|
||||
void
|
||||
ExpireFileActors(bool aExpireAll);
|
||||
|
||||
void
|
||||
InvalidateMutableFiles();
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbdatabase_h__
|
||||
|
|
|
@ -6,49 +6,45 @@
|
|||
|
||||
#include "IDBEvents.h"
|
||||
|
||||
#include "nsJSON.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "mozilla/dom/IDBVersionChangeEventBinding.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "IDBRequest.h"
|
||||
#include "IDBTransaction.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
|
||||
namespace {
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class EventFiringRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
EventFiringRunnable(EventTarget* aTarget,
|
||||
nsIDOMEvent* aEvent)
|
||||
: mTarget(aTarget), mEvent(aEvent)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
bool dummy;
|
||||
return mTarget->DispatchEvent(mEvent, &dummy);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<EventTarget> mTarget;
|
||||
nsCOMPtr<nsIDOMEvent> mEvent;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
const char16_t* kAbortEventType = MOZ_UTF16("abort");
|
||||
const char16_t* kBlockedEventType = MOZ_UTF16("blocked");
|
||||
const char16_t* kCompleteEventType = MOZ_UTF16("complete");
|
||||
const char16_t* kErrorEventType = MOZ_UTF16("error");
|
||||
const char16_t* kSuccessEventType = MOZ_UTF16("success");
|
||||
const char16_t* kUpgradeNeededEventType = MOZ_UTF16("upgradeneeded");
|
||||
const char16_t* kVersionChangeEventType = MOZ_UTF16("versionchange");
|
||||
|
||||
already_AddRefed<nsIDOMEvent>
|
||||
mozilla::dom::indexedDB::CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
CreateGenericEvent(EventTarget* aOwner,
|
||||
const nsDependentString& aType,
|
||||
Bubbles aBubbles,
|
||||
Cancelable aCancelable)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMEvent(getter_AddRefs(event), aOwner, nullptr, nullptr);
|
||||
nsresult rv = event->InitEvent(aType,
|
||||
nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), aOwner, nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = event->InitEvent(aType,
|
||||
aBubbles == eDoesBubble ? true : false,
|
||||
aCancelable == eCancelable ? true : false);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
|
@ -57,37 +53,39 @@ mozilla::dom::indexedDB::CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
|
|||
|
||||
// static
|
||||
already_AddRefed<IDBVersionChangeEvent>
|
||||
IDBVersionChangeEvent::CreateInternal(mozilla::dom::EventTarget* aOwner,
|
||||
IDBVersionChangeEvent::CreateInternal(EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
Nullable<uint64_t> aNewVersion)
|
||||
{
|
||||
nsRefPtr<IDBVersionChangeEvent> event(new IDBVersionChangeEvent(aOwner));
|
||||
nsRefPtr<IDBVersionChangeEvent> event =
|
||||
new IDBVersionChangeEvent(aOwner, aOldVersion);
|
||||
if (!aNewVersion.IsNull()) {
|
||||
event->mNewVersion.SetValue(aNewVersion.Value());
|
||||
}
|
||||
|
||||
nsresult rv = event->InitEvent(aType, false, false);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
event->mOldVersion = aOldVersion;
|
||||
event->mNewVersion = aNewVersion;
|
||||
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIRunnable>
|
||||
IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget,
|
||||
already_AddRefed<IDBVersionChangeEvent>
|
||||
IDBVersionChangeEvent::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
const IDBVersionChangeEventInit& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<Event> event =
|
||||
CreateInternal(aTarget, aType, aOldVersion, aNewVersion);
|
||||
NS_ENSURE_TRUE(event, nullptr);
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable(new EventFiringRunnable(aTarget, event));
|
||||
return runnable.forget();
|
||||
return CreateInternal(target,
|
||||
aType,
|
||||
aOptions.mOldVersion,
|
||||
aOptions.mNewVersion);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, Event)
|
||||
|
@ -96,3 +94,13 @@ NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, Event)
|
|||
NS_INTERFACE_MAP_BEGIN(IDBVersionChangeEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(IDBVersionChangeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
JSObject*
|
||||
IDBVersionChangeEvent::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return IDBVersionChangeEventBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,28 +7,28 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbevents_h__
|
||||
#define mozilla_dom_indexeddb_idbevents_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/IDBVersionChangeEventBinding.h"
|
||||
|
||||
#define SUCCESS_EVT_STR "success"
|
||||
#define ERROR_EVT_STR "error"
|
||||
#define COMPLETE_EVT_STR "complete"
|
||||
#define ABORT_EVT_STR "abort"
|
||||
#define VERSIONCHANGE_EVT_STR "versionchange"
|
||||
#define BLOCKED_EVT_STR "blocked"
|
||||
#define UPGRADENEEDED_EVT_STR "upgradeneeded"
|
||||
|
||||
#define IDBVERSIONCHANGEEVENT_IID \
|
||||
{ 0x3b65d4c3, 0x73ad, 0x492e, \
|
||||
{ 0xb1, 0x2d, 0x15, 0xf9, 0xda, 0xc2, 0x08, 0x4b } }
|
||||
{0x3b65d4c3, 0x73ad, 0x492e, {0xb1, 0x2d, 0x15, 0xf9, 0xda, 0xc2, 0x08, 0x4b}}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
class nsAString;
|
||||
class nsDependentString;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class EventTarget;
|
||||
class GlobalObject;
|
||||
struct IDBVersionChangeEventInit;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
enum Bubbles {
|
||||
eDoesNotBubble,
|
||||
|
@ -40,125 +40,94 @@ enum Cancelable {
|
|||
eCancelable
|
||||
};
|
||||
|
||||
extern const char16_t* kAbortEventType;
|
||||
extern const char16_t* kBlockedEventType;
|
||||
extern const char16_t* kCompleteEventType;
|
||||
extern const char16_t* kErrorEventType;
|
||||
extern const char16_t* kSuccessEventType;
|
||||
extern const char16_t* kUpgradeNeededEventType;
|
||||
extern const char16_t* kVersionChangeEventType;
|
||||
|
||||
already_AddRefed<nsIDOMEvent>
|
||||
CreateGenericEvent(mozilla::dom::EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
CreateGenericEvent(EventTarget* aOwner,
|
||||
const nsDependentString& aType,
|
||||
Bubbles aBubbles,
|
||||
Cancelable aCancelable);
|
||||
|
||||
class IDBVersionChangeEvent : public Event
|
||||
class IDBVersionChangeEvent MOZ_FINAL : public Event
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_TO_EVENT
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID)
|
||||
uint64_t mOldVersion;
|
||||
Nullable<uint64_t> mNewVersion;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE
|
||||
public:
|
||||
static already_AddRefed<IDBVersionChangeEvent>
|
||||
Create(EventTarget* aOwner,
|
||||
const nsDependentString& aName,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
{
|
||||
return mozilla::dom::IDBVersionChangeEventBinding::Wrap(aCx, this);
|
||||
Nullable<uint64_t> newVersion(aNewVersion);
|
||||
return CreateInternal(aOwner, aName, aOldVersion, newVersion);
|
||||
}
|
||||
|
||||
static already_AddRefed<IDBVersionChangeEvent>
|
||||
Create(EventTarget* aOwner,
|
||||
const nsDependentString& aName,
|
||||
uint64_t aOldVersion)
|
||||
{
|
||||
Nullable<uint64_t> newVersion(0);
|
||||
newVersion.SetNull();
|
||||
return CreateInternal(aOwner, aName, aOldVersion, newVersion);
|
||||
}
|
||||
|
||||
static already_AddRefed<IDBVersionChangeEvent>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const IDBVersionChangeEventInit& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
uint64_t newVersion = 0;
|
||||
if (!aOptions.mNewVersion.IsNull()) {
|
||||
newVersion = aOptions.mNewVersion.Value();
|
||||
}
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
return CreateInternal(target, aType, aOptions.mOldVersion, newVersion);
|
||||
}
|
||||
ErrorResult& aRv);
|
||||
|
||||
uint64_t OldVersion()
|
||||
uint64_t
|
||||
OldVersion() const
|
||||
{
|
||||
return mOldVersion;
|
||||
}
|
||||
|
||||
mozilla::dom::Nullable<uint64_t> GetNewVersion()
|
||||
Nullable<uint64_t>
|
||||
GetNewVersion() const
|
||||
{
|
||||
return mNewVersion
|
||||
? mozilla::dom::Nullable<uint64_t>(mNewVersion)
|
||||
: mozilla::dom::Nullable<uint64_t>();
|
||||
return mNewVersion;
|
||||
}
|
||||
|
||||
inline static already_AddRefed<Event>
|
||||
Create(mozilla::dom::EventTarget* aOwner,
|
||||
int64_t aOldVersion,
|
||||
int64_t aNewVersion)
|
||||
{
|
||||
return CreateInternal(aOwner,
|
||||
NS_LITERAL_STRING(VERSIONCHANGE_EVT_STR),
|
||||
aOldVersion, aNewVersion);
|
||||
}
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID)
|
||||
|
||||
inline static already_AddRefed<Event>
|
||||
CreateBlocked(mozilla::dom::EventTarget* aOwner,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
{
|
||||
return CreateInternal(aOwner, NS_LITERAL_STRING(BLOCKED_EVT_STR),
|
||||
aOldVersion, aNewVersion);
|
||||
}
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_TO_EVENT
|
||||
|
||||
inline static already_AddRefed<Event>
|
||||
CreateUpgradeNeeded(mozilla::dom::EventTarget* aOwner,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
{
|
||||
return CreateInternal(aOwner,
|
||||
NS_LITERAL_STRING(UPGRADENEEDED_EVT_STR),
|
||||
aOldVersion, aNewVersion);
|
||||
}
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
inline static already_AddRefed<nsIRunnable>
|
||||
CreateRunnable(mozilla::dom::EventTarget* aTarget,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
{
|
||||
return CreateRunnableInternal(aTarget,
|
||||
NS_LITERAL_STRING(VERSIONCHANGE_EVT_STR),
|
||||
aOldVersion, aNewVersion);
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIRunnable>
|
||||
CreateBlockedRunnable(mozilla::dom::EventTarget* aTarget,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion)
|
||||
{
|
||||
return CreateRunnableInternal(aTarget,
|
||||
NS_LITERAL_STRING(BLOCKED_EVT_STR),
|
||||
aOldVersion, aNewVersion);
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit IDBVersionChangeEvent(mozilla::dom::EventTarget* aOwner)
|
||||
private:
|
||||
IDBVersionChangeEvent(EventTarget* aOwner, uint64_t aOldVersion)
|
||||
: Event(aOwner, nullptr, nullptr)
|
||||
, mOldVersion(aOldVersion)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
virtual ~IDBVersionChangeEvent() { }
|
||||
|
||||
~IDBVersionChangeEvent()
|
||||
{ }
|
||||
|
||||
static already_AddRefed<IDBVersionChangeEvent>
|
||||
CreateInternal(mozilla::dom::EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
CreateInternal(EventTarget* aOwner,
|
||||
const nsAString& aName,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion);
|
||||
|
||||
static already_AddRefed<nsIRunnable>
|
||||
CreateRunnableInternal(mozilla::dom::EventTarget* aOwner,
|
||||
const nsAString& aType,
|
||||
uint64_t aOldVersion,
|
||||
uint64_t aNewVersion);
|
||||
|
||||
uint64_t mOldVersion;
|
||||
uint64_t mNewVersion;
|
||||
Nullable<uint64_t> aNewVersion);
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(IDBVersionChangeEvent, IDBVERSIONCHANGEEVENT_IID)
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbevents_h__
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,219 +7,203 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbfactory_h__
|
||||
#define mozilla_dom_indexeddb_idbfactory_h__
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h" // for Optional
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/StorageTypeBinding.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
class nsIFile;
|
||||
class nsIFileURL;
|
||||
class nsIPrincipal;
|
||||
class nsPIDOMWindow;
|
||||
template<typename> class nsRefPtr;
|
||||
struct PRThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class PBackgroundChild;
|
||||
class PrincipalInfo;
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
class nsIContentParent;
|
||||
|
||||
struct IDBOpenDBOptions;
|
||||
class TabChild;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
struct DatabaseInfo;
|
||||
class IDBDatabase;
|
||||
class BackgroundFactoryChild;
|
||||
class FactoryRequestParams;
|
||||
class IDBOpenDBRequest;
|
||||
class IndexedDBChild;
|
||||
class IndexedDBParent;
|
||||
|
||||
struct ObjectStoreInfo;
|
||||
|
||||
class IDBFactory MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class IDBFactory MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
typedef mozilla::dom::nsIContentParent nsIContentParent;
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
typedef mozilla::dom::StorageType StorageType;
|
||||
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
|
||||
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
|
||||
class BackgroundCreateCallback;
|
||||
struct PendingRequestInfo;
|
||||
|
||||
// Called when using IndexedDB from a window in a different process.
|
||||
static nsresult Create(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aASCIIOrigin,
|
||||
nsIContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
// Called when using IndexedDB from a window in the current process.
|
||||
static nsresult Create(nsPIDOMWindow* aWindow,
|
||||
nsIContentParent* aContentParent,
|
||||
IDBFactory** aFactory)
|
||||
{
|
||||
return Create(aWindow, EmptyCString(), EmptyCString(), aContentParent,
|
||||
aFactory);
|
||||
}
|
||||
|
||||
// Called when using IndexedDB from a JS component or a JSM in the current
|
||||
// process.
|
||||
static nsresult Create(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
nsIContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
// Called when using IndexedDB from a JS component or a JSM in a different
|
||||
// process or from a C++ component.
|
||||
static nsresult Create(nsIContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static already_AddRefed<nsIFileURL>
|
||||
GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
static already_AddRefed<mozIStorageConnection>
|
||||
GetConnection(const nsAString& aDatabaseFilePath,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
static nsresult
|
||||
SetDefaultPragmas(mozIStorageConnection* aConnection);
|
||||
|
||||
static nsresult
|
||||
LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
const nsACString& aDatabaseId,
|
||||
uint64_t* aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
|
||||
static nsresult
|
||||
SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
|
||||
uint64_t aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
|
||||
nsresult
|
||||
OpenInternal(const nsAString& aName,
|
||||
int64_t aVersion,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aASCIIOrigin,
|
||||
StoragePrivilege aStoragePrivilege,
|
||||
bool aDeleting,
|
||||
IDBOpenDBRequest** _retval);
|
||||
|
||||
nsresult
|
||||
OpenInternal(const nsAString& aName,
|
||||
int64_t aVersion,
|
||||
PersistenceType aPersistenceType,
|
||||
bool aDeleting,
|
||||
IDBOpenDBRequest** _retval)
|
||||
{
|
||||
return OpenInternal(aName, aVersion, aPersistenceType, mGroup, mASCIIOrigin,
|
||||
mPrivilege, aDeleting, _retval);
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent, "Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
GetASCIIOrigin() const
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
FromIPC()
|
||||
{
|
||||
return !!mContentParent;
|
||||
}
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Open(const nsAString& aName, uint64_t aVersion, ErrorResult& aRv)
|
||||
{
|
||||
return Open(nullptr, aName, Optional<uint64_t>(aVersion),
|
||||
Optional<mozilla::dom::StorageType>(), false, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Open(const nsAString& aName, const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
DeleteDatabase(const nsAString& aName, const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
int16_t
|
||||
Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
||||
JS::Handle<JS::Value> aSecond, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||
uint64_t aVersion, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
IDBFactory();
|
||||
~IDBFactory();
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Open(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||
const Optional<uint64_t>& aVersion,
|
||||
const Optional<mozilla::dom::StorageType>& aStorageType, bool aDelete,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsCString mGroup;
|
||||
nsCString mASCIIOrigin;
|
||||
StoragePrivilege mPrivilege;
|
||||
PersistenceType mDefaultPersistenceType;
|
||||
nsAutoPtr<PrincipalInfo> mPrincipalInfo;
|
||||
|
||||
// If this factory lives on a window then mWindow must be non-null. Otherwise
|
||||
// mOwningObject must be non-null.
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
JS::Heap<JSObject*> mOwningObject;
|
||||
|
||||
IndexedDBChild* mActorChild;
|
||||
IndexedDBParent* mActorParent;
|
||||
// This will only be set if the factory belongs to a window in a child
|
||||
// process.
|
||||
nsRefPtr<TabChild> mTabChild;
|
||||
|
||||
mozilla::dom::nsIContentParent* mContentParent;
|
||||
nsTArray<nsAutoPtr<PendingRequestInfo>> mPendingRequests;
|
||||
|
||||
BackgroundFactoryChild* mBackgroundActor;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRThread* mOwningThread;
|
||||
#endif
|
||||
|
||||
bool mRootedOwningObject;
|
||||
bool mBackgroundActorFailed;
|
||||
bool mPrivateBrowsingMode;
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
CreateForWindow(nsPIDOMWindow* aWindow,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static nsresult
|
||||
CreateForChromeJS(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static nsresult
|
||||
CreateForDatastore(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void
|
||||
SetBackgroundActor(BackgroundFactoryChild* aBackgroundActor);
|
||||
|
||||
void
|
||||
ClearBackgroundActor()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mBackgroundActor = nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
TabChild*
|
||||
GetTabChild() const
|
||||
{
|
||||
return mTabChild;
|
||||
}
|
||||
|
||||
PrincipalInfo*
|
||||
GetPrincipalInfo() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mPrincipalInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Open(const nsAString& aName,
|
||||
uint64_t aVersion,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Open(const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
DeleteDatabase(const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
int16_t
|
||||
Cmp(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aFirst,
|
||||
JS::Handle<JS::Value> aSecond,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
OpenForPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aName,
|
||||
uint64_t aVersion,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
OpenForPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
DeleteForPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aName,
|
||||
const IDBOpenDBOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
IDBFactory();
|
||||
~IDBFactory();
|
||||
|
||||
static nsresult
|
||||
CreateForJSInternal(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aOwningObject,
|
||||
nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
OpenInternal(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aName,
|
||||
const Optional<uint64_t>& aVersion,
|
||||
const Optional<StorageType>& aStorageType,
|
||||
bool aDeleting,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult
|
||||
BackgroundActorCreated(PBackgroundChild* aBackgroundActor);
|
||||
|
||||
void
|
||||
BackgroundActorFailed();
|
||||
|
||||
nsresult
|
||||
InitiateRequest(IDBOpenDBRequest* aRequest,
|
||||
const FactoryRequestParams& aParams);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
namespace {
|
||||
|
||||
NS_DEFINE_CID(kAppShellCID2, NS_APPSHELL_CID);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
IDBFileHandle::IDBFileHandle(FileMode aMode,
|
||||
RequestMode aRequestMode,
|
||||
IDBMutableFile* aMutableFile)
|
||||
|
@ -158,10 +158,10 @@ IDBFileHandle::OnCompleteOrAbort(bool aAborted)
|
|||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
if (aAborted) {
|
||||
event = CreateGenericEvent(this, NS_LITERAL_STRING(ABORT_EVT_STR),
|
||||
event = CreateGenericEvent(this, nsDependentString(kAbortEventType),
|
||||
eDoesBubble, eNotCancelable);
|
||||
} else {
|
||||
event = CreateGenericEvent(this, NS_LITERAL_STRING(COMPLETE_EVT_STR),
|
||||
event = CreateGenericEvent(this, nsDependentString(kCompleteEventType),
|
||||
eDoesNotBubble, eNotCancelable);
|
||||
}
|
||||
if (NS_WARN_IF(!event)) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,245 +7,207 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbindex_h__
|
||||
#define mozilla_dom_indexeddb_idbindex_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/IDBCursorBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/indexedDB/KeyPath.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
template <typename> class Sequence;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class IDBCursor;
|
||||
class IDBKeyRange;
|
||||
class IDBObjectStore;
|
||||
class IDBRequest;
|
||||
class IndexedDBIndexChild;
|
||||
class IndexedDBIndexParent;
|
||||
class IndexMetadata;
|
||||
class Key;
|
||||
class KeyPath;
|
||||
|
||||
struct IndexInfo;
|
||||
|
||||
class IDBIndex MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class IDBIndex MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
nsRefPtr<IDBObjectStore> mObjectStore;
|
||||
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
|
||||
// This normally points to the IndexMetadata owned by the parent IDBDatabase
|
||||
// object. However, if this index is part of a versionchange transaction and
|
||||
// it gets deleted then the metadata is copied into mDeletedMetadata and
|
||||
// mMetadata is set to point at mDeletedMetadata.
|
||||
const IndexMetadata* mMetadata;
|
||||
nsAutoPtr<IndexMetadata> mDeletedMetadata;
|
||||
|
||||
const int64_t mId;
|
||||
bool mRooted;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBIndex)
|
||||
|
||||
static already_AddRefed<IDBIndex>
|
||||
Create(IDBObjectStore* aObjectStore,
|
||||
const IndexInfo* aIndexInfo,
|
||||
bool aCreating);
|
||||
Create(IDBObjectStore* aObjectStore, const IndexMetadata& aMetadata);
|
||||
|
||||
IDBObjectStore* ObjectStore()
|
||||
int64_t
|
||||
Id() const
|
||||
{
|
||||
return mObjectStore;
|
||||
}
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
const int64_t Id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
const nsString&
|
||||
Name() const;
|
||||
|
||||
bool IsUnique() const
|
||||
{
|
||||
return mUnique;
|
||||
}
|
||||
bool
|
||||
Unique() const;
|
||||
|
||||
bool IsMultiEntry() const
|
||||
{
|
||||
return mMultiEntry;
|
||||
}
|
||||
bool
|
||||
MultiEntry() const;
|
||||
|
||||
const KeyPath& GetKeyPath() const
|
||||
{
|
||||
return mKeyPath;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBIndexChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBIndexParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBIndexChild*
|
||||
GetActorChild() const
|
||||
{
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
IndexedDBIndexParent*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetKeyInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllInternal(IDBKeyRange* aKeyRange,
|
||||
uint32_t aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllKeysInternal(IDBKeyRange* aKeyRange,
|
||||
uint32_t aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
CountInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult OpenCursorFromChildProcess(
|
||||
IDBRequest* aRequest,
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey,
|
||||
IDBCursor** _retval);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
|
||||
size_t aDirection,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult OpenCursorInternal(IDBKeyRange* aKeyRange,
|
||||
size_t aDirection,
|
||||
IDBRequest** _retval);
|
||||
|
||||
nsresult OpenCursorFromChildProcess(
|
||||
IDBRequest* aRequest,
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval);
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
IDBObjectStore*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mObjectStore;
|
||||
}
|
||||
|
||||
void
|
||||
GetName(nsString& aName) const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
aName.Assign(mName);
|
||||
}
|
||||
const KeyPath&
|
||||
GetKeyPath() const;
|
||||
|
||||
IDBObjectStore*
|
||||
ObjectStore() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
return mObjectStore;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const;
|
||||
|
||||
void
|
||||
GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
GetName(nsString& aName) const
|
||||
{
|
||||
aName = Name();
|
||||
}
|
||||
|
||||
void
|
||||
GetKeyPath(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool
|
||||
MultiEntry() const
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursor(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mMultiEntry;
|
||||
}
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
bool
|
||||
Unique() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mUnique;
|
||||
return OpenCursorInternal(/* aKeysOnly */ false, aCx, aRange, aDirection,
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection, ErrorResult& aRv);
|
||||
OpenKeyCursor(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return OpenCursorInternal(/* aKeysOnly */ true, aCx, aRange, aDirection,
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection, ErrorResult& aRv);
|
||||
Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return GetInternal(/* aKeyOnly */ false, aCx, aKey, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
|
||||
GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
|
||||
return GetInternal(/* aKeyOnly */ true, aCx, aKey, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetStoreName(nsString& aStoreName) const
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mObjectStore->GetName(aStoreName);
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return GetAllInternal(/* aKeysOnly */ false, aCx, aKey, aLimit, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return GetAllInternal(/* aKeysOnly */ true, aCx, aKey, aLimit, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
RefreshMetadata(bool aMayDelete);
|
||||
|
||||
void
|
||||
NoteDeletion();
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
IDBIndex();
|
||||
IDBIndex(IDBObjectStore* aObjectStore, const IndexMetadata* aMetadata);
|
||||
|
||||
~IDBIndex();
|
||||
|
||||
nsRefPtr<IDBObjectStore> mObjectStore;
|
||||
already_AddRefed<IDBRequest>
|
||||
GetInternal(bool aKeyOnly,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv);
|
||||
|
||||
int64_t mId;
|
||||
nsString mName;
|
||||
KeyPath mKeyPath;
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllInternal(bool aKeysOnly,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IndexedDBIndexChild* mActorChild;
|
||||
IndexedDBIndexParent* mActorParent;
|
||||
|
||||
bool mUnique;
|
||||
bool mMultiEntry;
|
||||
bool mRooted;
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursorInternal(bool aKeysOnly,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbindex_h__
|
||||
|
|
|
@ -4,30 +4,21 @@
|
|||
* 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 "base/basictypes.h"
|
||||
|
||||
#include "IDBKeyRange.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "Key.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/IDBKeyRangeBinding.h"
|
||||
#include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
|
||||
#include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::dom::indexedDB::ipc;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
namespace {
|
||||
|
||||
inline nsresult
|
||||
nsresult
|
||||
GetKeyFromJSVal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal,
|
||||
Key& aKey,
|
||||
|
@ -35,8 +26,7 @@ GetKeyFromJSVal(JSContext* aCx,
|
|||
{
|
||||
nsresult rv = aKey.SetFromJSVal(aCx, aVal);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB,
|
||||
"Bad error code!");
|
||||
MOZ_ASSERT(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -49,6 +39,42 @@ GetKeyFromJSVal(JSContext* aCx,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
IDBKeyRange::IDBKeyRange(nsISupports* aGlobal,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen,
|
||||
bool aIsOnly)
|
||||
: mGlobal(aGlobal)
|
||||
, mCachedLowerVal(JSVAL_VOID)
|
||||
, mCachedUpperVal(JSVAL_VOID)
|
||||
, mLowerOpen(aLowerOpen)
|
||||
, mUpperOpen(aUpperOpen)
|
||||
, mIsOnly(aIsOnly)
|
||||
, mHaveCachedLowerVal(false)
|
||||
, mHaveCachedUpperVal(false)
|
||||
, mRooted(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mOwningThread = PR_GetCurrentThread();
|
||||
#endif
|
||||
AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
IDBKeyRange::~IDBKeyRange()
|
||||
{
|
||||
DropJSObjects();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
IDBKeyRange::AssertIsOnOwningThread() const
|
||||
{
|
||||
MOZ_ASSERT(mOwningThread);
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBKeyRange::FromJSVal(JSContext* aCx,
|
||||
|
@ -87,9 +113,8 @@ IDBKeyRange::FromJSVal(JSContext* aCx,
|
|||
}
|
||||
|
||||
// static
|
||||
template <class T>
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
|
||||
IDBKeyRange::FromSerialized(const SerializedKeyRange& aKeyRange)
|
||||
{
|
||||
nsRefPtr<IDBKeyRange> keyRange =
|
||||
new IDBKeyRange(nullptr, aKeyRange.lowerOpen(), aKeyRange.upperOpen(),
|
||||
|
@ -101,12 +126,11 @@ IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
|
|||
return keyRange.forget();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
IDBKeyRange::ToSerializedKeyRange(T& aKeyRange)
|
||||
IDBKeyRange::ToSerialized(SerializedKeyRange& aKeyRange) const
|
||||
{
|
||||
aKeyRange.lowerOpen() = IsLowerOpen();
|
||||
aKeyRange.upperOpen() = IsUpperOpen();
|
||||
aKeyRange.lowerOpen() = LowerOpen();
|
||||
aKeyRange.upperOpen() = UpperOpen();
|
||||
aKeyRange.isOnly() = IsOnly();
|
||||
|
||||
aKeyRange.lower() = Lower();
|
||||
|
@ -115,6 +139,76 @@ IDBKeyRange::ToSerializedKeyRange(T& aKeyRange)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
IDBKeyRange::GetBindingClause(const nsACString& aKeyColumnName,
|
||||
nsACString& _retval) const
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
|
||||
NS_NAMED_LITERAL_CSTRING(spacecolon, " :");
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
|
||||
|
||||
if (IsOnly()) {
|
||||
// Both keys are set and they're equal.
|
||||
_retval = andStr + aKeyColumnName + NS_LITERAL_CSTRING(" =") +
|
||||
spacecolon + lowerKey;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString clause;
|
||||
|
||||
if (!Lower().IsUnset()) {
|
||||
// Lower key is set.
|
||||
clause.Append(andStr + aKeyColumnName);
|
||||
clause.AppendLiteral(" >");
|
||||
if (!LowerOpen()) {
|
||||
clause.Append('=');
|
||||
}
|
||||
clause.Append(spacecolon + lowerKey);
|
||||
}
|
||||
|
||||
if (!Upper().IsUnset()) {
|
||||
// Upper key is set.
|
||||
clause.Append(andStr + aKeyColumnName);
|
||||
clause.AppendLiteral(" <");
|
||||
if (!UpperOpen()) {
|
||||
clause.Append('=');
|
||||
}
|
||||
clause.Append(spacecolon + NS_LITERAL_CSTRING("upper_key"));
|
||||
}
|
||||
|
||||
_retval = clause;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IDBKeyRange::BindToStatement(mozIStorageStatement* aStatement) const
|
||||
{
|
||||
MOZ_ASSERT(aStatement);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
|
||||
|
||||
if (IsOnly()) {
|
||||
return Lower().BindToStatement(aStatement, lowerKey);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!Lower().IsUnset()) {
|
||||
rv = Lower().BindToStatement(aStatement, lowerKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Upper().IsUnset()) {
|
||||
rv = Upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
|
||||
|
@ -145,19 +239,14 @@ IDBKeyRange::DropJSObjects()
|
|||
if (!mRooted) {
|
||||
return;
|
||||
}
|
||||
mCachedLowerVal = JS::UndefinedValue();
|
||||
mCachedUpperVal = JS::UndefinedValue();
|
||||
mCachedLowerVal.setUndefined();
|
||||
mCachedUpperVal.setUndefined();
|
||||
mHaveCachedLowerVal = false;
|
||||
mHaveCachedUpperVal = false;
|
||||
mRooted = false;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
IDBKeyRange::~IDBKeyRange()
|
||||
{
|
||||
DropJSObjects();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
IDBKeyRange::WrapObject(JSContext* aCx)
|
||||
{
|
||||
|
@ -168,7 +257,7 @@ void
|
|||
IDBKeyRange::GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!mHaveCachedLowerVal) {
|
||||
if (!mRooted) {
|
||||
|
@ -192,7 +281,7 @@ void
|
|||
IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!mHaveCachedUpperVal) {
|
||||
if (!mRooted) {
|
||||
|
@ -215,10 +304,9 @@ IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
|||
// static
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::Only(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
|
||||
JS::Handle<JS::Value> aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange =
|
||||
new IDBKeyRange(aGlobal.GetAsSupports(), false, false, true);
|
||||
|
||||
|
@ -233,11 +321,10 @@ IDBKeyRange::Only(const GlobalObject& aGlobal,
|
|||
// static
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::LowerBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, bool aOpen,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
bool aOpen,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange =
|
||||
new IDBKeyRange(aGlobal.GetAsSupports(), aOpen, true, false);
|
||||
|
||||
|
@ -252,11 +339,10 @@ IDBKeyRange::LowerBound(const GlobalObject& aGlobal,
|
|||
// static
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::UpperBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, bool aOpen,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
bool aOpen,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange =
|
||||
new IDBKeyRange(aGlobal.GetAsSupports(), true, aOpen, false);
|
||||
|
||||
|
@ -271,11 +357,12 @@ IDBKeyRange::UpperBound(const GlobalObject& aGlobal,
|
|||
// static
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::Bound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
|
||||
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv)
|
||||
JS::Handle<JS::Value> aLower,
|
||||
JS::Handle<JS::Value> aUpper,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange =
|
||||
new IDBKeyRange(aGlobal.GetAsSupports(), aLowerOpen, aUpperOpen, false);
|
||||
|
||||
|
@ -298,9 +385,6 @@ IDBKeyRange::Bound(const GlobalObject& aGlobal,
|
|||
return keyRange.forget();
|
||||
}
|
||||
|
||||
// Explicitly instantiate for all our key range types... Grumble.
|
||||
template already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::FromSerializedKeyRange<KeyRange> (const KeyRange& aKeyRange);
|
||||
|
||||
template void
|
||||
IDBKeyRange::ToSerializedKeyRange<KeyRange> (KeyRange& aKeyRange);
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,144 +7,137 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbkeyrange_h__
|
||||
#define mozilla_dom_indexeddb_idbkeyrange_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class mozIStorageStatement;
|
||||
struct PRThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class GlobalObject;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace indexedDB {
|
||||
|
||||
namespace ipc {
|
||||
class KeyRange;
|
||||
} // namespace ipc
|
||||
class SerializedKeyRange;
|
||||
|
||||
class IDBKeyRange MOZ_FINAL : public nsISupports
|
||||
class IDBKeyRange MOZ_FINAL
|
||||
: public nsISupports
|
||||
{
|
||||
nsCOMPtr<nsISupports> mGlobal;
|
||||
Key mLower;
|
||||
Key mUpper;
|
||||
JS::Heap<JS::Value> mCachedLowerVal;
|
||||
JS::Heap<JS::Value> mCachedUpperVal;
|
||||
|
||||
const bool mLowerOpen : 1;
|
||||
const bool mUpperOpen : 1;
|
||||
const bool mIsOnly : 1;
|
||||
bool mHaveCachedLowerVal : 1;
|
||||
bool mHaveCachedUpperVal : 1;
|
||||
bool mRooted : 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRThread* mOwningThread;
|
||||
#endif
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange)
|
||||
|
||||
static nsresult FromJSVal(JSContext* aCx,
|
||||
static nsresult
|
||||
FromJSVal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal,
|
||||
IDBKeyRange** aKeyRange);
|
||||
|
||||
template <class T>
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
FromSerializedKeyRange(const T& aKeyRange);
|
||||
FromSerialized(const SerializedKeyRange& aKeyRange);
|
||||
|
||||
const Key& Lower() const
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
Only(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
LowerBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
bool aOpen,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
UpperBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
bool aOpen,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
Bound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aLower,
|
||||
JS::Handle<JS::Value> aUpper,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void
|
||||
ToSerialized(SerializedKeyRange& aKeyRange) const;
|
||||
|
||||
const Key&
|
||||
Lower() const
|
||||
{
|
||||
return mLower;
|
||||
}
|
||||
|
||||
Key& Lower()
|
||||
Key&
|
||||
Lower()
|
||||
{
|
||||
return mLower;
|
||||
}
|
||||
|
||||
const Key& Upper() const
|
||||
const Key&
|
||||
Upper() const
|
||||
{
|
||||
return mIsOnly ? mLower : mUpper;
|
||||
}
|
||||
|
||||
Key& Upper()
|
||||
Key&
|
||||
Upper()
|
||||
{
|
||||
return mIsOnly ? mLower : mUpper;
|
||||
}
|
||||
|
||||
// TODO: Remove these in favour of LowerOpen() / UpperOpen(), bug 900578.
|
||||
bool IsLowerOpen() const
|
||||
{
|
||||
return mLowerOpen;
|
||||
}
|
||||
|
||||
bool IsUpperOpen() const
|
||||
{
|
||||
return mUpperOpen;
|
||||
}
|
||||
|
||||
bool IsOnly() const
|
||||
bool
|
||||
IsOnly() const
|
||||
{
|
||||
return mIsOnly;
|
||||
}
|
||||
|
||||
void GetBindingClause(const nsACString& aKeyColumnName,
|
||||
nsACString& _retval) const
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
|
||||
NS_NAMED_LITERAL_CSTRING(spacecolon, " :");
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
|
||||
void
|
||||
GetBindingClause(const nsACString& aKeyColumnName,
|
||||
nsACString& _retval) const;
|
||||
|
||||
if (IsOnly()) {
|
||||
// Both keys are set and they're equal.
|
||||
_retval = andStr + aKeyColumnName + NS_LITERAL_CSTRING(" =") +
|
||||
spacecolon + lowerKey;
|
||||
}
|
||||
else {
|
||||
nsAutoCString clause;
|
||||
nsresult
|
||||
BindToStatement(mozIStorageStatement* aStatement) const;
|
||||
|
||||
if (!Lower().IsUnset()) {
|
||||
// Lower key is set.
|
||||
clause.Append(andStr + aKeyColumnName);
|
||||
clause.AppendLiteral(" >");
|
||||
if (!IsLowerOpen()) {
|
||||
clause.Append('=');
|
||||
}
|
||||
clause.Append(spacecolon + lowerKey);
|
||||
}
|
||||
|
||||
if (!Upper().IsUnset()) {
|
||||
// Upper key is set.
|
||||
clause.Append(andStr + aKeyColumnName);
|
||||
clause.AppendLiteral(" <");
|
||||
if (!IsUpperOpen()) {
|
||||
clause.Append('=');
|
||||
}
|
||||
clause.Append(spacecolon + NS_LITERAL_CSTRING("upper_key"));
|
||||
}
|
||||
|
||||
_retval = clause;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult BindToStatement(mozIStorageStatement* aStatement) const
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
|
||||
|
||||
if (IsOnly()) {
|
||||
return Lower().BindToStatement(aStatement, lowerKey);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!Lower().IsUnset()) {
|
||||
rv = Lower().BindToStatement(aStatement, lowerKey);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
|
||||
if (!Upper().IsUnset()) {
|
||||
rv = Upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ToSerializedKeyRange(T& aKeyRange);
|
||||
|
||||
void DropJSObjects();
|
||||
void
|
||||
DropJSObjects();
|
||||
|
||||
// WebIDL
|
||||
JSObject*
|
||||
|
@ -176,48 +169,17 @@ public:
|
|||
return mUpperOpen;
|
||||
}
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
Only(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
LowerBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
UpperBound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<IDBKeyRange>
|
||||
Bound(const GlobalObject& aGlobal,
|
||||
JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
|
||||
bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
IDBKeyRange(nsISupports* aGlobal,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen,
|
||||
bool aIsOnly)
|
||||
: mGlobal(aGlobal), mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID),
|
||||
mLowerOpen(aLowerOpen), mUpperOpen(aUpperOpen), mIsOnly(aIsOnly),
|
||||
mHaveCachedLowerVal(false), mHaveCachedUpperVal(false), mRooted(false)
|
||||
{ }
|
||||
bool aIsOnly);
|
||||
|
||||
~IDBKeyRange();
|
||||
|
||||
nsCOMPtr<nsISupports> mGlobal;
|
||||
Key mLower;
|
||||
Key mUpper;
|
||||
JS::Heap<JS::Value> mCachedLowerVal;
|
||||
JS::Heap<JS::Value> mCachedUpperVal;
|
||||
const bool mLowerOpen;
|
||||
const bool mUpperOpen;
|
||||
const bool mIsOnly;
|
||||
bool mHaveCachedLowerVal;
|
||||
bool mHaveCachedUpperVal;
|
||||
bool mRooted;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbkeyrange_h__
|
||||
|
|
|
@ -6,26 +6,36 @@
|
|||
|
||||
#include "IDBMutableFile.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
|
||||
#include "FileSnapshot.h"
|
||||
#include "FileInfo.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBFactory.h"
|
||||
#include "IDBFileHandle.h"
|
||||
#include "IDBFileRequest.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/FileService.h"
|
||||
#include "mozilla/dom/IDBMutableFileBinding.h"
|
||||
#include "mozilla/dom/MetadataHelper.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
|
||||
#include "mozilla/dom/quota/FileStreams.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#include "FileSnapshot.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBFileHandle.h"
|
||||
#include "IDBFileRequest.h"
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
using namespace mozilla::dom;
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
USING_QUOTA_NAMESPACE
|
||||
using namespace mozilla::dom::quota;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -48,7 +58,6 @@ public:
|
|||
ReleaseObjects() MOZ_OVERRIDE
|
||||
{
|
||||
mMutableFile = nullptr;
|
||||
|
||||
MetadataHelper::ReleaseObjects();
|
||||
}
|
||||
|
||||
|
@ -56,109 +65,213 @@ private:
|
|||
nsRefPtr<IDBMutableFile> mMutableFile;
|
||||
};
|
||||
|
||||
inline
|
||||
already_AddRefed<nsIFile>
|
||||
GetFileFor(FileInfo* aFileInfo)
|
||||
|
||||
{
|
||||
FileManager* fileManager = aFileInfo->Manager();
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
NS_ENSURE_TRUE(directory, nullptr);
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aFileInfo);
|
||||
|
||||
nsCOMPtr<nsIFile> file = fileManager->GetFileForId(directory,
|
||||
aFileInfo->Id());
|
||||
NS_ENSURE_TRUE(file, nullptr);
|
||||
FileManager* fileManager = aFileInfo->Manager();
|
||||
MOZ_ASSERT(fileManager);
|
||||
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
if (NS_WARN_IF(!directory)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file =
|
||||
fileManager->GetFileForId(directory, aFileInfo->Id());
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
IDBMutableFile::IDBMutableFile(IDBDatabase* aOwner)
|
||||
: DOMEventTargetHelper(aOwner)
|
||||
IDBMutableFile::IDBMutableFile(IDBDatabase* aDatabase,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
already_AddRefed<FileInfo> aFileInfo,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const nsACString& aStorageId,
|
||||
PersistenceType aPersistenceType,
|
||||
already_AddRefed<nsIFile> aFile)
|
||||
: DOMEventTargetHelper(aDatabase)
|
||||
, mDatabase(aDatabase)
|
||||
, mFileInfo(aFileInfo)
|
||||
, mGroup(aGroup)
|
||||
, mOrigin(aOrigin)
|
||||
, mPersistenceType(aPersistenceType)
|
||||
, mInvalidated(false)
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mDatabase);
|
||||
MOZ_ASSERT(mFileInfo);
|
||||
|
||||
mName = aName;
|
||||
mType = aType;
|
||||
mFile = aFile;
|
||||
mStorageId = aStorageId;
|
||||
mFileName.AppendInt(mFileInfo->Id());
|
||||
|
||||
MOZ_ASSERT(mFile);
|
||||
|
||||
mDatabase->NoteLiveMutableFile(this);
|
||||
}
|
||||
|
||||
IDBMutableFile::~IDBMutableFile()
|
||||
{
|
||||
// XXX This is always in the main process but it sometimes happens too late in
|
||||
// shutdown and the IndexedDatabaseManager has already been torn down.
|
||||
// MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mDatabase) {
|
||||
mDatabase->NoteFinishedMutableFile(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(IDBMutableFile, DOMEventTargetHelper,
|
||||
mDatabase)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBMutableFile)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
|
||||
// static
|
||||
already_AddRefed<IDBMutableFile>
|
||||
IDBMutableFile::Create(const nsAString& aName,
|
||||
IDBMutableFile::Create(IDBDatabase* aDatabase,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
IDBDatabase* aDatabase,
|
||||
already_AddRefed<FileInfo> aFileInfo)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<FileInfo> fileInfo(aFileInfo);
|
||||
NS_ASSERTION(fileInfo, "Null pointer!");
|
||||
MOZ_ASSERT(fileInfo);
|
||||
|
||||
nsRefPtr<IDBMutableFile> newFile = new IDBMutableFile(aDatabase);
|
||||
PrincipalInfo* principalInfo = aDatabase->Factory()->GetPrincipalInfo();
|
||||
MOZ_ASSERT(principalInfo);
|
||||
|
||||
newFile->mName = aName;
|
||||
newFile->mType = aType;
|
||||
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(*principalInfo);
|
||||
if (NS_WARN_IF(!principal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newFile->mFile = GetFileFor(fileInfo);
|
||||
NS_ENSURE_TRUE(newFile->mFile, nullptr);
|
||||
nsCString group;
|
||||
nsCString origin;
|
||||
if (NS_WARN_IF(NS_FAILED(QuotaManager::GetInfoFromPrincipal(principal,
|
||||
&group,
|
||||
&origin,
|
||||
nullptr,
|
||||
nullptr)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newFile->mStorageId = aDatabase->Id();
|
||||
newFile->mFileName.AppendInt(fileInfo->Id());
|
||||
const DatabaseSpec* spec = aDatabase->Spec();
|
||||
MOZ_ASSERT(spec);
|
||||
|
||||
newFile->mDatabase = aDatabase;
|
||||
fileInfo.swap(newFile->mFileInfo);
|
||||
PersistenceType persistenceType = spec->metadata().persistenceType();
|
||||
|
||||
nsCString storageId;
|
||||
QuotaManager::GetStorageId(persistenceType,
|
||||
origin,
|
||||
Client::IDB,
|
||||
aDatabase->Name(),
|
||||
storageId);
|
||||
|
||||
nsCOMPtr<nsIFile> file = GetFileFor(fileInfo);
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBMutableFile> newFile =
|
||||
new IDBMutableFile(aDatabase,
|
||||
aName,
|
||||
aType,
|
||||
fileInfo.forget(),
|
||||
group,
|
||||
origin,
|
||||
storageId,
|
||||
persistenceType,
|
||||
file.forget());
|
||||
|
||||
return newFile.forget();
|
||||
}
|
||||
|
||||
void
|
||||
IDBMutableFile::Invalidate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mInvalidated);
|
||||
|
||||
mInvalidated = true;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBMutableFile)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBMutableFile)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBMutableFile,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDatabase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBMutableFile,
|
||||
DOMEventTargetHelper)
|
||||
MOZ_ASSERT(tmp->mDatabase);
|
||||
tmp->mDatabase->NoteFinishedMutableFile(tmp);
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDatabase)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
bool
|
||||
IDBMutableFile::IsInvalid()
|
||||
{
|
||||
return mDatabase->IsInvalidated();
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
nsIOfflineStorage*
|
||||
IDBMutableFile::Storage()
|
||||
{
|
||||
return mDatabase;
|
||||
MOZ_CRASH("Don't call me!");
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
IDBMutableFile::CreateStream(bool aReadOnly)
|
||||
{
|
||||
PersistenceType persistenceType = mDatabase->Type();
|
||||
const nsACString& group = mDatabase->Group();
|
||||
const nsACString& origin = mDatabase->Origin();
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
|
||||
nsCOMPtr<nsISupports> result;
|
||||
|
||||
if (aReadOnly) {
|
||||
nsRefPtr<FileInputStream> stream =
|
||||
FileInputStream::Create(persistenceType, group, origin, mFile, -1, -1,
|
||||
FileInputStream::Create(mPersistenceType,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mFile,
|
||||
-1,
|
||||
-1,
|
||||
nsIFileInputStream::DEFER_OPEN);
|
||||
result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
nsRefPtr<FileStream> stream =
|
||||
FileStream::Create(persistenceType, group, origin, mFile, -1, -1,
|
||||
FileStream::Create(mPersistenceType,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mFile,
|
||||
-1,
|
||||
-1,
|
||||
nsIFileStream::DEFER_OPEN);
|
||||
result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
|
||||
}
|
||||
NS_ENSURE_TRUE(result, nullptr);
|
||||
|
||||
if (NS_WARN_IF(!result)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result.forget();
|
||||
}
|
||||
|
@ -166,33 +279,37 @@ IDBMutableFile::CreateStream(bool aReadOnly)
|
|||
void
|
||||
IDBMutableFile::SetThreadLocals()
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(mDatabase->GetOwner(), "Should have owner!");
|
||||
|
||||
QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
|
||||
}
|
||||
|
||||
void
|
||||
IDBMutableFile::UnsetThreadLocals()
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
|
||||
QuotaManager::SetCurrentWindow(nullptr);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMFile>
|
||||
IDBMutableFile::CreateFileObject(IDBFileHandle* aFileHandle, uint32_t aFileSize)
|
||||
{
|
||||
nsCOMPtr<nsIDOMFile> fileSnapshot = new DOMFile(
|
||||
new FileImplSnapshot(mName, mType, aFileSize, mFile, aFileHandle,
|
||||
mFileInfo));
|
||||
|
||||
return fileSnapshot.forget();
|
||||
}
|
||||
|
||||
// virtual
|
||||
JSObject*
|
||||
IDBMutableFile::WrapObject(JSContext* aCx)
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return IDBMutableFileBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
IDBDatabase*
|
||||
IDBMutableFile::Database() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBFileHandle>
|
||||
IDBMutableFile::Open(FileMode aMode, ErrorResult& aError)
|
||||
{
|
||||
|
@ -213,6 +330,31 @@ IDBMutableFile::Open(FileMode aMode, ErrorResult& aError)
|
|||
return fileHandle.forget();
|
||||
}
|
||||
|
||||
int64_t
|
||||
IDBMutableFile::GetFileId() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mFileInfo);
|
||||
|
||||
return mFileInfo->Id();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMFile>
|
||||
IDBMutableFile::CreateFileObject(IDBFileHandle* aFileHandle,
|
||||
MetadataParameters* aMetadataParams)
|
||||
{
|
||||
nsRefPtr<DOMFileImpl> impl =
|
||||
new FileImplSnapshot(mName,
|
||||
mType,
|
||||
aMetadataParams,
|
||||
mFile,
|
||||
aFileHandle,
|
||||
mFileInfo);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> fileSnapshot = new DOMFile(impl);
|
||||
return fileSnapshot.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
IDBMutableFile::GetFile(ErrorResult& aError)
|
||||
{
|
||||
|
@ -227,10 +369,11 @@ IDBMutableFile::GetFile(ErrorResult& aError)
|
|||
IDBFileHandle::Create(FileMode::Readonly, FileHandleBase::PARALLEL, this);
|
||||
|
||||
nsRefPtr<IDBFileRequest> request =
|
||||
IDBFileRequest::Create(GetOwner(), fileHandle, /* aWrapAsDOMRequest */
|
||||
true);
|
||||
IDBFileRequest::Create(GetOwner(),
|
||||
fileHandle,
|
||||
/* aWrapAsDOMRequest */ true);
|
||||
|
||||
nsRefPtr<MetadataParameters> params = new MetadataParameters(true, false);
|
||||
nsRefPtr<MetadataParameters> params = new MetadataParameters(true, true);
|
||||
|
||||
nsRefPtr<GetFileHelper> helper =
|
||||
new GetFileHelper(fileHandle, request, params, this);
|
||||
|
@ -244,10 +387,6 @@ IDBMutableFile::GetFile(ErrorResult& aError)
|
|||
return request.forget();
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
nsresult
|
||||
GetFileHelper::GetSuccessResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal)
|
||||
|
@ -257,7 +396,7 @@ GetFileHelper::GetSuccessResult(JSContext* aCx,
|
|||
auto fileHandle = static_cast<IDBFileHandle*>(mFileHandle.get());
|
||||
|
||||
nsCOMPtr<nsIDOMFile> domFile =
|
||||
mMutableFile->CreateFileObject(fileHandle, mParams->Size());
|
||||
mMutableFile->CreateFileObject(fileHandle, mParams);
|
||||
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, domFile, &NS_GET_IID(nsIDOMFile), aVal);
|
||||
|
@ -267,3 +406,7 @@ GetFileHelper::GetSuccessResult(JSContext* aCx,
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#define mozilla_dom_indexeddb_idbmutablefile_h__
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/FileModeBinding.h"
|
||||
#include "mozilla/dom/indexedDB/FileInfo.h"
|
||||
#include "mozilla/dom/MutableFile.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/FileModeBinding.h"
|
||||
#include "mozilla/dom/MutableFile.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
|
@ -28,23 +28,39 @@ class ErrorResult;
|
|||
namespace dom {
|
||||
|
||||
class DOMRequest;
|
||||
class MetadataParameters;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class FileInfo;
|
||||
class IDBDatabase;
|
||||
class IDBFileHandle;
|
||||
|
||||
class IDBMutableFile MOZ_FINAL : public DOMEventTargetHelper,
|
||||
public MutableFileBase
|
||||
class IDBMutableFile MOZ_FINAL
|
||||
: public DOMEventTargetHelper
|
||||
, public MutableFileBase
|
||||
{
|
||||
typedef mozilla::dom::MetadataParameters MetadataParameters;
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
|
||||
nsString mName;
|
||||
nsString mType;
|
||||
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
|
||||
const nsCString mGroup;
|
||||
const nsCString mOrigin;
|
||||
const PersistenceType mPersistenceType;
|
||||
|
||||
Atomic<bool> mInvalidated;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
|
||||
static already_AddRefed<IDBMutableFile>
|
||||
Create(const nsAString& aName, const nsAString& aType,
|
||||
IDBDatabase* aDatabase, already_AddRefed<FileInfo> aFileInfo);
|
||||
Create(IDBDatabase* aDatabase,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
already_AddRefed<FileInfo> aFileInfo);
|
||||
|
||||
const nsAString&
|
||||
Name() const
|
||||
|
@ -59,10 +75,7 @@ public:
|
|||
}
|
||||
|
||||
int64_t
|
||||
GetFileId() const
|
||||
{
|
||||
return mFileInfo->Id();
|
||||
}
|
||||
GetFileId() const;
|
||||
|
||||
FileInfo*
|
||||
GetFileInfo() const
|
||||
|
@ -70,6 +83,16 @@ public:
|
|||
return mFileInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMFile>
|
||||
CreateFileObject(IDBFileHandle* aFileHandle,
|
||||
MetadataParameters* aMetadataParams);
|
||||
|
||||
void
|
||||
Invalidate();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBMutableFile, DOMEventTargetHelper)
|
||||
|
||||
virtual bool
|
||||
IsInvalid() MOZ_OVERRIDE;
|
||||
|
||||
|
@ -85,9 +108,6 @@ public:
|
|||
virtual void
|
||||
UnsetThreadLocals() MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<nsIDOMFile>
|
||||
CreateFileObject(IDBFileHandle* aFileHandle, uint32_t aFileSize);
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
@ -112,12 +132,7 @@ public:
|
|||
}
|
||||
|
||||
IDBDatabase*
|
||||
Database()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
return mDatabase;
|
||||
}
|
||||
Database() const;
|
||||
|
||||
already_AddRefed<IDBFileHandle>
|
||||
Open(FileMode aMode, ErrorResult& aError);
|
||||
|
@ -129,14 +144,17 @@ public:
|
|||
IMPL_EVENT_HANDLER(error)
|
||||
|
||||
private:
|
||||
explicit IDBMutableFile(IDBDatabase* aOwner);
|
||||
IDBMutableFile(IDBDatabase* aDatabase,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
already_AddRefed<FileInfo> aFileInfo,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const nsACString& aStorageId,
|
||||
PersistenceType aPersistenceType,
|
||||
already_AddRefed<nsIFile> aFile);
|
||||
|
||||
~IDBMutableFile();
|
||||
|
||||
nsString mName;
|
||||
nsString mType;
|
||||
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,61 +7,68 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbobjectstore_h__
|
||||
#define mozilla_dom_indexeddb_idbobjectstore_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/dom/IDBCursorBinding.h"
|
||||
#include "mozilla/dom/IDBIndexBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "mozilla/dom/indexedDB/KeyPath.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIScriptContext;
|
||||
struct JSClass;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class DOMStringList;
|
||||
class nsIContentParent;
|
||||
class PBlobChild;
|
||||
class PBlobParent;
|
||||
}
|
||||
}
|
||||
template <typename> class Sequence;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace indexedDB {
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class FileManager;
|
||||
class IDBCursor;
|
||||
class IDBKeyRange;
|
||||
class IDBRequest;
|
||||
class IndexedDBObjectStoreChild;
|
||||
class IndexedDBObjectStoreParent;
|
||||
class IDBTransaction;
|
||||
class IndexUpdateInfo;
|
||||
class Key;
|
||||
class KeyPath;
|
||||
class ObjectStoreSpec;
|
||||
struct StructuredCloneFile;
|
||||
struct StructuredCloneReadInfo;
|
||||
|
||||
struct IndexInfo;
|
||||
struct IndexUpdateInfo;
|
||||
struct ObjectStoreInfo;
|
||||
|
||||
struct MutableFileData;
|
||||
struct BlobOrFileData;
|
||||
|
||||
class IDBObjectStore MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class IDBObjectStore MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
static const JSClass sDummyPropJSClass;
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
|
||||
// This normally points to the ObjectStoreSpec owned by the parent IDBDatabase
|
||||
// object. However, if this objectStore is part of a versionchange transaction
|
||||
// and it gets deleted then the spec is copied into mDeletedSpec and mSpec is
|
||||
// set to point at mDeletedSpec.
|
||||
const ObjectStoreSpec* mSpec;
|
||||
nsAutoPtr<ObjectStoreSpec> mDeletedSpec;
|
||||
|
||||
nsTArray<nsRefPtr<IDBIndex>> mIndexes;
|
||||
|
||||
const int64_t mId;
|
||||
bool mRooted;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore)
|
||||
struct StructuredCloneWriteInfo;
|
||||
|
||||
static already_AddRefed<IDBObjectStore>
|
||||
Create(IDBTransaction* aTransaction,
|
||||
ObjectStoreInfo* aInfo,
|
||||
const nsACString& aDatabaseId,
|
||||
bool aCreating);
|
||||
Create(IDBTransaction* aTransaction, const ObjectStoreSpec& aSpec);
|
||||
|
||||
static nsresult
|
||||
AppendIndexUpdateInfo(int64_t aIndexID,
|
||||
|
@ -72,214 +79,62 @@ public:
|
|||
JS::Handle<JS::Value> aObject,
|
||||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
|
||||
static nsresult
|
||||
UpdateIndexes(IDBTransaction* aTransaction,
|
||||
int64_t aObjectStoreId,
|
||||
const Key& aObjectStoreKey,
|
||||
bool aOverwrite,
|
||||
int64_t aObjectDataId,
|
||||
const nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
|
||||
static nsresult
|
||||
GetStructuredCloneReadInfoFromStatement(mozIStorageStatement* aStatement,
|
||||
uint32_t aDataIndex,
|
||||
uint32_t aFileIdsIndex,
|
||||
IDBDatabase* aDatabase,
|
||||
StructuredCloneReadInfo& aInfo);
|
||||
|
||||
static void
|
||||
ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo);
|
||||
|
||||
static void
|
||||
ClearCloneWriteInfo(StructuredCloneWriteInfo& aWriteInfo);
|
||||
|
||||
static bool
|
||||
DeserializeValue(JSContext* aCx,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
static bool
|
||||
SerializeValue(JSContext* aCx,
|
||||
StructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
DeserializeIndexValue(JSContext* aCx,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
template <class DeserializationTraits>
|
||||
static JSObject*
|
||||
StructuredCloneReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aData,
|
||||
void* aClosure);
|
||||
static bool
|
||||
StructuredCloneWriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure);
|
||||
|
||||
static nsresult
|
||||
ConvertFileIdsToArray(const nsAString& aFileIds,
|
||||
nsTArray<int64_t>& aResult);
|
||||
|
||||
// Called only in the main process.
|
||||
static nsresult
|
||||
ConvertBlobsToActors(nsIContentParent* aContentParent,
|
||||
FileManager* aFileManager,
|
||||
const nsTArray<StructuredCloneFile>& aFiles,
|
||||
InfallibleTArray<PBlobParent*>& aActors);
|
||||
|
||||
// Called only in the child process.
|
||||
static void
|
||||
ConvertActorsToBlobs(const InfallibleTArray<PBlobChild*>& aActors,
|
||||
nsTArray<StructuredCloneFile>& aFiles);
|
||||
|
||||
const nsString& Name() const
|
||||
static const JSClass*
|
||||
DummyPropClass()
|
||||
{
|
||||
return mName;
|
||||
return &sDummyPropJSClass;
|
||||
}
|
||||
|
||||
bool IsAutoIncrement() const
|
||||
{
|
||||
return mAutoIncrement;
|
||||
}
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
bool IsWriteAllowed() const
|
||||
int64_t
|
||||
Id() const
|
||||
{
|
||||
return mTransaction->IsWriteAllowed();
|
||||
}
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
int64_t Id() const
|
||||
{
|
||||
NS_ASSERTION(mId != INT64_MIN, "Don't ask for this yet!");
|
||||
return mId;
|
||||
}
|
||||
|
||||
const KeyPath& GetKeyPath() const
|
||||
{
|
||||
return mKeyPath;
|
||||
}
|
||||
const nsString&
|
||||
Name() const;
|
||||
|
||||
const bool HasValidKeyPath() const
|
||||
{
|
||||
return mKeyPath.IsValid();
|
||||
}
|
||||
bool
|
||||
AutoIncrement() const;
|
||||
|
||||
IDBTransaction* Transaction()
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
const KeyPath&
|
||||
GetKeyPath() const;
|
||||
|
||||
ObjectStoreInfo* Info()
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
bool
|
||||
HasValidKeyPath() const;
|
||||
|
||||
void
|
||||
SetActor(IndexedDBObjectStoreChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBObjectStoreParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBObjectStoreChild*
|
||||
GetActorChild() const
|
||||
{
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
IndexedDBObjectStoreParent*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBIndex>
|
||||
CreateIndexInternal(const IndexInfo& aInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult AddOrPutInternal(
|
||||
const SerializedStructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
const Key& aKey,
|
||||
const InfallibleTArray<IndexUpdateInfo>& aUpdateInfoArray,
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
|
||||
bool aOverwrite,
|
||||
IDBRequest** _retval);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllInternal(IDBKeyRange* aKeyRange,
|
||||
uint32_t aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllKeysInternal(IDBKeyRange* aKeyRange,
|
||||
uint32_t aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
DeleteInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
CountInternal(IDBKeyRange* aKeyRange,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursorInternal(IDBKeyRange* aKeyRange,
|
||||
size_t aDirection,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
|
||||
size_t aDirection,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult
|
||||
OpenCursorFromChildProcess(
|
||||
IDBRequest* aRequest,
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval);
|
||||
|
||||
nsresult
|
||||
OpenCursorFromChildProcess(IDBRequest* aRequest,
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
IDBCursor** _retval);
|
||||
|
||||
void
|
||||
SetInfo(ObjectStoreInfo* aInfo);
|
||||
|
||||
static const JSClass sDummyPropJSClass;
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
IDBTransaction*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mTransaction;
|
||||
}
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const;
|
||||
|
||||
void
|
||||
GetName(nsString& aName) const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
aName.Assign(mName);
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
aName = Name();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -287,38 +142,38 @@ public:
|
|||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMStringList>
|
||||
GetIndexNames(ErrorResult& aRv);
|
||||
IndexNames();
|
||||
|
||||
IDBTransaction*
|
||||
Transaction() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
bool
|
||||
AutoIncrement() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mAutoIncrement;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Put(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey, ErrorResult& aRv)
|
||||
Add(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return AddOrPut(aCx, aValue, aKey, true, aRv);
|
||||
}
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Add(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey, ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return AddOrPut(aCx, aValue, aKey, false, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Put(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return AddOrPut(aCx, aValue, aKey, true, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Delete(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
|
||||
|
||||
|
@ -328,18 +183,19 @@ public:
|
|||
already_AddRefed<IDBRequest>
|
||||
Clear(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection, ErrorResult& aRv);
|
||||
already_AddRefed<IDBIndex>
|
||||
CreateIndex(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
const nsAString& aKeyPath,
|
||||
const IDBIndexParameters& aOptionalParameters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBIndex>
|
||||
CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath,
|
||||
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBIndex>
|
||||
CreateIndex(JSContext* aCx, const nsAString& aName,
|
||||
CreateIndex(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
const Sequence<nsString>& aKeyPath,
|
||||
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
|
||||
const IDBIndexParameters& aOptionalParameters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBIndex>
|
||||
Index(const nsAString& aName, ErrorResult &aRv);
|
||||
|
@ -348,26 +204,79 @@ public:
|
|||
DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
Count(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
|
||||
GetAll(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return GetAllInternal(/* aKeysOnly */ false, aCx, aKey, aLimit, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit, ErrorResult& aRv);
|
||||
GetAllKeys(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return GetAllInternal(/* aKeysOnly */ true, aCx, aKey, aLimit, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection, ErrorResult& aRv);
|
||||
OpenCursor(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return OpenCursorInternal(/* aKeysOnly */ false, aCx, aRange, aDirection,
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenKeyCursor(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return OpenCursorInternal(/* aKeysOnly */ true, aCx, aRange, aDirection,
|
||||
aRv);
|
||||
}
|
||||
|
||||
void
|
||||
RefreshSpec(bool aMayDelete);
|
||||
|
||||
const ObjectStoreSpec&
|
||||
Spec() const;
|
||||
|
||||
void
|
||||
NoteDeletion();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
IDBObjectStore(IDBTransaction* aTransaction, const ObjectStoreSpec* aSpec);
|
||||
|
||||
protected:
|
||||
IDBObjectStore();
|
||||
~IDBObjectStore();
|
||||
|
||||
nsresult GetAddInfo(JSContext* aCx,
|
||||
nsresult
|
||||
GetAddInfo(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKeyVal,
|
||||
StructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
|
@ -375,43 +284,36 @@ protected:
|
|||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey, bool aOverwrite,
|
||||
AddOrPut(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
bool aOverwrite,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBRequest>
|
||||
GetAllInternal(bool aKeysOnly,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
const Optional<uint32_t>& aLimit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<IDBIndex>
|
||||
CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath,
|
||||
const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
|
||||
CreateIndexInternal(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
const KeyPath& aKeyPath,
|
||||
const IDBIndexParameters& aOptionalParameters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
|
||||
|
||||
static bool
|
||||
ReadMutableFile(JSStructuredCloneReader* aReader,
|
||||
MutableFileData* aRetval);
|
||||
|
||||
static bool
|
||||
ReadBlobOrFile(JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
BlobOrFileData* aRetval);
|
||||
private:
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
int64_t mId;
|
||||
nsString mName;
|
||||
KeyPath mKeyPath;
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
bool mRooted;
|
||||
bool mAutoIncrement;
|
||||
nsCString mDatabaseId;
|
||||
nsRefPtr<ObjectStoreInfo> mInfo;
|
||||
|
||||
nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;
|
||||
|
||||
IndexedDBObjectStoreChild* mActorChild;
|
||||
IndexedDBObjectStoreParent* mActorParent;
|
||||
already_AddRefed<IDBRequest>
|
||||
OpenCursorInternal(bool aKeysOnly,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aRange,
|
||||
IDBCursorDirection aDirection,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbobjectstore_h__
|
||||
|
|
|
@ -6,78 +6,88 @@
|
|||
|
||||
#include "IDBRequest.h"
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
#include "BackgroundChildImpl.h"
|
||||
#include "IDBCursor.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBEvents.h"
|
||||
#include "IDBFactory.h"
|
||||
#include "IDBIndex.h"
|
||||
#include "IDBObjectStore.h"
|
||||
#include "IDBTransaction.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsString.h"
|
||||
#include "ReportInternalError.h"
|
||||
|
||||
namespace {
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t gNextRequestSerialNumber = 1;
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
|
||||
using mozilla::dom::ErrorEventInit;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
IDBRequest::IDBRequest(IDBDatabase* aDatabase)
|
||||
: IDBWrapperCache(aDatabase),
|
||||
mResultVal(JSVAL_VOID),
|
||||
mActorParent(nullptr),
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
mSerialNumber(gNextRequestSerialNumber++),
|
||||
#endif
|
||||
mErrorCode(NS_OK),
|
||||
mLineNo(0),
|
||||
mHaveResultOrErrorCode(false)
|
||||
: IDBWrapperCache(aDatabase)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(aDatabase);
|
||||
aDatabase->AssertIsOnOwningThread();
|
||||
|
||||
InitMembers();
|
||||
}
|
||||
|
||||
IDBRequest::IDBRequest(nsPIDOMWindow* aOwner)
|
||||
: IDBWrapperCache(aOwner),
|
||||
mResultVal(JSVAL_VOID),
|
||||
mActorParent(nullptr),
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
mSerialNumber(gNextRequestSerialNumber++),
|
||||
#endif
|
||||
mErrorCode(NS_OK),
|
||||
mLineNo(0),
|
||||
mHaveResultOrErrorCode(false)
|
||||
: IDBWrapperCache(aOwner)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
InitMembers();
|
||||
}
|
||||
|
||||
IDBRequest::~IDBRequest()
|
||||
{
|
||||
mResultVal = JSVAL_VOID;
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
IDBRequest::AssertIsOnOwningThread() const
|
||||
{
|
||||
MOZ_ASSERT(mOwningThread);
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
void
|
||||
IDBRequest::InitMembers()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mOwningThread = PR_GetCurrentThread();
|
||||
#endif
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mResultVal.setUndefined();
|
||||
mErrorCode = NS_OK;
|
||||
mLineNo = 0;
|
||||
mHaveResultOrErrorCode = false;
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
{
|
||||
BackgroundChildImpl::ThreadLocal* threadLocal =
|
||||
BackgroundChildImpl::GetThreadLocalForCurrentThread();
|
||||
MOZ_ASSERT(threadLocal);
|
||||
|
||||
mSerialNumber = threadLocal->mNextRequestSerialNumber++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -85,16 +95,15 @@ already_AddRefed<IDBRequest>
|
|||
IDBRequest::Create(IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
nsRefPtr<IDBRequest> request(new IDBRequest(aDatabase));
|
||||
MOZ_ASSERT(aDatabase);
|
||||
aDatabase->AssertIsOnOwningThread();
|
||||
|
||||
nsRefPtr<IDBRequest> request = new IDBRequest(aDatabase);
|
||||
|
||||
request->mTransaction = aTransaction;
|
||||
request->SetScriptOwner(aDatabase->GetScriptOwner());
|
||||
|
||||
if (!aDatabase->Factory()->FromIPC()) {
|
||||
request->CaptureCaller();
|
||||
}
|
||||
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -105,6 +114,9 @@ IDBRequest::Create(IDBObjectStore* aSourceAsObjectStore,
|
|||
IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction)
|
||||
{
|
||||
MOZ_ASSERT(aSourceAsObjectStore);
|
||||
aSourceAsObjectStore->AssertIsOnOwningThread();
|
||||
|
||||
nsRefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
|
||||
|
||||
request->mSourceAsObjectStore = aSourceAsObjectStore;
|
||||
|
@ -118,6 +130,9 @@ IDBRequest::Create(IDBIndex* aSourceAsIndex,
|
|||
IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction)
|
||||
{
|
||||
MOZ_ASSERT(aSourceAsIndex);
|
||||
aSourceAsIndex->AssertIsOnOwningThread();
|
||||
|
||||
nsRefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
|
||||
|
||||
request->mSourceAsIndex = aSourceAsIndex;
|
||||
|
@ -125,31 +140,24 @@ IDBRequest::Create(IDBIndex* aSourceAsIndex,
|
|||
return request.forget();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
IDBRequest::AssertSourceIsCorrect() const
|
||||
IDBRequest::GetSource(
|
||||
Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
|
||||
{
|
||||
// At most one of mSourceAs* is allowed to be non-null. Check that by
|
||||
// summing the double negation of each one and asserting the sum is at most
|
||||
// 1.
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
MOZ_ASSERT(!!mSourceAsObjectStore + !!mSourceAsIndex + !!mSourceAsCursor <= 1);
|
||||
}
|
||||
#endif
|
||||
MOZ_ASSERT_IF(mSourceAsObjectStore, !mSourceAsIndex);
|
||||
MOZ_ASSERT_IF(mSourceAsIndex, !mSourceAsObjectStore);
|
||||
MOZ_ASSERT_IF(mSourceAsCursor, mSourceAsObjectStore || mSourceAsIndex);
|
||||
|
||||
void
|
||||
IDBRequest::GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
AssertSourceIsCorrect();
|
||||
|
||||
if (mSourceAsObjectStore) {
|
||||
// Always check cursor first since cursor requests hold both the cursor and
|
||||
// the objectStore or index the cursor came from.
|
||||
if (mSourceAsCursor) {
|
||||
aSource.SetValue().SetAsIDBCursor() = mSourceAsCursor;
|
||||
} else if (mSourceAsObjectStore) {
|
||||
aSource.SetValue().SetAsIDBObjectStore() = mSourceAsObjectStore;
|
||||
} else if (mSourceAsIndex) {
|
||||
aSource.SetValue().SetAsIDBIndex() = mSourceAsIndex;
|
||||
} else if (mSourceAsCursor) {
|
||||
aSource.SetValue().SetAsIDBCursor() = mSourceAsCursor;
|
||||
} else {
|
||||
aSource.SetNull();
|
||||
}
|
||||
|
@ -158,116 +166,63 @@ IDBRequest::GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSour
|
|||
void
|
||||
IDBRequest::Reset()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mResultVal = JSVAL_VOID;
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mResultVal.setUndefined();
|
||||
mHaveResultOrErrorCode = false;
|
||||
mError = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
|
||||
NS_ASSERTION(mResultVal.isUndefined(), "Should be undefined!");
|
||||
|
||||
mHaveResultOrErrorCode = true;
|
||||
|
||||
nsresult rv = aHelper->GetResultCode();
|
||||
|
||||
// If the request failed then set the error code and return.
|
||||
if (NS_FAILED(rv)) {
|
||||
SetError(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// See if our window is still valid. If not then we're going to pretend that
|
||||
// we never completed.
|
||||
if (NS_FAILED(CheckInnerWindowCorrectness())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise we need to get the result from the helper.
|
||||
AutoJSAPI jsapi;
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (GetScriptOwner()) {
|
||||
// If we have a script owner we want the SafeJSContext and then to enter
|
||||
// the script owner's compartment.
|
||||
jsapi.Init();
|
||||
ac.emplace(jsapi.cx(), GetScriptOwner());
|
||||
} else {
|
||||
// Otherwise our owner is a window and we use that to initialize.
|
||||
if (!jsapi.InitWithLegacyErrorReporting(GetOwner())) {
|
||||
IDB_WARNING("Failed to initialise AutoJSAPI!");
|
||||
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
SetError(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
AssertIsRooted();
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
rv = aHelper->GetSuccessResult(cx, &value);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("GetSuccessResult failed!");
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mError = nullptr;
|
||||
mResultVal = value;
|
||||
}
|
||||
else {
|
||||
SetError(rv);
|
||||
mResultVal = JSVAL_VOID;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
IDBRequest::NotifyHelperSentResultsToChildProcess(nsresult aRv)
|
||||
IDBRequest::DispatchNonTransactionError(nsresult aErrorCode)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
|
||||
NS_ASSERTION(mResultVal.isUndefined(), "Should be undefined!");
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(NS_FAILED(aErrorCode));
|
||||
MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
||||
|
||||
// See if our window is still valid. If not then we're going to pretend that
|
||||
// we never completed.
|
||||
if (NS_FAILED(CheckInnerWindowCorrectness())) {
|
||||
SetError(aErrorCode);
|
||||
|
||||
// Make an error event and fire it at the target.
|
||||
nsCOMPtr<nsIDOMEvent> event =
|
||||
CreateGenericEvent(this,
|
||||
nsDependentString(kErrorEventType),
|
||||
eDoesBubble,
|
||||
eCancelable);
|
||||
if (NS_WARN_IF(!event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mHaveResultOrErrorCode = true;
|
||||
|
||||
if (NS_FAILED(aRv)) {
|
||||
SetError(aRv);
|
||||
}
|
||||
bool ignored;
|
||||
NS_WARN_IF(NS_FAILED(DispatchEvent(event, &ignored)));
|
||||
}
|
||||
|
||||
void
|
||||
IDBRequest::SetError(nsresult aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_FAILED(aRv), "Er, what?");
|
||||
NS_ASSERTION(!mError, "Already have an error?");
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(NS_FAILED(aRv));
|
||||
MOZ_ASSERT(NS_ERROR_GET_MODULE(aRv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
||||
MOZ_ASSERT(!mError);
|
||||
|
||||
mHaveResultOrErrorCode = true;
|
||||
mError = new mozilla::dom::DOMError(GetOwner(), aRv);
|
||||
mError = new DOMError(GetOwner(), aRv);
|
||||
mErrorCode = aRv;
|
||||
|
||||
mResultVal = JSVAL_VOID;
|
||||
mResultVal.setUndefined();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
nsresult
|
||||
IDBRequest::GetErrorCode() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(mHaveResultOrErrorCode, "Don't call me yet!");
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mHaveResultOrErrorCode);
|
||||
|
||||
return mErrorCode;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
void
|
||||
IDBRequest::CaptureCaller()
|
||||
|
@ -277,7 +232,6 @@ IDBRequest::CaptureCaller()
|
|||
const char* filename = nullptr;
|
||||
uint32_t lineNo = 0;
|
||||
if (!nsJSUtils::GetCallingLocation(cx, &filename, &lineNo)) {
|
||||
NS_WARNING("Failed to get caller.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -292,16 +246,25 @@ IDBRequest::FillScriptErrorEvent(ErrorEventInit& aEventInit) const
|
|||
aEventInit.mFilename = mFilename;
|
||||
}
|
||||
|
||||
mozilla::dom::IDBRequestReadyState
|
||||
IDBRequestReadyState
|
||||
IDBRequest::ReadyState() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (IsPending()) {
|
||||
return IDBRequestReadyState::Pending;
|
||||
}
|
||||
return IsPending() ?
|
||||
IDBRequestReadyState::Pending :
|
||||
IDBRequestReadyState::Done;
|
||||
}
|
||||
|
||||
return IDBRequestReadyState::Done;
|
||||
void
|
||||
IDBRequest::SetSource(IDBCursor* aSource)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aSource);
|
||||
MOZ_ASSERT(mSourceAsObjectStore || mSourceAsIndex);
|
||||
MOZ_ASSERT(!mSourceAsCursor);
|
||||
|
||||
mSourceAsCursor = aSource;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -314,21 +277,72 @@ void
|
|||
IDBRequest::GetResult(JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!mHaveResultOrErrorCode) {
|
||||
// XXX Need a real error code here.
|
||||
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::ExposeValueToActiveJS(mResultVal);
|
||||
aResult.set(mResultVal);
|
||||
}
|
||||
|
||||
mozilla::dom::DOMError*
|
||||
IDBRequest::GetError(mozilla::ErrorResult& aRv)
|
||||
void
|
||||
IDBRequest::SetResultCallback(ResultCallback* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(!mHaveResultOrErrorCode);
|
||||
MOZ_ASSERT(mResultVal.isUndefined());
|
||||
MOZ_ASSERT(!mError);
|
||||
|
||||
// See if our window is still valid.
|
||||
if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
AutoJSAPI autoJS;
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
|
||||
if (GetScriptOwner()) {
|
||||
// If we have a script owner we want the SafeJSContext and then to enter the
|
||||
// script owner's compartment.
|
||||
autoJS.Init();
|
||||
ac.emplace(autoJS.cx(), GetScriptOwner());
|
||||
} else {
|
||||
// Otherwise our owner is a window and we use that to initialize.
|
||||
MOZ_ASSERT(GetOwner());
|
||||
if (!autoJS.InitWithLegacyErrorReporting(GetOwner())) {
|
||||
IDB_WARNING("Failed to initialize AutoJSAPI!");
|
||||
SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JSContext* cx = autoJS.cx();
|
||||
|
||||
AssertIsRooted();
|
||||
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
nsresult rv = aCallback->GetResult(cx, &result);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
SetError(rv);
|
||||
mResultVal.setUndefined();
|
||||
} else {
|
||||
mError = nullptr;
|
||||
mResultVal = result;
|
||||
}
|
||||
|
||||
mHaveResultOrErrorCode = true;
|
||||
}
|
||||
|
||||
DOMError*
|
||||
IDBRequest::GetError(ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!mHaveResultOrErrorCode) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
@ -351,7 +365,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
|
||||
tmp->mResultVal = JSVAL_VOID;
|
||||
tmp->mResultVal.setUndefined();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsObjectStore)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsIndex)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsCursor)
|
||||
|
@ -374,41 +388,60 @@ NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
|
|||
nsresult
|
||||
IDBRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
aVisitor.mCanHandle = true;
|
||||
aVisitor.mParentTarget = mTransaction;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
IDBOpenDBRequest::IDBOpenDBRequest(nsPIDOMWindow* aOwner)
|
||||
IDBOpenDBRequest::IDBOpenDBRequest(IDBFactory* aFactory, nsPIDOMWindow* aOwner)
|
||||
: IDBRequest(aOwner)
|
||||
, mFactory(aFactory)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aFactory);
|
||||
|
||||
// aOwner may be null.
|
||||
}
|
||||
|
||||
IDBOpenDBRequest::~IDBOpenDBRequest()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
IDBOpenDBRequest::Create(IDBFactory* aFactory,
|
||||
IDBOpenDBRequest::CreateForWindow(IDBFactory* aFactory,
|
||||
nsPIDOMWindow* aOwner,
|
||||
JS::Handle<JSObject*> aScriptOwner)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aFactory, "Null pointer!");
|
||||
MOZ_ASSERT(aFactory);
|
||||
aFactory->AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aOwner);
|
||||
MOZ_ASSERT(aScriptOwner);
|
||||
|
||||
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aOwner);
|
||||
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aFactory, aOwner);
|
||||
request->CaptureCaller();
|
||||
|
||||
request->SetScriptOwner(aScriptOwner);
|
||||
request->mFactory = aFactory;
|
||||
|
||||
if (!aFactory->FromIPC()) {
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
IDBOpenDBRequest::CreateForJS(IDBFactory* aFactory,
|
||||
JS::Handle<JSObject*> aScriptOwner)
|
||||
{
|
||||
MOZ_ASSERT(aFactory);
|
||||
aFactory->AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aScriptOwner);
|
||||
|
||||
nsRefPtr<IDBOpenDBRequest> request = new IDBOpenDBRequest(aFactory, nullptr);
|
||||
request->CaptureCaller();
|
||||
}
|
||||
|
||||
request->SetScriptOwner(aScriptOwner);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -416,10 +449,9 @@ IDBOpenDBRequest::Create(IDBFactory* aFactory,
|
|||
void
|
||||
IDBOpenDBRequest::SetTransaction(IDBTransaction* aTransaction)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
NS_ASSERTION(!aTransaction || !mTransaction,
|
||||
"Shouldn't have a transaction here!");
|
||||
MOZ_ASSERT(!aTransaction || !mTransaction);
|
||||
|
||||
mTransaction = aTransaction;
|
||||
}
|
||||
|
@ -445,11 +477,20 @@ NS_IMPL_RELEASE_INHERITED(IDBOpenDBRequest, IDBRequest)
|
|||
nsresult
|
||||
IDBOpenDBRequest::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
{
|
||||
// XXX Fix me!
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return IndexedDatabaseManager::FireWindowOnError(GetOwner(), aVisitor);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
IDBOpenDBRequest::WrapObject(JSContext* aCx)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return IDBOpenDBRequestBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,72 +7,98 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbrequest_h__
|
||||
#define mozilla_dom_indexeddb_idbrequest_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/IDBRequestBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
struct PRThread;
|
||||
|
||||
namespace mozilla {
|
||||
class EventChainPostVisitor;
|
||||
class EventChainPreVisitor;
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
|
||||
|
||||
class DOMError;
|
||||
struct ErrorEventInit;
|
||||
}
|
||||
}
|
||||
template <typename> struct Nullable;
|
||||
class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace indexedDB {
|
||||
|
||||
class HelperBase;
|
||||
class IDBCursor;
|
||||
class IDBDatabase;
|
||||
class IDBFactory;
|
||||
class IDBIndex;
|
||||
class IDBObjectStore;
|
||||
class IDBTransaction;
|
||||
class IndexedDBRequestParentBase;
|
||||
|
||||
class IDBRequest : public IDBWrapperCache
|
||||
class IDBRequest
|
||||
: public IDBWrapperCache
|
||||
{
|
||||
protected:
|
||||
// mSourceAsObjectStore and mSourceAsIndex are exclusive and one must always
|
||||
// be set. mSourceAsCursor is sometimes set also.
|
||||
nsRefPtr<IDBObjectStore> mSourceAsObjectStore;
|
||||
nsRefPtr<IDBIndex> mSourceAsIndex;
|
||||
nsRefPtr<IDBCursor> mSourceAsCursor;
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRThread* mOwningThread;
|
||||
#endif
|
||||
|
||||
JS::Heap<JS::Value> mResultVal;
|
||||
nsRefPtr<DOMError> mError;
|
||||
|
||||
nsString mFilename;
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t mSerialNumber;
|
||||
#endif
|
||||
nsresult mErrorCode;
|
||||
uint32_t mLineNo;
|
||||
bool mHaveResultOrErrorCode;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
|
||||
IDBWrapperCache)
|
||||
class ResultCallback;
|
||||
|
||||
static
|
||||
already_AddRefed<IDBRequest> Create(IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction);
|
||||
static already_AddRefed<IDBRequest>
|
||||
Create(IDBDatabase* aDatabase, IDBTransaction* aTransaction);
|
||||
|
||||
static
|
||||
already_AddRefed<IDBRequest> Create(IDBObjectStore* aSource,
|
||||
static already_AddRefed<IDBRequest>
|
||||
Create(IDBObjectStore* aSource,
|
||||
IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction);
|
||||
|
||||
static
|
||||
already_AddRefed<IDBRequest> Create(IDBIndex* aSource,
|
||||
static already_AddRefed<IDBRequest>
|
||||
Create(IDBIndex* aSource,
|
||||
IDBDatabase* aDatabase,
|
||||
IDBTransaction* aTransaction);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
|
||||
void GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
|
||||
void
|
||||
GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
|
||||
|
||||
void Reset();
|
||||
void
|
||||
Reset();
|
||||
|
||||
nsresult NotifyHelperCompleted(HelperBase* aHelper);
|
||||
void NotifyHelperSentResultsToChildProcess(nsresult aRv);
|
||||
void
|
||||
DispatchNonTransactionError(nsresult aErrorCode);
|
||||
|
||||
void SetError(nsresult aRv);
|
||||
void
|
||||
SetResultCallback(ResultCallback* aCallback);
|
||||
|
||||
void
|
||||
SetError(nsresult aRv);
|
||||
|
||||
nsresult
|
||||
GetErrorCode() const
|
||||
|
@ -84,25 +110,11 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
DOMError* GetError(ErrorResult& aRv);
|
||||
DOMError*
|
||||
GetError(ErrorResult& aRv);
|
||||
|
||||
void
|
||||
SetActor(IndexedDBRequestParentBase* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBRequestParentBase*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
void CaptureCaller();
|
||||
|
||||
void FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
|
||||
FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
|
||||
|
||||
bool
|
||||
IsPending() const
|
||||
|
@ -118,11 +130,6 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
|
@ -142,66 +149,87 @@ public:
|
|||
IDBTransaction*
|
||||
GetTransaction() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
IDBRequestReadyState
|
||||
ReadyState() const;
|
||||
|
||||
void
|
||||
SetSource(IDBCursor* aSource);
|
||||
|
||||
IMPL_EVENT_HANDLER(success);
|
||||
IMPL_EVENT_HANDLER(error);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
|
||||
IDBWrapperCache)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
explicit IDBRequest(IDBDatabase* aDatabase);
|
||||
explicit IDBRequest(nsPIDOMWindow* aOwner);
|
||||
~IDBRequest();
|
||||
|
||||
// At most one of these three fields can be non-null.
|
||||
nsRefPtr<IDBObjectStore> mSourceAsObjectStore;
|
||||
nsRefPtr<IDBIndex> mSourceAsIndex;
|
||||
nsRefPtr<IDBCursor> mSourceAsCursor;
|
||||
void
|
||||
InitMembers();
|
||||
|
||||
// Check that the above condition holds.
|
||||
#ifdef DEBUG
|
||||
void AssertSourceIsCorrect() const;
|
||||
#else
|
||||
void AssertSourceIsCorrect() const {}
|
||||
#endif
|
||||
void
|
||||
ConstructResult();
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
JS::Heap<JS::Value> mResultVal;
|
||||
nsRefPtr<mozilla::dom::DOMError> mError;
|
||||
IndexedDBRequestParentBase* mActorParent;
|
||||
nsString mFilename;
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t mSerialNumber;
|
||||
#endif
|
||||
nsresult mErrorCode;
|
||||
uint32_t mLineNo;
|
||||
bool mHaveResultOrErrorCode;
|
||||
void
|
||||
CaptureCaller();
|
||||
};
|
||||
|
||||
class IDBOpenDBRequest : public IDBRequest
|
||||
class NS_NO_VTABLE IDBRequest::ResultCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
|
||||
virtual nsresult
|
||||
GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) = 0;
|
||||
|
||||
static
|
||||
already_AddRefed<IDBOpenDBRequest>
|
||||
Create(IDBFactory* aFactory,
|
||||
protected:
|
||||
ResultCallback()
|
||||
{ }
|
||||
};
|
||||
|
||||
class IDBOpenDBRequest MOZ_FINAL
|
||||
: public IDBRequest
|
||||
{
|
||||
// Only touched on the owning thread.
|
||||
nsRefPtr<IDBFactory> mFactory;
|
||||
|
||||
public:
|
||||
static already_AddRefed<IDBOpenDBRequest>
|
||||
CreateForWindow(IDBFactory* aFactory,
|
||||
nsPIDOMWindow* aOwner,
|
||||
JS::Handle<JSObject*> aScriptOwner);
|
||||
|
||||
void SetTransaction(IDBTransaction* aTransaction);
|
||||
static already_AddRefed<IDBOpenDBRequest>
|
||||
CreateForJS(IDBFactory* aFactory,
|
||||
JS::Handle<JSObject*> aScriptOwner);
|
||||
|
||||
void
|
||||
SetTransaction(IDBTransaction* aTransaction);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PostHandleEvent(
|
||||
EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
PostHandleEvent(EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
|
||||
DOMError* GetError(ErrorResult& aRv)
|
||||
DOMError*
|
||||
GetError(ErrorResult& aRv)
|
||||
{
|
||||
return IDBRequest::GetError(aRv);
|
||||
}
|
||||
|
@ -212,22 +240,24 @@ public:
|
|||
return mFactory;
|
||||
}
|
||||
|
||||
IMPL_EVENT_HANDLER(blocked);
|
||||
IMPL_EVENT_HANDLER(upgradeneeded);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
IMPL_EVENT_HANDLER(blocked);
|
||||
IMPL_EVENT_HANDLER(upgradeneeded);
|
||||
private:
|
||||
IDBOpenDBRequest(IDBFactory* aFactory, nsPIDOMWindow* aOwner);
|
||||
|
||||
protected:
|
||||
explicit IDBOpenDBRequest(nsPIDOMWindow* aOwner);
|
||||
~IDBOpenDBRequest();
|
||||
|
||||
// Only touched on the main thread.
|
||||
nsRefPtr<IDBFactory> mFactory;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbrequest_h__
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,71 +8,48 @@
|
|||
#define mozilla_dom_indexeddb_idbtransaction_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStorageFunction.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "mozilla/dom/IDBTransactionBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
#include "mozilla/dom/indexedDB/FileInfo.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIThread;
|
||||
class nsIDOMBlob;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class EventChainPreVisitor;
|
||||
} // namespace mozilla
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace dom {
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class CommitHelper;
|
||||
class DOMError;
|
||||
class DOMStringList;
|
||||
class PBlobChild;
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class BackgroundCursorChild;
|
||||
class BackgroundRequestChild;
|
||||
class BackgroundTransactionChild;
|
||||
class BackgroundVersionChangeTransactionChild;
|
||||
class IDBDatabase;
|
||||
class IDBObjectStore;
|
||||
class IDBRequest;
|
||||
class IndexedDBDatabaseChild;
|
||||
class IndexedDBTransactionChild;
|
||||
class IndexedDBTransactionParent;
|
||||
struct ObjectStoreInfo;
|
||||
class TransactionThreadPool;
|
||||
class UpdateRefcountFunction;
|
||||
class IndexMetadata;
|
||||
class ObjectStoreSpec;
|
||||
class OpenCursorParams;
|
||||
class PBackgroundIDBDatabaseFileChild;
|
||||
class RequestParams;
|
||||
|
||||
class IDBTransactionListener
|
||||
class IDBTransaction MOZ_FINAL
|
||||
: public IDBWrapperCache
|
||||
, public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0;
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release() = 0;
|
||||
|
||||
// Called just before dispatching the final events on the transaction.
|
||||
virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction) = 0;
|
||||
// Called just after dispatching the final events on the transaction.
|
||||
virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction) = 0;
|
||||
};
|
||||
|
||||
class IDBTransaction : public IDBWrapperCache,
|
||||
public nsIRunnable
|
||||
{
|
||||
friend class AsyncConnectionHelper;
|
||||
friend class CommitHelper;
|
||||
friend class IndexedDBDatabaseChild;
|
||||
friend class ThreadObserver;
|
||||
friend class TransactionThreadPool;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
|
||||
|
||||
enum Mode
|
||||
{
|
||||
READ_ONLY = 0,
|
||||
|
@ -91,156 +68,184 @@ public:
|
|||
DONE
|
||||
};
|
||||
|
||||
private:
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<DOMError> mError;
|
||||
nsTArray<nsString> mObjectStoreNames;
|
||||
nsTArray<nsRefPtr<IDBObjectStore>> mObjectStores;
|
||||
nsTArray<nsRefPtr<IDBObjectStore>> mDeletedObjectStores;
|
||||
|
||||
// Tagged with mMode. If mMode is VERSION_CHANGE then mBackgroundActor will be
|
||||
// a BackgroundVersionChangeTransactionChild. Otherwise it will be a
|
||||
// BackgroundTransactionChild.
|
||||
union {
|
||||
BackgroundTransactionChild* mNormalBackgroundActor;
|
||||
BackgroundVersionChangeTransactionChild* mVersionChangeBackgroundActor;
|
||||
} mBackgroundActor;
|
||||
|
||||
|
||||
// Only used for VERSION_CHANGE transactions.
|
||||
int64_t mNextObjectStoreId;
|
||||
int64_t mNextIndexId;
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t mSerialNumber;
|
||||
#endif
|
||||
|
||||
nsresult mAbortCode;
|
||||
uint32_t mPendingRequestCount;
|
||||
|
||||
ReadyState mReadyState;
|
||||
Mode mMode;
|
||||
|
||||
bool mCreating;
|
||||
bool mAbortedByScript;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mSentCommitOrAbort;
|
||||
bool mFiredCompleteOrAbort;
|
||||
#endif
|
||||
|
||||
public:
|
||||
static already_AddRefed<IDBTransaction>
|
||||
CreateVersionChange(IDBDatabase* aDatabase,
|
||||
BackgroundVersionChangeTransactionChild* aActor,
|
||||
int64_t aNextObjectStoreId,
|
||||
int64_t aNextIndexId);
|
||||
|
||||
static already_AddRefed<IDBTransaction>
|
||||
Create(IDBDatabase* aDatabase,
|
||||
const Sequence<nsString>& aObjectStoreNames,
|
||||
Mode aMode,
|
||||
bool aDispatchDelayed)
|
||||
const nsTArray<nsString>& aObjectStoreNames,
|
||||
Mode aMode);
|
||||
|
||||
static IDBTransaction*
|
||||
GetCurrent();
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void
|
||||
SetBackgroundActor(BackgroundTransactionChild* aBackgroundActor);
|
||||
|
||||
void
|
||||
ClearBackgroundActor()
|
||||
{
|
||||
return CreateInternal(aDatabase, aObjectStoreNames, aMode, aDispatchDelayed,
|
||||
false);
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mMode == VERSION_CHANGE) {
|
||||
mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
|
||||
} else {
|
||||
mBackgroundActor.mNormalBackgroundActor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
void
|
||||
StartRequest(BackgroundRequestChild* aBackgroundActor,
|
||||
const RequestParams& aParams);
|
||||
|
||||
void OnNewRequest();
|
||||
void OnRequestFinished();
|
||||
void OnRequestDisconnected();
|
||||
void
|
||||
OpenCursor(BackgroundCursorChild* aBackgroundActor,
|
||||
const OpenCursorParams& aParams);
|
||||
|
||||
void RemoveObjectStore(const nsAString& aName);
|
||||
void
|
||||
RefreshSpec(bool aMayDelete);
|
||||
|
||||
void SetTransactionListener(IDBTransactionListener* aListener);
|
||||
void
|
||||
OnNewRequest();
|
||||
|
||||
bool StartSavepoint();
|
||||
nsresult ReleaseSavepoint();
|
||||
void RollbackSavepoint();
|
||||
void
|
||||
OnRequestFinished();
|
||||
|
||||
// Only meant to be called on mStorageThread!
|
||||
nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
|
||||
bool
|
||||
IsOpen() const;
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetCachedStatement(const nsACString& aQuery);
|
||||
|
||||
template<int N>
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetCachedStatement(const char (&aQuery)[N])
|
||||
{
|
||||
return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
|
||||
}
|
||||
|
||||
bool IsOpen() const;
|
||||
|
||||
bool IsFinished() const
|
||||
bool
|
||||
IsFinished() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mReadyState > LOADING;
|
||||
}
|
||||
|
||||
bool IsWriteAllowed() const
|
||||
bool
|
||||
IsWriteAllowed() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mMode == READ_WRITE || mMode == VERSION_CHANGE;
|
||||
}
|
||||
|
||||
bool IsAborted() const
|
||||
bool
|
||||
IsAborted() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return NS_FAILED(mAbortCode);
|
||||
}
|
||||
|
||||
// 'Get' prefix is to avoid name collisions with the enum
|
||||
Mode GetMode()
|
||||
Mode
|
||||
GetMode() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mMode;
|
||||
}
|
||||
|
||||
IDBDatabase* Database()
|
||||
IDBDatabase*
|
||||
Database() const
|
||||
{
|
||||
NS_ASSERTION(mDatabase, "This should never be null!");
|
||||
AssertIsOnOwningThread();
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
DatabaseInfo* DBInfo() const
|
||||
{
|
||||
return mDatabaseInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
GetOrCreateObjectStore(const nsAString& aName,
|
||||
ObjectStoreInfo* aObjectStoreInfo,
|
||||
bool aCreating);
|
||||
|
||||
already_AddRefed<FileInfo> GetFileInfo(nsIDOMBlob* aBlob);
|
||||
void AddFileInfo(nsIDOMBlob* aBlob, FileInfo* aFileInfo);
|
||||
|
||||
void ClearCreatedFileInfos();
|
||||
|
||||
void
|
||||
SetActor(IndexedDBTransactionChild* aActorChild)
|
||||
{
|
||||
NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
|
||||
mActorChild = aActorChild;
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(IndexedDBTransactionParent* aActorParent)
|
||||
{
|
||||
NS_ASSERTION(!aActorParent || !mActorParent,
|
||||
"Shouldn't have more than one!");
|
||||
mActorParent = aActorParent;
|
||||
}
|
||||
|
||||
IndexedDBTransactionChild*
|
||||
GetActorChild() const
|
||||
{
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
IndexedDBTransactionParent*
|
||||
GetActorParent() const
|
||||
{
|
||||
return mActorParent;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Abort(IDBRequest* aRequest);
|
||||
|
||||
nsresult
|
||||
Abort(nsresult aAbortCode);
|
||||
|
||||
nsresult
|
||||
GetAbortCode() const
|
||||
{
|
||||
return mAbortCode;
|
||||
}
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t
|
||||
GetSerialNumber() const
|
||||
{
|
||||
return mSerialNumber;
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
IDBTransactionMode
|
||||
GetMode(ErrorResult& aRv) const;
|
||||
|
||||
IDBDatabase*
|
||||
Db() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mDatabase;
|
||||
return Database();
|
||||
}
|
||||
|
||||
const nsTArray<nsString>&
|
||||
ObjectStoreNamesInternal() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mObjectStoreNames;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
CreateObjectStore(const ObjectStoreSpec& aSpec);
|
||||
|
||||
void
|
||||
DeleteObjectStore(int64_t aObjectStoreId);
|
||||
|
||||
void
|
||||
CreateIndex(IDBObjectStore* aObjectStore, const IndexMetadata& aMetadata);
|
||||
|
||||
void
|
||||
DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId);
|
||||
|
||||
void
|
||||
Abort(IDBRequest* aRequest);
|
||||
|
||||
void
|
||||
Abort(nsresult aAbortCode);
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint32_t
|
||||
GetSerialNumber() const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return mSerialNumber;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const;
|
||||
|
||||
IDBTransactionMode
|
||||
GetMode(ErrorResult& aRv) const;
|
||||
|
||||
DOMError*
|
||||
GetError() const;
|
||||
|
||||
|
@ -248,255 +253,56 @@ public:
|
|||
ObjectStore(const nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Abort(ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
aRv = AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
|
||||
}
|
||||
Abort(ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(abort)
|
||||
IMPL_EVENT_HANDLER(complete)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
|
||||
already_AddRefed<DOMStringList>
|
||||
GetObjectStoreNames(ErrorResult& aRv);
|
||||
ObjectStoreNames();
|
||||
|
||||
void
|
||||
FireCompleteOrAbortEvents(nsresult aResult);
|
||||
|
||||
// Only for VERSION_CHANGE transactions.
|
||||
int64_t
|
||||
NextObjectStoreId();
|
||||
|
||||
// Only for VERSION_CHANGE transactions.
|
||||
int64_t
|
||||
NextIndexId();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
|
||||
|
||||
// nsWrapperCache
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult
|
||||
PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsresult
|
||||
AbortInternal(nsresult aAbortCode,
|
||||
already_AddRefed<mozilla::dom::DOMError> aError);
|
||||
|
||||
// Should only be called directly through IndexedDBDatabaseChild.
|
||||
static already_AddRefed<IDBTransaction>
|
||||
CreateInternal(IDBDatabase* aDatabase,
|
||||
const Sequence<nsString>& aObjectStoreNames,
|
||||
Mode aMode,
|
||||
bool aDispatchDelayed,
|
||||
bool aIsVersionChangeTransactionChild);
|
||||
|
||||
explicit IDBTransaction(IDBDatabase* aDatabase);
|
||||
IDBTransaction(IDBDatabase* aDatabase,
|
||||
const nsTArray<nsString>& aObjectStoreNames,
|
||||
Mode aMode);
|
||||
~IDBTransaction();
|
||||
|
||||
nsresult CommitOrRollback();
|
||||
void
|
||||
AbortInternal(nsresult aAbortCode, already_AddRefed<DOMError> aError);
|
||||
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<DatabaseInfo> mDatabaseInfo;
|
||||
nsRefPtr<DOMError> mError;
|
||||
nsTArray<nsString> mObjectStoreNames;
|
||||
ReadyState mReadyState;
|
||||
Mode mMode;
|
||||
uint32_t mPendingRequests;
|
||||
void
|
||||
SendCommit();
|
||||
|
||||
nsInterfaceHashtable<nsCStringHashKey, mozIStorageStatement>
|
||||
mCachedStatements;
|
||||
|
||||
nsRefPtr<IDBTransactionListener> mListener;
|
||||
|
||||
// Only touched on the database thread.
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
|
||||
// Only touched on the database thread.
|
||||
uint32_t mSavepointCount;
|
||||
|
||||
nsTArray<nsRefPtr<IDBObjectStore> > mCreatedObjectStores;
|
||||
nsTArray<nsRefPtr<IDBObjectStore> > mDeletedObjectStores;
|
||||
|
||||
nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
|
||||
nsRefPtrHashtable<nsISupportsHashKey, FileInfo> mCreatedFileInfos;
|
||||
|
||||
IndexedDBTransactionChild* mActorChild;
|
||||
IndexedDBTransactionParent* mActorParent;
|
||||
|
||||
nsresult mAbortCode;
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
uint64_t mSerialNumber;
|
||||
#endif
|
||||
bool mCreating;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mFiredCompleteOrAbort;
|
||||
#endif
|
||||
void
|
||||
SendAbort(nsresult aResultCode);
|
||||
};
|
||||
|
||||
class CommitHelper MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CommitHelper(IDBTransaction* aTransaction,
|
||||
IDBTransactionListener* aListener,
|
||||
const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
|
||||
CommitHelper(IDBTransaction* aTransaction,
|
||||
nsresult aAbortCode);
|
||||
|
||||
template<class T>
|
||||
bool AddDoomedObject(nsCOMPtr<T>& aCOMPtr)
|
||||
{
|
||||
if (aCOMPtr) {
|
||||
if (!mDoomedObjects.AppendElement(do_QueryInterface(aCOMPtr))) {
|
||||
NS_ERROR("Out of memory!");
|
||||
return false;
|
||||
}
|
||||
aCOMPtr = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
~CommitHelper();
|
||||
|
||||
// Writes new autoincrement counts to database
|
||||
nsresult WriteAutoIncrementCounts();
|
||||
|
||||
// Updates counts after a successful commit
|
||||
void CommitAutoIncrementCounts();
|
||||
|
||||
// Reverts counts when a transaction is aborted
|
||||
void RevertAutoIncrementCounts();
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsRefPtr<IDBTransactionListener> mListener;
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
|
||||
nsAutoTArray<nsCOMPtr<nsISupports>, 10> mDoomedObjects;
|
||||
nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
|
||||
|
||||
nsresult mAbortCode;
|
||||
};
|
||||
|
||||
class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
|
||||
{
|
||||
~UpdateRefcountFunction()
|
||||
{ }
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGEFUNCTION
|
||||
|
||||
explicit UpdateRefcountFunction(FileManager* aFileManager)
|
||||
: mFileManager(aFileManager), mInSavepoint(false)
|
||||
{ }
|
||||
|
||||
void StartSavepoint()
|
||||
{
|
||||
MOZ_ASSERT(!mInSavepoint);
|
||||
MOZ_ASSERT(!mSavepointEntriesIndex.Count());
|
||||
|
||||
mInSavepoint = true;
|
||||
}
|
||||
|
||||
void ReleaseSavepoint()
|
||||
{
|
||||
MOZ_ASSERT(mInSavepoint);
|
||||
|
||||
mSavepointEntriesIndex.Clear();
|
||||
|
||||
mInSavepoint = false;
|
||||
}
|
||||
|
||||
void RollbackSavepoint()
|
||||
{
|
||||
MOZ_ASSERT(mInSavepoint);
|
||||
|
||||
mInSavepoint = false;
|
||||
|
||||
mSavepointEntriesIndex.EnumerateRead(RollbackSavepointCallback, nullptr);
|
||||
|
||||
mSavepointEntriesIndex.Clear();
|
||||
}
|
||||
|
||||
void ClearFileInfoEntries()
|
||||
{
|
||||
mFileInfoEntries.Clear();
|
||||
}
|
||||
|
||||
nsresult WillCommit(mozIStorageConnection* aConnection);
|
||||
void DidCommit();
|
||||
void DidAbort();
|
||||
|
||||
private:
|
||||
class FileInfoEntry
|
||||
{
|
||||
public:
|
||||
explicit FileInfoEntry(FileInfo* aFileInfo)
|
||||
: mFileInfo(aFileInfo), mDelta(0), mSavepointDelta(0)
|
||||
{ }
|
||||
|
||||
~FileInfoEntry()
|
||||
{ }
|
||||
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
int32_t mDelta;
|
||||
int32_t mSavepointDelta;
|
||||
};
|
||||
|
||||
enum UpdateType {
|
||||
eIncrement,
|
||||
eDecrement
|
||||
};
|
||||
|
||||
class DatabaseUpdateFunction
|
||||
{
|
||||
public:
|
||||
DatabaseUpdateFunction(mozIStorageConnection* aConnection,
|
||||
UpdateRefcountFunction* aFunction)
|
||||
: mConnection(aConnection), mFunction(aFunction), mErrorCode(NS_OK)
|
||||
{ }
|
||||
|
||||
bool Update(int64_t aId, int32_t aDelta);
|
||||
nsresult ErrorCode()
|
||||
{
|
||||
return mErrorCode;
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult UpdateInternal(int64_t aId, int32_t aDelta);
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
nsCOMPtr<mozIStorageStatement> mUpdateStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mSelectStatement;
|
||||
nsCOMPtr<mozIStorageStatement> mInsertStatement;
|
||||
|
||||
UpdateRefcountFunction* mFunction;
|
||||
|
||||
nsresult mErrorCode;
|
||||
};
|
||||
|
||||
nsresult ProcessValue(mozIStorageValueArray* aValues,
|
||||
int32_t aIndex,
|
||||
UpdateType aUpdateType);
|
||||
|
||||
nsresult CreateJournals();
|
||||
|
||||
nsresult RemoveJournals(const nsTArray<int64_t>& aJournals);
|
||||
|
||||
static PLDHashOperator
|
||||
DatabaseUpdateCallback(const uint64_t& aKey,
|
||||
FileInfoEntry* aValue,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator
|
||||
FileInfoUpdateCallback(const uint64_t& aKey,
|
||||
FileInfoEntry* aValue,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator
|
||||
RollbackSavepointCallback(const uint64_t& aKey,
|
||||
FileInfoEntry* aValue,
|
||||
void* aUserArg);
|
||||
|
||||
FileManager* mFileManager;
|
||||
nsClassHashtable<nsUint64HashKey, FileInfoEntry> mFileInfoEntries;
|
||||
nsDataHashtable<nsUint64HashKey, FileInfoEntry*> mSavepointEntriesIndex;
|
||||
|
||||
nsTArray<int64_t> mJournalsToCreateBeforeCommit;
|
||||
nsTArray<int64_t> mJournalsToRemoveAfterCommit;
|
||||
nsTArray<int64_t> mJournalsToRemoveAfterAbort;
|
||||
|
||||
bool mInSavepoint;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbtransaction_h__
|
||||
|
|
|
@ -5,9 +5,19 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IDBWrapperCache.h"
|
||||
#include "nsCycleCollector.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsCycleCollector.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBWrapperCache)
|
||||
|
||||
|
@ -38,6 +48,14 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|||
NS_IMPL_ADDREF_INHERITED(IDBWrapperCache, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(IDBWrapperCache, DOMEventTargetHelper)
|
||||
|
||||
IDBWrapperCache::IDBWrapperCache(DOMEventTargetHelper* aOwner)
|
||||
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
|
||||
{ }
|
||||
|
||||
IDBWrapperCache::IDBWrapperCache(nsPIDOMWindow* aOwner)
|
||||
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
|
||||
{ }
|
||||
|
||||
IDBWrapperCache::~IDBWrapperCache()
|
||||
{
|
||||
mScriptOwner = nullptr;
|
||||
|
@ -48,7 +66,7 @@ IDBWrapperCache::~IDBWrapperCache()
|
|||
void
|
||||
IDBWrapperCache::SetScriptOwner(JSObject* aScriptOwner)
|
||||
{
|
||||
NS_ASSERTION(aScriptOwner, "This should never be null!");
|
||||
MOZ_ASSERT(aScriptOwner);
|
||||
|
||||
mScriptOwner = aScriptOwner;
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
@ -62,3 +80,7 @@ IDBWrapperCache::AssertIsRooted() const
|
|||
"Why aren't we rooted?!");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,47 +7,51 @@
|
|||
#ifndef mozilla_dom_indexeddb_idbwrappercache_h__
|
||||
#define mozilla_dom_indexeddb_idbwrappercache_h__
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class IDBWrapperCache : public DOMEventTargetHelper
|
||||
{
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
|
||||
IDBWrapperCache,
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBWrapperCache,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
JSObject* GetScriptOwner() const
|
||||
JSObject*
|
||||
GetScriptOwner() const
|
||||
{
|
||||
return mScriptOwner;
|
||||
}
|
||||
void SetScriptOwner(JSObject* aScriptOwner);
|
||||
|
||||
void
|
||||
SetScriptOwner(JSObject* aScriptOwner);
|
||||
|
||||
void AssertIsRooted() const
|
||||
#ifdef DEBUG
|
||||
void AssertIsRooted() const;
|
||||
;
|
||||
#else
|
||||
inline void AssertIsRooted() const
|
||||
{
|
||||
}
|
||||
{ }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
explicit IDBWrapperCache(DOMEventTargetHelper* aOwner)
|
||||
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
|
||||
{ }
|
||||
explicit IDBWrapperCache(nsPIDOMWindow* aOwner)
|
||||
: DOMEventTargetHelper(aOwner), mScriptOwner(nullptr)
|
||||
{ }
|
||||
explicit IDBWrapperCache(DOMEventTargetHelper* aOwner);
|
||||
explicit IDBWrapperCache(nsPIDOMWindow* aOwner);
|
||||
|
||||
virtual ~IDBWrapperCache();
|
||||
|
||||
private:
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_idbwrappercache_h__
|
||||
|
|
|
@ -9,148 +9,70 @@
|
|||
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
#define BEGIN_INDEXEDDB_NAMESPACE \
|
||||
namespace mozilla { namespace dom { namespace indexedDB {
|
||||
|
||||
#define END_INDEXEDDB_NAMESPACE \
|
||||
} /* namespace indexedDB */ } /* namepsace dom */ } /* namespace mozilla */
|
||||
|
||||
#define USING_INDEXEDDB_NAMESPACE \
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIInputStream;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class FileInfo;
|
||||
class IDBDatabase;
|
||||
class IDBTransaction;
|
||||
class SerializedStructuredCloneReadInfo;
|
||||
class SerializedStructuredCloneWriteInfo;
|
||||
|
||||
struct StructuredCloneFile
|
||||
{
|
||||
bool operator==(const StructuredCloneFile& aOther) const
|
||||
{
|
||||
return this->mFile == aOther.mFile &&
|
||||
this->mFileInfo == aOther.mFileInfo &&
|
||||
this->mInputStream == aOther.mInputStream;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> mFile;
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneReadInfo;
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline
|
||||
StructuredCloneFile();
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline
|
||||
~StructuredCloneFile();
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline bool
|
||||
operator==(const StructuredCloneFile& aOther) const;
|
||||
};
|
||||
|
||||
struct StructuredCloneReadInfo
|
||||
{
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline StructuredCloneReadInfo();
|
||||
|
||||
inline StructuredCloneReadInfo&
|
||||
operator=(StructuredCloneReadInfo&& aCloneReadInfo);
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline bool
|
||||
SetFromSerialized(const SerializedStructuredCloneReadInfo& aOther);
|
||||
|
||||
JSAutoStructuredCloneBuffer mCloneBuffer;
|
||||
nsTArray<uint8_t> mData;
|
||||
nsTArray<StructuredCloneFile> mFiles;
|
||||
IDBDatabase* mDatabase;
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneReadInfo
|
||||
{
|
||||
SerializedStructuredCloneReadInfo()
|
||||
: data(nullptr), dataLength(0)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const SerializedStructuredCloneReadInfo& aOther) const
|
||||
{
|
||||
return this->data == aOther.data &&
|
||||
this->dataLength == aOther.dataLength;
|
||||
}
|
||||
|
||||
SerializedStructuredCloneReadInfo&
|
||||
operator=(const StructuredCloneReadInfo& aOther)
|
||||
{
|
||||
data = aOther.mCloneBuffer.data();
|
||||
dataLength = aOther.mCloneBuffer.nbytes();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
uint64_t* data;
|
||||
size_t dataLength;
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneWriteInfo;
|
||||
|
||||
struct StructuredCloneWriteInfo
|
||||
{
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline StructuredCloneWriteInfo();
|
||||
inline StructuredCloneWriteInfo(StructuredCloneWriteInfo&& aCloneWriteInfo);
|
||||
|
||||
bool operator==(const StructuredCloneWriteInfo& aOther) const
|
||||
{
|
||||
return this->mCloneBuffer.nbytes() == aOther.mCloneBuffer.nbytes() &&
|
||||
this->mCloneBuffer.data() == aOther.mCloneBuffer.data() &&
|
||||
this->mFiles == aOther.mFiles &&
|
||||
this->mTransaction == aOther.mTransaction &&
|
||||
this->mOffsetToKeyProp == aOther.mOffsetToKeyProp;
|
||||
}
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline bool
|
||||
SetFromSerialized(const SerializedStructuredCloneWriteInfo& aOther);
|
||||
|
||||
// XXX Remove!
|
||||
JSAutoStructuredCloneBuffer mCloneBuffer;
|
||||
nsTArray<StructuredCloneFile> mFiles;
|
||||
IDBTransaction* mTransaction;
|
||||
uint64_t mOffsetToKeyProp;
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline
|
||||
StructuredCloneReadInfo();
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline
|
||||
~StructuredCloneReadInfo();
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline StructuredCloneReadInfo&
|
||||
operator=(StructuredCloneReadInfo&& aOther);
|
||||
|
||||
// In IndexedDatabaseInlines.h
|
||||
inline
|
||||
StructuredCloneReadInfo(SerializedStructuredCloneReadInfo&& aOther);
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneWriteInfo
|
||||
{
|
||||
SerializedStructuredCloneWriteInfo()
|
||||
: data(nullptr), dataLength(0), offsetToKeyProp(0)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const SerializedStructuredCloneWriteInfo& aOther) const
|
||||
{
|
||||
return this->data == aOther.data &&
|
||||
this->dataLength == aOther.dataLength &&
|
||||
this->offsetToKeyProp == aOther.offsetToKeyProp;
|
||||
}
|
||||
|
||||
SerializedStructuredCloneWriteInfo&
|
||||
operator=(const StructuredCloneWriteInfo& aOther)
|
||||
{
|
||||
data = aOther.mCloneBuffer.data();
|
||||
dataLength = aOther.mCloneBuffer.nbytes();
|
||||
offsetToKeyProp = aOther.mOffsetToKeyProp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||
uint64_t* data;
|
||||
size_t dataLength;
|
||||
uint64_t offsetToKeyProp;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_indexeddb_indexeddatabase_h__
|
||||
|
|
|
@ -11,48 +11,55 @@
|
|||
#error Must include IndexedDatabase.h first
|
||||
#endif
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
#include "FileInfo.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
inline
|
||||
StructuredCloneWriteInfo::StructuredCloneWriteInfo()
|
||||
: mTransaction(nullptr),
|
||||
mOffsetToKeyProp(0)
|
||||
StructuredCloneFile::StructuredCloneFile()
|
||||
{
|
||||
MOZ_COUNT_CTOR(StructuredCloneFile);
|
||||
}
|
||||
|
||||
inline
|
||||
StructuredCloneWriteInfo::StructuredCloneWriteInfo(
|
||||
StructuredCloneWriteInfo&& aCloneWriteInfo)
|
||||
: mCloneBuffer(Move(aCloneWriteInfo.mCloneBuffer))
|
||||
, mTransaction(aCloneWriteInfo.mTransaction)
|
||||
, mOffsetToKeyProp(aCloneWriteInfo.mOffsetToKeyProp)
|
||||
StructuredCloneFile::~StructuredCloneFile()
|
||||
{
|
||||
mFiles.SwapElements(aCloneWriteInfo.mFiles);
|
||||
aCloneWriteInfo.mTransaction = nullptr;
|
||||
aCloneWriteInfo.mOffsetToKeyProp = 0;
|
||||
MOZ_COUNT_DTOR(StructuredCloneFile);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
StructuredCloneWriteInfo::SetFromSerialized(
|
||||
const SerializedStructuredCloneWriteInfo& aOther)
|
||||
StructuredCloneFile::operator==(const StructuredCloneFile& aOther) const
|
||||
{
|
||||
if (!aOther.dataLength) {
|
||||
mCloneBuffer.clear();
|
||||
}
|
||||
else if (!mCloneBuffer.copy(aOther.data, aOther.dataLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mFiles.Clear();
|
||||
mOffsetToKeyProp = aOther.offsetToKeyProp;
|
||||
return true;
|
||||
return this->mFile == aOther.mFile &&
|
||||
this->mFileInfo == aOther.mFileInfo;
|
||||
}
|
||||
|
||||
inline
|
||||
StructuredCloneReadInfo::StructuredCloneReadInfo()
|
||||
: mDatabase(nullptr)
|
||||
: mDatabase(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
|
||||
}
|
||||
|
||||
inline
|
||||
StructuredCloneReadInfo::StructuredCloneReadInfo(
|
||||
SerializedStructuredCloneReadInfo&& aCloneReadInfo)
|
||||
: mData(Move(aCloneReadInfo.data()))
|
||||
, mDatabase(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
|
||||
}
|
||||
|
||||
inline
|
||||
StructuredCloneReadInfo::~StructuredCloneReadInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(StructuredCloneReadInfo);
|
||||
}
|
||||
|
||||
inline StructuredCloneReadInfo&
|
||||
|
@ -60,6 +67,7 @@ StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
|
|||
{
|
||||
MOZ_ASSERT(&aCloneReadInfo != this);
|
||||
|
||||
mData = Move(aCloneReadInfo.mData);
|
||||
mCloneBuffer = Move(aCloneReadInfo.mCloneBuffer);
|
||||
mFiles.Clear();
|
||||
mFiles.SwapElements(aCloneReadInfo.mFiles);
|
||||
|
@ -68,45 +76,8 @@ StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
StructuredCloneReadInfo::SetFromSerialized(
|
||||
const SerializedStructuredCloneReadInfo& aOther)
|
||||
{
|
||||
if (aOther.dataLength &&
|
||||
!mCloneBuffer.copy(aOther.data, aOther.dataLength)) {
|
||||
return false;
|
||||
}
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
mFiles.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
AppendConditionClause(const nsACString& aColumnName,
|
||||
const nsACString& aArgName,
|
||||
bool aLessThan,
|
||||
bool aEquals,
|
||||
nsACString& aResult)
|
||||
{
|
||||
aResult += NS_LITERAL_CSTRING(" AND ") + aColumnName +
|
||||
NS_LITERAL_CSTRING(" ");
|
||||
|
||||
if (aLessThan) {
|
||||
aResult.Append('<');
|
||||
}
|
||||
else {
|
||||
aResult.Append('>');
|
||||
}
|
||||
|
||||
if (aEquals) {
|
||||
aResult.Append('=');
|
||||
}
|
||||
|
||||
aResult += NS_LITERAL_CSTRING(" :") + aArgName;
|
||||
}
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif
|
||||
#endif // IndexedDatabaseInlines_h
|
||||
|
|
|
@ -16,12 +16,16 @@
|
|||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/CondVar.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
#include "mozilla/dom/PBlobChild.h"
|
||||
#include "mozilla/dom/quota/OriginOrPatternString.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/quota/Utilities.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/storage.h"
|
||||
|
@ -53,12 +57,11 @@
|
|||
#define LOW_DISK_SPACE_DATA_FULL "full"
|
||||
#define LOW_DISK_SPACE_DATA_FREE "free"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
USING_QUOTA_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::dom::quota;
|
||||
|
||||
class FileManagerInfo
|
||||
{
|
||||
|
@ -103,14 +106,15 @@ private:
|
|||
nsTArray<nsRefPtr<FileManager> > mTemporaryStorageFileManagers;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestingPref[] = "dom.indexedDB.testing";
|
||||
|
||||
mozilla::StaticRefPtr<IndexedDatabaseManager> gDBManager;
|
||||
|
||||
mozilla::Atomic<bool> gInitialized(false);
|
||||
mozilla::Atomic<bool> gClosed(false);
|
||||
mozilla::Atomic<bool> gTestingMode(false);
|
||||
|
||||
class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
|
@ -183,6 +187,16 @@ struct MOZ_STACK_CLASS InvalidateInfo
|
|||
const nsACString& pattern;
|
||||
};
|
||||
|
||||
void
|
||||
TestingPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!strcmp(aPrefName, kTestingPref));
|
||||
MOZ_ASSERT(!aClosure);
|
||||
|
||||
gTestingMode = Preferences::GetBool(aPrefName);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
IndexedDatabaseManager::IndexedDatabaseManager()
|
||||
|
@ -281,6 +295,9 @@ IndexedDatabaseManager::Init()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
Preferences::RegisterCallbackAndCall(TestingPrefChangedCallback,
|
||||
kTestingPref);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -293,6 +310,8 @@ IndexedDatabaseManager::Destroy()
|
|||
NS_ERROR("Shutdown more than once?!");
|
||||
}
|
||||
|
||||
Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
@ -314,7 +333,7 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
|
|||
nsresult rv = aVisitor.mDOMEvent->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!type.EqualsLiteral(ERROR_EVT_STR)) {
|
||||
if (nsDependentString(kErrorEventType) != type) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -425,7 +444,8 @@ IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
|
|||
}
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
if (NS_FAILED(IDBFactory::Create(aCx, aGlobal, nullptr,
|
||||
if (NS_FAILED(IDBFactory::CreateForChromeJS(aCx,
|
||||
aGlobal,
|
||||
getter_AddRefs(factory)))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -471,6 +491,16 @@ IndexedDatabaseManager::InLowDiskSpaceMode()
|
|||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::InTestingMode()
|
||||
{
|
||||
MOZ_ASSERT(gDBManager,
|
||||
"InTestingMode() called before indexedDB has been initialized!");
|
||||
|
||||
return gTestingMode;
|
||||
}
|
||||
|
||||
already_AddRefed<FileManager>
|
||||
IndexedDatabaseManager::GetFileManager(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
|
@ -626,13 +656,38 @@ IndexedDatabaseManager::BlockAndGetFileReferences(
|
|||
int32_t* aSliceRefCnt,
|
||||
bool* aResult)
|
||||
{
|
||||
if (NS_WARN_IF(!InTestingMode())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (IsMainProcess()) {
|
||||
nsRefPtr<GetFileReferencesHelper> helper =
|
||||
new GetFileReferencesHelper(aPersistenceType, aOrigin, aDatabaseName,
|
||||
aFileId);
|
||||
|
||||
nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
|
||||
nsresult rv =
|
||||
helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
|
||||
aSliceRefCnt, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
||||
if (NS_WARN_IF(!contentChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!contentChild->SendGetFileReferences(aPersistenceType,
|
||||
nsCString(aOrigin),
|
||||
nsString(aDatabaseName),
|
||||
aFileId,
|
||||
aRefCnt,
|
||||
aDBRefCnt,
|
||||
aSliceRefCnt,
|
||||
aResult)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -886,3 +941,7 @@ GetFileReferencesHelper::Run()
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#ifndef mozilla_dom_indexeddb_indexeddatabasemanager_h__
|
||||
#define mozilla_dom_indexeddb_indexeddatabasemanager_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
|
@ -21,16 +19,20 @@
|
|||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
class EventChainPostVisitor;
|
||||
namespace dom {
|
||||
class TabContext;
|
||||
namespace quota {
|
||||
class OriginOrPatternString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
class EventChainPostVisitor;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class TabContext;
|
||||
|
||||
namespace quota {
|
||||
|
||||
class OriginOrPatternString;
|
||||
|
||||
} // namespace quota
|
||||
|
||||
namespace indexedDB {
|
||||
|
||||
class FileManager;
|
||||
class FileManagerInfo;
|
||||
|
@ -75,6 +77,9 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
InTestingMode();
|
||||
|
||||
already_AddRefed<FileManager>
|
||||
GetFileManager(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
|
@ -160,6 +165,8 @@ private:
|
|||
static mozilla::Atomic<bool> sLowDiskSpaceMode;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_indexeddb_indexeddatabasemanager_h__ */
|
||||
#endif // mozilla_dom_indexeddb_indexeddatabasemanager_h__
|
||||
|
|
|
@ -4,19 +4,23 @@
|
|||
* 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/FloatingPoint.h"
|
||||
|
||||
#include "Key.h"
|
||||
#include "ReportInternalError.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "js/Value.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "ReportInternalError.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include <algorithm>
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
/*
|
||||
Here's how we encode keys:
|
||||
|
@ -262,6 +266,14 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
|||
#define TWO_BYTE_ADJUST (-0x7F)
|
||||
#define THREE_BYTE_SHIFT 6
|
||||
|
||||
nsresult
|
||||
Key::EncodeJSVal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal,
|
||||
uint8_t aTypeOffset)
|
||||
{
|
||||
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Key::EncodeString(const nsAString& aString, uint8_t aTypeOffset)
|
||||
{
|
||||
|
@ -314,6 +326,17 @@ Key::EncodeString(const nsAString& aString, uint8_t aTypeOffset)
|
|||
NS_ASSERTION(buffer == mBuffer.EndReading(), "Wrote wrong number of bytes");
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
Key::DecodeJSVal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd,
|
||||
JSContext* aCx,
|
||||
uint8_t aTypeOffset,
|
||||
JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
Key::DecodeString(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
|
@ -428,3 +451,108 @@ Key::DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd)
|
|||
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::BindToStatement(mozIStorageStatement* aStatement,
|
||||
const nsACString& aParamName) const
|
||||
{
|
||||
nsresult rv = aStatement->BindBlobByName(aParamName,
|
||||
reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
|
||||
|
||||
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::SetFromStatement(mozIStorageStatement* aStatement,
|
||||
uint32_t aIndex)
|
||||
{
|
||||
uint8_t* data;
|
||||
uint32_t dataLength = 0;
|
||||
|
||||
nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
mBuffer.Adopt(
|
||||
reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::SetFromJSVal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal)
|
||||
{
|
||||
mBuffer.Truncate();
|
||||
|
||||
if (aVal.isNull() || aVal.isUndefined()) {
|
||||
Unset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = EncodeJSVal(aCx, aVal, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unset();
|
||||
return rv;
|
||||
}
|
||||
TrimBuffer();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::ToJSVal(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal) const
|
||||
{
|
||||
if (IsUnset()) {
|
||||
aVal.setUndefined();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const unsigned char* pos = BufferStart();
|
||||
nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pos >= BufferEnd());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::ToJSVal(JSContext* aCx,
|
||||
JS::Heap<JS::Value>& aVal) const
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aVal = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal)
|
||||
{
|
||||
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unset();
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
Key::Assert(bool aCondition) const
|
||||
{
|
||||
MOZ_ASSERT(aCondition);
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,84 +7,91 @@
|
|||
#ifndef mozilla_dom_indexeddb_key_h__
|
||||
#define mozilla_dom_indexeddb_key_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "mozIStorageStatement.h"
|
||||
|
||||
#include "js/Value.h"
|
||||
class mozIStorageStatement;
|
||||
|
||||
namespace IPC {
|
||||
template <typename T> struct ParamTraits;
|
||||
|
||||
template <typename> struct ParamTraits;
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class Key
|
||||
{
|
||||
friend struct IPC::ParamTraits<Key>;
|
||||
|
||||
nsCString mBuffer;
|
||||
|
||||
public:
|
||||
Key()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
Key& operator=(const nsAString& aString)
|
||||
Key&
|
||||
operator=(const nsAString& aString)
|
||||
{
|
||||
SetFromString(aString);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Key& operator=(int64_t aInt)
|
||||
Key&
|
||||
operator=(int64_t aInt)
|
||||
{
|
||||
SetFromInteger(aInt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Key& aOther) const
|
||||
bool
|
||||
operator==(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return mBuffer.Equals(aOther.mBuffer);
|
||||
}
|
||||
|
||||
bool operator!=(const Key& aOther) const
|
||||
bool
|
||||
operator!=(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return !mBuffer.Equals(aOther.mBuffer);
|
||||
}
|
||||
|
||||
bool operator<(const Key& aOther) const
|
||||
bool
|
||||
operator<(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return Compare(mBuffer, aOther.mBuffer) < 0;
|
||||
}
|
||||
|
||||
bool operator>(const Key& aOther) const
|
||||
bool
|
||||
operator>(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return Compare(mBuffer, aOther.mBuffer) > 0;
|
||||
}
|
||||
|
||||
bool operator<=(const Key& aOther) const
|
||||
bool
|
||||
operator<=(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return Compare(mBuffer, aOther.mBuffer) <= 0;
|
||||
}
|
||||
|
||||
bool operator>=(const Key& aOther) const
|
||||
bool
|
||||
operator>=(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
|
||||
"Don't compare unset keys!");
|
||||
Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
|
||||
|
||||
return Compare(mBuffer, aOther.mBuffer) >= 0;
|
||||
}
|
||||
|
@ -95,169 +102,114 @@ public:
|
|||
mBuffer.SetIsVoid(true);
|
||||
}
|
||||
|
||||
bool IsUnset() const
|
||||
bool
|
||||
IsUnset() const
|
||||
{
|
||||
return mBuffer.IsVoid();
|
||||
}
|
||||
|
||||
bool IsFloat() const
|
||||
bool
|
||||
IsFloat() const
|
||||
{
|
||||
return !IsUnset() && mBuffer.First() == eFloat;
|
||||
}
|
||||
|
||||
bool IsDate() const
|
||||
bool
|
||||
IsDate() const
|
||||
{
|
||||
return !IsUnset() && mBuffer.First() == eDate;
|
||||
}
|
||||
|
||||
bool IsString() const
|
||||
bool
|
||||
IsString() const
|
||||
{
|
||||
return !IsUnset() && mBuffer.First() == eString;
|
||||
}
|
||||
|
||||
bool IsArray() const
|
||||
bool
|
||||
IsArray() const
|
||||
{
|
||||
return !IsUnset() && mBuffer.First() >= eArray;
|
||||
}
|
||||
|
||||
double ToFloat() const
|
||||
double
|
||||
ToFloat() const
|
||||
{
|
||||
NS_ASSERTION(IsFloat(), "Why'd you call this?");
|
||||
Assert(IsFloat());
|
||||
const unsigned char* pos = BufferStart();
|
||||
double res = DecodeNumber(pos, BufferEnd());
|
||||
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
|
||||
Assert(pos >= BufferEnd());
|
||||
return res;
|
||||
}
|
||||
|
||||
double ToDateMsec() const
|
||||
double
|
||||
ToDateMsec() const
|
||||
{
|
||||
NS_ASSERTION(IsDate(), "Why'd you call this?");
|
||||
Assert(IsDate());
|
||||
const unsigned char* pos = BufferStart();
|
||||
double res = DecodeNumber(pos, BufferEnd());
|
||||
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
|
||||
Assert(pos >= BufferEnd());
|
||||
return res;
|
||||
}
|
||||
|
||||
void ToString(nsString& aString) const
|
||||
void
|
||||
ToString(nsString& aString) const
|
||||
{
|
||||
NS_ASSERTION(IsString(), "Why'd you call this?");
|
||||
Assert(IsString());
|
||||
const unsigned char* pos = BufferStart();
|
||||
DecodeString(pos, BufferEnd(), aString);
|
||||
NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
|
||||
Assert(pos >= BufferEnd());
|
||||
}
|
||||
|
||||
void SetFromString(const nsAString& aString)
|
||||
void
|
||||
SetFromString(const nsAString& aString)
|
||||
{
|
||||
mBuffer.Truncate();
|
||||
EncodeString(aString, 0);
|
||||
TrimBuffer();
|
||||
}
|
||||
|
||||
void SetFromInteger(int64_t aInt)
|
||||
void
|
||||
SetFromInteger(int64_t aInt)
|
||||
{
|
||||
mBuffer.Truncate();
|
||||
EncodeNumber(double(aInt), eFloat);
|
||||
TrimBuffer();
|
||||
}
|
||||
|
||||
nsresult SetFromJSVal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal)
|
||||
{
|
||||
mBuffer.Truncate();
|
||||
nsresult
|
||||
SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal);
|
||||
|
||||
if (aVal.isNull() || aVal.isUndefined()) {
|
||||
Unset();
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
|
||||
|
||||
nsresult rv = EncodeJSVal(aCx, aVal, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unset();
|
||||
return rv;
|
||||
}
|
||||
TrimBuffer();
|
||||
nsresult
|
||||
ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal) const
|
||||
{
|
||||
if (IsUnset()) {
|
||||
aVal.setUndefined();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const unsigned char* pos = BufferStart();
|
||||
nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(pos >= BufferEnd(),
|
||||
"Didn't consume whole buffer");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx,
|
||||
JS::Heap<JS::Value>& aVal) const
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aVal = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult AppendItem(JSContext* aCx,
|
||||
bool aFirstOfArray,
|
||||
JS::Handle<JS::Value> aVal)
|
||||
{
|
||||
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unset();
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void FinishArray()
|
||||
void
|
||||
FinishArray()
|
||||
{
|
||||
TrimBuffer();
|
||||
}
|
||||
|
||||
const nsCString& GetBuffer() const
|
||||
const nsCString&
|
||||
GetBuffer() const
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
nsresult BindToStatement(mozIStorageStatement* aStatement,
|
||||
const nsACString& aParamName) const
|
||||
{
|
||||
nsresult rv = aStatement->BindBlobByName(aParamName,
|
||||
reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
|
||||
nsresult
|
||||
BindToStatement(mozIStorageStatement* aStatement,
|
||||
const nsACString& aParamName) const;
|
||||
|
||||
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
nsresult
|
||||
SetFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex);
|
||||
|
||||
nsresult SetFromStatement(mozIStorageStatement* aStatement,
|
||||
uint32_t aIndex)
|
||||
{
|
||||
uint8_t* data;
|
||||
uint32_t dataLength = 0;
|
||||
|
||||
nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
mBuffer.Adopt(
|
||||
reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static
|
||||
int16_t CompareKeys(Key& aFirst, Key& aSecond)
|
||||
static int16_t
|
||||
CompareKeys(Key& aFirst, Key& aSecond)
|
||||
{
|
||||
int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
|
||||
|
||||
|
@ -273,12 +225,14 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
const unsigned char* BufferStart() const
|
||||
const unsigned char*
|
||||
BufferStart() const
|
||||
{
|
||||
return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
|
||||
}
|
||||
|
||||
const unsigned char* BufferEnd() const
|
||||
const unsigned char*
|
||||
BufferEnd() const
|
||||
{
|
||||
return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
|
||||
}
|
||||
|
@ -294,7 +248,8 @@ private:
|
|||
|
||||
// Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
|
||||
// step.
|
||||
void TrimBuffer()
|
||||
void
|
||||
TrimBuffer()
|
||||
{
|
||||
const char* end = mBuffer.EndReading() - 1;
|
||||
while (!*end) {
|
||||
|
@ -305,41 +260,57 @@ private:
|
|||
}
|
||||
|
||||
// Encoding functions. These append the encoded value to the end of mBuffer
|
||||
inline nsresult EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
||||
uint8_t aTypeOffset)
|
||||
{
|
||||
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
|
||||
}
|
||||
void EncodeString(const nsAString& aString, uint8_t aTypeOffset);
|
||||
void EncodeNumber(double aFloat, uint8_t aType);
|
||||
nsresult
|
||||
EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
|
||||
|
||||
void
|
||||
EncodeString(const nsAString& aString, uint8_t aTypeOffset);
|
||||
|
||||
void
|
||||
EncodeNumber(double aFloat, uint8_t aType);
|
||||
|
||||
// Decoding functions. aPos points into mBuffer and is adjusted to point
|
||||
// past the consumed value.
|
||||
static inline nsresult DecodeJSVal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd, JSContext* aCx,
|
||||
uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
|
||||
}
|
||||
static nsresult
|
||||
DecodeJSVal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd,
|
||||
JSContext* aCx,
|
||||
uint8_t aTypeOffset,
|
||||
JS::MutableHandle<JS::Value> aVal);
|
||||
|
||||
static void DecodeString(const unsigned char*& aPos,
|
||||
static void
|
||||
DecodeString(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd,
|
||||
nsString& aString);
|
||||
static double DecodeNumber(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd);
|
||||
|
||||
nsCString mBuffer;
|
||||
static double
|
||||
DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd);
|
||||
|
||||
private:
|
||||
nsresult EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
||||
uint8_t aTypeOffset, uint16_t aRecursionDepth);
|
||||
nsresult
|
||||
EncodeJSValInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aVal,
|
||||
uint8_t aTypeOffset,
|
||||
uint16_t aRecursionDepth);
|
||||
|
||||
static nsresult DecodeJSValInternal(const unsigned char*& aPos,
|
||||
static nsresult
|
||||
DecodeJSValInternal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd,
|
||||
JSContext* aCx, uint8_t aTypeOffset,
|
||||
JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
|
||||
JSContext* aCx,
|
||||
uint8_t aTypeOffset,
|
||||
JS::MutableHandle<JS::Value> aVal,
|
||||
uint16_t aRecursionDepth);
|
||||
|
||||
void
|
||||
Assert(bool aCondition) const
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_indexeddb_key_h__ */
|
||||
#endif // mozilla_dom_indexeddb_key_h__
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -178,8 +180,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
|
|||
obj = dummy;
|
||||
}
|
||||
else {
|
||||
JS::Rooted<JSObject*> dummy(aCx, JS_NewObject(aCx, &IDBObjectStore::sDummyPropJSClass,
|
||||
JS::NullPtr(), JS::NullPtr()));
|
||||
JS::Rooted<JSObject*> dummy(aCx,
|
||||
JS_NewObject(aCx, IDBObjectStore::DummyPropClass(), JS::NullPtr(),
|
||||
JS::NullPtr()));
|
||||
if (!dummy) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -569,3 +572,7 @@ KeyPath::IsAllowedForObjectStore(bool aAutoIncrement) const
|
|||
// Everything else is ok.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,16 +7,28 @@
|
|||
#ifndef mozilla_dom_indexeddb_keypath_h__
|
||||
#define mozilla_dom_indexeddb_keypath_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
class IndexMetadata;
|
||||
class Key;
|
||||
class ObjectStoreMetadata;
|
||||
|
||||
class KeyPath
|
||||
{
|
||||
// This private constructor is only to be used by IPDL-generated classes.
|
||||
friend class IndexMetadata;
|
||||
friend class ObjectStoreMetadata;
|
||||
|
||||
KeyPath()
|
||||
: mType(NONEXISTENT)
|
||||
{
|
||||
MOZ_COUNT_CTOR(KeyPath);
|
||||
}
|
||||
|
||||
public:
|
||||
enum KeyPathType {
|
||||
NONEXISTENT,
|
||||
|
@ -105,6 +117,8 @@ public:
|
|||
nsTArray<nsString> mStrings;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_indexeddb_keypath_h__ */
|
||||
#endif // mozilla_dom_indexeddb_keypath_h__
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,175 +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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_opendatabasehelper_h__
|
||||
#define mozilla_dom_indexeddb_opendatabasehelper_h__
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
|
||||
#include "DatabaseInfo.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBRequest.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class nsIContentParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class CheckPermissionsHelper;
|
||||
|
||||
class OpenDatabaseHelper : public HelperBase
|
||||
{
|
||||
friend class CheckPermissionsHelper;
|
||||
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
|
||||
~OpenDatabaseHelper() {}
|
||||
|
||||
public:
|
||||
OpenDatabaseHelper(IDBOpenDBRequest* aRequest,
|
||||
const nsAString& aName,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aASCIIOrigin,
|
||||
uint64_t aRequestedVersion,
|
||||
PersistenceType aPersistenceType,
|
||||
bool aForDeletion,
|
||||
mozilla::dom::nsIContentParent* aContentParent,
|
||||
StoragePrivilege aPrivilege)
|
||||
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
|
||||
mGroup(aGroup), mASCIIOrigin(aASCIIOrigin),
|
||||
mRequestedVersion(aRequestedVersion), mPersistenceType(aPersistenceType),
|
||||
mForDeletion(aForDeletion), mPrivilege(aPrivilege),
|
||||
mContentParent(aContentParent), mCurrentVersion(0), mLastObjectStoreId(0),
|
||||
mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
|
||||
mLoadDBMetadata(false),
|
||||
mTrackingQuota(aPrivilege != mozilla::dom::quota::Chrome)
|
||||
{
|
||||
NS_ASSERTION(!aForDeletion || !aRequestedVersion,
|
||||
"Can't be for deletion and request a version!");
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsresult WaitForOpenAllowed();
|
||||
nsresult Dispatch(nsIEventTarget* aDatabaseThread);
|
||||
nsresult DispatchToIOThread();
|
||||
nsresult RunImmediately();
|
||||
|
||||
void SetError(nsresult rv)
|
||||
{
|
||||
NS_ASSERTION(NS_FAILED(rv), "Why are you telling me?");
|
||||
mResultCode = rv;
|
||||
}
|
||||
|
||||
virtual nsresult GetResultCode() MOZ_OVERRIDE
|
||||
{
|
||||
return mResultCode;
|
||||
}
|
||||
|
||||
nsresult NotifySetVersionFinished();
|
||||
nsresult NotifyDeleteFinished();
|
||||
void BlockDatabase();
|
||||
|
||||
const nsACString& Id() const
|
||||
{
|
||||
return mDatabaseId;
|
||||
}
|
||||
|
||||
IDBDatabase* Database() const
|
||||
{
|
||||
NS_ASSERTION(mDatabase, "Calling at the wrong time!");
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
const StoragePrivilege& Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
|
||||
static
|
||||
nsresult CreateDatabaseConnection(nsIFile* aDBFile,
|
||||
nsIFile* aFMDirectory,
|
||||
const nsAString& aName,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
mozIStorageConnection** aConnection);
|
||||
|
||||
protected:
|
||||
// Methods only called on the main thread
|
||||
nsresult EnsureSuccessResult();
|
||||
nsresult StartSetVersion();
|
||||
nsresult StartDelete();
|
||||
virtual nsresult GetSuccessResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
|
||||
void DispatchSuccessEvent();
|
||||
void DispatchErrorEvent();
|
||||
virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
|
||||
|
||||
// Called by CheckPermissionsHelper on the main thread before dispatch.
|
||||
void SetUnlimitedQuotaAllowed()
|
||||
{
|
||||
mTrackingQuota = false;
|
||||
}
|
||||
|
||||
// Methods only called on the DB thread
|
||||
nsresult DoDatabaseWork();
|
||||
|
||||
// In-params.
|
||||
nsRefPtr<IDBOpenDBRequest> mOpenDBRequest;
|
||||
nsString mName;
|
||||
nsCString mGroup;
|
||||
nsCString mASCIIOrigin;
|
||||
uint64_t mRequestedVersion;
|
||||
PersistenceType mPersistenceType;
|
||||
bool mForDeletion;
|
||||
StoragePrivilege mPrivilege;
|
||||
nsCString mDatabaseId;
|
||||
mozilla::dom::nsIContentParent* mContentParent;
|
||||
|
||||
// Out-params.
|
||||
nsTArray<nsRefPtr<ObjectStoreInfo> > mObjectStores;
|
||||
uint64_t mCurrentVersion;
|
||||
nsString mDatabaseFilePath;
|
||||
int64_t mLastObjectStoreId;
|
||||
int64_t mLastIndexId;
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
|
||||
// State variables
|
||||
enum OpenDatabaseState {
|
||||
eCreated = 0, // Not yet dispatched to the DB thread
|
||||
eOpenPending, // Waiting for open allowed/open allowed
|
||||
eDBWork, // Waiting to do/doing work on the DB thread
|
||||
eFiringEvents, // Waiting to fire/firing events on the main thread
|
||||
eSetVersionPending, // Waiting on a SetVersionHelper
|
||||
eSetVersionCompleted, // SetVersionHelper is done
|
||||
eDeletePending, // Waiting on a DeleteDatabaseHelper
|
||||
eDeleteCompleted, // DeleteDatabaseHelper is done
|
||||
};
|
||||
OpenDatabaseState mState;
|
||||
nsresult mResultCode;
|
||||
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
|
||||
nsRefPtr<DatabaseInfo> mDBInfo;
|
||||
bool mLoadDBMetadata;
|
||||
bool mTrackingQuota;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_opendatabasehelper_h__
|
|
@ -0,0 +1,90 @@
|
|||
/* 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 protocol PBackgroundIDBTransaction;
|
||||
include protocol PBackgroundIDBVersionChangeTransaction;
|
||||
include protocol PBlob;
|
||||
|
||||
include PBackgroundIDBSharedTypes;
|
||||
|
||||
include "mozilla/dom/indexedDB/SerializationHelpers.h";
|
||||
|
||||
using struct mozilla::void_t
|
||||
from "ipc/IPCMessageUtils.h";
|
||||
|
||||
using class mozilla::dom::indexedDB::Key
|
||||
from "mozilla/dom/indexedDB/Key.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
struct ContinueParams
|
||||
{
|
||||
Key key;
|
||||
};
|
||||
|
||||
struct AdvanceParams
|
||||
{
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
union CursorRequestParams
|
||||
{
|
||||
ContinueParams;
|
||||
AdvanceParams;
|
||||
};
|
||||
|
||||
struct ObjectStoreCursorResponse
|
||||
{
|
||||
Key key;
|
||||
SerializedStructuredCloneReadInfo cloneInfo;
|
||||
};
|
||||
|
||||
struct ObjectStoreKeyCursorResponse
|
||||
{
|
||||
Key key;
|
||||
};
|
||||
|
||||
struct IndexCursorResponse
|
||||
{
|
||||
Key key;
|
||||
Key objectKey;
|
||||
SerializedStructuredCloneReadInfo cloneInfo;
|
||||
};
|
||||
|
||||
struct IndexKeyCursorResponse
|
||||
{
|
||||
Key key;
|
||||
Key objectKey;
|
||||
};
|
||||
|
||||
union CursorResponse
|
||||
{
|
||||
void_t;
|
||||
nsresult;
|
||||
ObjectStoreCursorResponse;
|
||||
ObjectStoreKeyCursorResponse;
|
||||
IndexCursorResponse;
|
||||
IndexKeyCursorResponse;
|
||||
};
|
||||
|
||||
protocol PBackgroundIDBCursor
|
||||
{
|
||||
manager PBackgroundIDBTransaction or PBackgroundIDBVersionChangeTransaction;
|
||||
|
||||
parent:
|
||||
DeleteMe();
|
||||
|
||||
Continue(CursorRequestParams params);
|
||||
|
||||
child:
|
||||
__delete__();
|
||||
|
||||
Response(CursorResponse response);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,72 @@
|
|||
/* 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 protocol PBackgroundIDBDatabaseFile;
|
||||
include protocol PBackgroundIDBFactory;
|
||||
include protocol PBackgroundIDBTransaction;
|
||||
include protocol PBackgroundIDBVersionChangeTransaction;
|
||||
include protocol PBlob;
|
||||
|
||||
include InputStreamParams;
|
||||
include PBackgroundIDBSharedTypes;
|
||||
|
||||
include "mozilla/dom/indexedDB/SerializationHelpers.h";
|
||||
|
||||
using struct mozilla::null_t
|
||||
from "ipc/IPCMessageUtils.h";
|
||||
|
||||
using mozilla::dom::indexedDB::IDBTransaction::Mode
|
||||
from "mozilla/dom/indexedDB/IDBTransaction.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace indexedDB {
|
||||
|
||||
union NullableVersion
|
||||
{
|
||||
null_t;
|
||||
uint64_t;
|
||||
};
|
||||
|
||||
union BlobOrInputStream
|
||||
{
|
||||
PBlob;
|
||||
InputStreamParams;
|
||||
};
|
||||
|
||||
protocol PBackgroundIDBDatabase
|
||||
{
|
||||
manager PBackgroundIDBFactory;
|
||||
|
||||
manages PBackgroundIDBDatabaseFile;
|
||||
manages PBackgroundIDBTransaction;
|
||||
manages PBackgroundIDBVersionChangeTransaction;
|
||||
|
||||
parent:
|
||||
DeleteMe();
|
||||
|
||||
Blocked();
|
||||
|
||||
Close();
|
||||
|
||||
PBackgroundIDBDatabaseFile(BlobOrInputStream blobOrInputStream);
|
||||
|
||||
PBackgroundIDBTransaction(nsString[] objectStoreNames, Mode mode);
|
||||
|
||||
child:
|
||||
__delete__();
|
||||
|
||||
VersionChange(uint64_t oldVersion, NullableVersion newVersion);
|
||||
|
||||
Invalidate();
|
||||
|
||||
PBackgroundIDBVersionChangeTransaction(uint64_t currentVersion,
|
||||
uint64_t requestedVersion,
|
||||
int64_t nextObjectStoreId,
|
||||
int64_t nextIndexId);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче