--HG--
rename : toolkit/modules/tests/browser/browser_AddonWatcher.js => toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js
This commit is contained in:
Ryan VanderMeulen 2015-04-17 15:44:37 -04:00
Родитель 8d0b312cb2 e53c8996ad
Коммит 86aee22968
788 изменённых файлов: 61159 добавлений и 65998 удалений

Просмотреть файл

@ -22,8 +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 1155082: Merge BluetoothUUID.{cpp,h} variants into single file
This patch set renames and removes source files. This requires updating
the build system's dependency information from scratch. The issue has
been reported in bug 1154232.
Bug 1148639 - libvpx update moved a bunch of files around.

Просмотреть файл

@ -287,6 +287,7 @@ skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and
[browser_bug1070778.js]
[browser_canonizeURL.js]
skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
[browser_clipboard.js]
[browser_contentAreaClick.js]
[browser_contextSearchTabPosition.js]
skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash

Просмотреть файл

@ -0,0 +1,123 @@
// This test is used to check copy and paste in editable areas to ensure that non-text
// types (html and images) are copied to and pasted from the clipboard properly.
let testPage = "<div id='main' contenteditable='true'>Test <b>Bold</b> After Text</div>";
add_task(function*() {
let tab = gBrowser.addTab();
let browser = gBrowser.getBrowserForTab(tab);
gBrowser.selectedTab = tab;
yield promiseTabLoadEvent(tab, "data:text/html," + escape(testPage));
yield SimpleTest.promiseFocus(browser.contentWindowAsCPOW);
let results = yield ContentTask.spawn(browser, {}, function* () {
var doc = content.document;
var main = doc.getElementById("main");
main.focus();
const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
const modifier = (content.navigator.platform.indexOf("Mac") >= 0) ?
Components.interfaces.nsIDOMWindowUtils.MODIFIER_META :
Components.interfaces.nsIDOMWindowUtils.MODIFIER_CONTROL;
function sendKey(key)
{
if (utils.sendKeyEvent("keydown", key, 0, modifier)) {
utils.sendKeyEvent("keypress", key, key.charCodeAt(0), modifier);
}
utils.sendKeyEvent("keyup", key, 0, modifier);
}
let results = [];
function is(l, r, v) {
results.push(((l === r) ? "PASSED" : "FAILED") + " got: " + l + " expected: " + r + " - " + v);
}
// Select an area of the text.
let selection = doc.getSelection();
selection.modify("move", "left", "line");
selection.modify("move", "right", "character");
selection.modify("move", "right", "character");
selection.modify("move", "right", "character");
selection.modify("extend", "right", "word");
selection.modify("extend", "right", "word");
yield new content.Promise((resolve, reject) => {
addEventListener("copy", function copyEvent(event) {
removeEventListener("copy", copyEvent, true);
// The data is empty as the selection is copied during the event default phase.
is(event.clipboardData.mozItemCount, 0, "Zero items on clipboard");
resolve();
}, true)
sendKey("c");
});
selection.modify("move", "right", "line");
yield new content.Promise((resolve, reject) => {
addEventListener("paste", function copyEvent(event) {
removeEventListener("paste", copyEvent, true);
let clipboardData = event.clipboardData;
is(clipboardData.mozItemCount, 1, "One item on clipboard");
is(clipboardData.types.length, 2, "Two types on clipboard");
is(clipboardData.types[0], "text/html", "text/html on clipboard");
is(clipboardData.types[1], "text/plain", "text/plain on clipboard");
is(clipboardData.getData("text/html"), "t <b>Bold</b>", "text/html value");
is(clipboardData.getData("text/plain"), "t Bold", "text/plain value");
resolve();
}, true)
sendKey("v");
});
is(main.innerHTML, "Test <b>Bold</b> After Textt <b>Bold</b>", "Copy and paste html");
selection.modify("extend", "left", "word");
selection.modify("extend", "left", "word");
selection.modify("extend", "left", "character");
yield new content.Promise((resolve, reject) => {
addEventListener("cut", function copyEvent(event) {
removeEventListener("cut", copyEvent, true);
event.clipboardData.setData("text/plain", "Some text");
event.clipboardData.setData("text/html", "<i>Italic</i> ");
selection.deleteFromDocument();
event.preventDefault();
resolve();
}, true)
sendKey("x");
});
selection.modify("move", "left", "line");
yield new content.Promise((resolve, reject) => {
addEventListener("paste", function copyEvent(event) {
removeEventListener("paste", copyEvent, true);
let clipboardData = event.clipboardData;
is(clipboardData.mozItemCount, 1, "One item on clipboard 2");
is(clipboardData.types.length, 2, "Two types on clipboard 2");
is(clipboardData.types[0], "text/html", "text/html on clipboard 2");
is(clipboardData.types[1], "text/plain", "text/plain on clipboard 2");
is(clipboardData.getData("text/html"), "<i>Italic</i> ", "text/html value 2");
is(clipboardData.getData("text/plain"), "Some text", "text/plain value 2");
resolve();
}, true)
sendKey("v");
});
is(main.innerHTML, "<i>Italic</i> Test <b>Bold</b> After<b></b>", "Copy and paste html 2");
return results;
});
is(results.length, 15, "Correct number of results");
for (var t = 0; t < results.length; t++) {
ok(results[t].startsWith("PASSED"), results[t]);
}
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -246,7 +246,7 @@ var gAdvancedPane = {
document.getElementById("submitTelemetryBox").disabled = disabled;
if (disabled) {
// If we disable FHR, untick the telemetry checkbox.
document.getElementById("submitTelemetryBox").checked = false;
Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
}
document.getElementById("telemetryDataDesc").disabled = disabled;
#endif

Просмотреть файл

@ -275,7 +275,7 @@ var gAdvancedPane = {
document.getElementById("submitTelemetryBox").disabled = disabled;
if (disabled) {
// If we disable FHR, untick the telemetry checkbox.
document.getElementById("submitTelemetryBox").checked = false;
Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
}
document.getElementById("telemetryDataDesc").disabled = disabled;
#endif

Просмотреть файл

@ -3,6 +3,8 @@
"use strict";
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
function runPaneTest(fn) {
open_preferences((win) => {
let doc = win.document;
@ -28,12 +30,16 @@ function testTelemetryState(win, doc) {
let telmetryCheckbox = doc.getElementById("submitTelemetryBox");
Assert.ok(!telmetryCheckbox.disabled,
"Telemetry checkbox must be enabled if FHR is checked.");
Assert.ok(Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
"Telemetry must be enabled if the checkbox is ticked.");
// Uncheck the FHR checkbox and make sure that Telemetry checkbox gets disabled.
fhrCheckbox.click();
Assert.ok(telmetryCheckbox.disabled,
"Telemetry checkbox must be disabled if FHR is unchecked.");
Assert.ok(!Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
"Telemetry must be disabled if the checkbox is unticked.");
win.close();
finish();
@ -41,5 +47,6 @@ function testTelemetryState(win, doc) {
function resetPreferences() {
Services.prefs.clearUserPref("datareporting.healthreport.uploadEnabled");
Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
}

Просмотреть файл

@ -3,6 +3,8 @@
"use strict";
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
function runPaneTest(fn) {
function observer(win, topic, data) {
Services.obs.removeObserver(observer, "advanced-pane-loaded");
@ -40,12 +42,16 @@ function testTelemetryState(win) {
let telmetryCheckbox = doc.getElementById("submitTelemetryBox");
Assert.ok(!telmetryCheckbox.disabled,
"Telemetry checkbox must be enabled if FHR is checked.");
Assert.ok(Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
"Telemetry must be enabled if the checkbox is ticked.");
// Uncheck the FHR checkbox and make sure that Telemetry checkbox gets disabled.
fhrCheckbox.click();
Assert.ok(telmetryCheckbox.disabled,
"Telemetry checkbox must be disabled if FHR is unchecked.");
Assert.ok(!Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
"Telemetry must be disabled if the checkbox is unticked.");
win.close();
finish();
@ -57,5 +63,6 @@ function resetPreferences() {
.wrappedJSObject;
service.policy._prefs.resetBranch("datareporting.policy.");
service.policy.dataSubmissionPolicyBypassNotification = true;
Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
}

Просмотреть файл

@ -243,6 +243,7 @@ def check_style():
# - "js/src/vm/String.h" -> "vm/String.h"
mfbt_inclnames = set() # type: set(inclname)
mozalloc_inclnames = set() # type: set(inclname)
js_names = dict() # type: dict(filename, inclname)
# Select the appropriate files.
@ -251,6 +252,10 @@ def check_style():
inclname = 'mozilla/' + filename.split('/')[-1]
mfbt_inclnames.add(inclname)
if filename.startswith('memory/mozalloc/') and filename.endswith('.h'):
inclname = 'mozilla/' + filename.split('/')[-1]
mozalloc_inclnames.add(inclname)
if filename.startswith('js/public/') and filename.endswith('.h'):
inclname = 'js/' + filename[len('js/public/'):]
js_names[filename] = inclname
@ -261,13 +266,13 @@ def check_style():
inclname = filename[len('js/src/'):]
js_names[filename] = inclname
all_inclnames = mfbt_inclnames | set(js_names.values())
all_inclnames = mfbt_inclnames | mozalloc_inclnames | set(js_names.values())
edges = dict() # type: dict(inclname, set(inclname))
# We don't care what's inside the MFBT files, but because they are
# #included from JS files we have to add them to the inclusion graph.
for inclname in mfbt_inclnames:
# We don't care what's inside the MFBT and MOZALLOC files, but because they
# are #included from JS files we have to add them to the inclusion graph.
for inclname in mfbt_inclnames | mozalloc_inclnames:
edges[inclname] = set()
# Process all the JS files.

Просмотреть файл

@ -3436,20 +3436,6 @@ AC_CACHE_CHECK(for __attribute__((always_inline)),
ac_cv_attribute_always_inline=yes,
ac_cv_attribute_always_inline=no)])
AC_CACHE_CHECK(for __attribute__((malloc)),
ac_cv_attribute_malloc,
[AC_TRY_COMPILE([void* f(int) __attribute__((malloc));],
[],
ac_cv_attribute_malloc=yes,
ac_cv_attribute_malloc=no)])
AC_CACHE_CHECK(for __attribute__((warn_unused_result)),
ac_cv_attribute_warn_unused,
[AC_TRY_COMPILE([int f(void) __attribute__((warn_unused_result));],
[],
ac_cv_attribute_warn_unused=yes,
ac_cv_attribute_warn_unused=no)])
dnl End of C++ language/feature checks
AC_LANG_C
@ -3481,25 +3467,6 @@ if test -n "${CPU_ARCH}" -a -n "${TARGET_COMPILER_ABI}"; then
AC_DEFINE_UNQUOTED(TARGET_XPCOM_ABI, ["${TARGET_XPCOM_ABI}"])
fi
dnl Mozilla specific options
dnl ========================================================
dnl The macros used for command line options
dnl are defined in build/autoconf/altoptions.m4.
dnl If the compiler supports these attributes, define them as
dnl convenience macros.
if test "$ac_cv_attribute_malloc" = yes ; then
AC_DEFINE(NS_ATTR_MALLOC, [__attribute__((malloc))])
else
AC_DEFINE(NS_ATTR_MALLOC,)
fi
if test "$ac_cv_attribute_warn_unused" = yes ; then
AC_DEFINE(NS_WARN_UNUSED_RESULT, [__attribute__((warn_unused_result))])
else
AC_DEFINE(NS_WARN_UNUSED_RESULT,)
fi
dnl We can't run TRY_COMPILE tests on Windows, so hard-code some
dnl features that Windows actually does support.
@ -3510,6 +3477,11 @@ if test -n "$SKIP_COMPILER_CHECKS"; then
AC_DEFINE(HAVE_LOCALECONV)
fi # SKIP_COMPILER_CHECKS
dnl Mozilla specific options
dnl ========================================================
dnl The macros used for command line options
dnl are defined in build/autoconf/altoptions.m4.
dnl ========================================================
dnl =
dnl = Check for external package dependencies

Просмотреть файл

@ -5023,24 +5023,32 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
error.AssignLiteral("nssBadCert");
// if this is a Strict-Transport-Security host and the cert
// is bad, don't allow overrides (STS Spec section 7.3).
uint32_t type = nsISiteSecurityService::HEADER_HSTS;
// If this is an HTTP Strict Transport Security host or a pinned host
// and the certificate is bad, don't allow overrides (RFC 6797 section
// 12.1, HPKP draft spec section 2.6).
uint32_t flags =
mInPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
bool isStsHost = false;
bool isPinnedHost = false;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
nsCOMPtr<nsISiteSecurityService> sss =
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(type, aURI, flags, &isStsHost);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
flags, &isStsHost);
NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
flags, &isPinnedHost);
NS_ENSURE_SUCCESS(rv, rv);
} else {
mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton();
mozilla::ipc::URIParams uri;
SerializeURI(aURI, uri);
cc->SendIsSecureURI(type, uri, flags, &isStsHost);
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri, flags,
&isStsHost);
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HPKP, uri, flags,
&isPinnedHost);
}
if (Preferences::GetBool(
@ -5048,11 +5056,16 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
cssClass.AssignLiteral("expertBadCert");
}
// HSTS takes precedence over the expert bad cert pref. We
// never want to show the "Add Exception" button for HSTS sites.
// HSTS/pinning takes precedence over the expert bad cert pref. We
// never want to show the "Add Exception" button for these sites.
// In the future we should differentiate between an HSTS host and a
// pinned host and display a more informative message to the user.
if (isStsHost || isPinnedHost) {
cssClass.AssignLiteral("badStsCert");
}
uint32_t bucketId;
if (isStsHost) {
cssClass.AssignLiteral("badStsCert");
// measuring STS separately allows us to measure click through
// rates easily
bucketId = nsISecurityUITelemetry::WARNING_BAD_CERT_TOP_STS;
@ -11461,7 +11474,7 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
scContainer = new nsStructuredCloneContainer();
rv = scContainer->InitFromJSVal(aData);
rv = scContainer->InitFromJSVal(aData, aCx);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> newDocument = GetDocument();

Просмотреть файл

@ -1,6 +1,4 @@
[DEFAULT]
skip-if = e10s
support-files =
file_empty.html

Просмотреть файл

@ -456,7 +456,7 @@ FragmentOrElement::Children()
if (!slots->mChildrenList) {
slots->mChildrenList = new nsContentList(this, kNameSpaceID_Wildcard,
nsGkAtoms::_asterix, nsGkAtoms::_asterix,
nsGkAtoms::_asterisk, nsGkAtoms::_asterisk,
false);
}

Просмотреть файл

@ -17,7 +17,6 @@
#include "nsAttrAndChildArray.h" // member
#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
#include "nsIContent.h" // base class
#include "nsINodeList.h" // base class
#include "nsIWeakReference.h" // base class
#include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl
#include "nsIHTMLCollection.h"
@ -38,50 +37,6 @@ class Element;
}
}
/**
* Class that implements the nsIDOMNodeList interface (a list of children of
* the content), by holding a reference to the content and delegating GetLength
* and Item to its existing child list.
* @see nsIDOMNodeList
*/
class nsChildContentList final : public nsINodeList
{
public:
explicit nsChildContentList(nsINode* aNode)
: mNode(aNode)
{
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList)
// nsWrapperCache
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
// nsIDOMNodeList interface
NS_DECL_NSIDOMNODELIST
// nsINodeList interface
virtual int32_t IndexOf(nsIContent* aContent) override;
virtual nsIContent* Item(uint32_t aIndex) override;
void DropReference()
{
mNode = nullptr;
}
virtual nsINode* GetParentObject() override
{
return mNode;
}
private:
~nsChildContentList() {}
// The node whose children make up the list (weak reference)
nsINode* mNode;
};
/**
* A class that implements nsIWeakReference
*/
@ -186,8 +141,8 @@ public:
virtual bool TextIsOnlyWhitespace() override;
virtual bool HasTextForTranslation() override;
virtual void AppendTextTo(nsAString& aResult) override;
virtual bool AppendTextTo(nsAString& aResult,
const mozilla::fallible_t&) override NS_WARN_UNUSED_RESULT;
MOZ_WARN_UNUSED_RESULT
virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) override;
virtual nsIContent *GetBindingParent() const override;
virtual nsXBLBinding *GetXBLBinding() const override;
virtual void SetXBLBinding(nsXBLBinding* aBinding,

Просмотреть файл

@ -0,0 +1,9 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<body><body>
<script>
s = document.createElement('script');
s.src="";
document.body.appendChild(s);
</script>
</body>
</html>

Просмотреть файл

@ -200,3 +200,5 @@ pref(dom.webcomponents.enabled,true) load 1029710.html
HTTP(..) load xhr_abortinprogress.html
load xhr_empty_datauri.html
load xhr_html_nullresponse.html
load structured_clone_container_throws.html
load 1154598.xhtml

Просмотреть файл

@ -0,0 +1,9 @@
<iframe></iframe>
<script>
try { frames[0].history.pushState({ dummy: function() {} }, ''); }
catch (e) {}
var doc = frames[0].document;
var s = doc.createElement("script");
s.textContent = "1";
doc.body.appendChild(s);
</script>

Просмотреть файл

@ -417,6 +417,7 @@ LOCAL_INCLUDES += [
'/dom/xml',
'/dom/xslt/xpath',
'/dom/xul',
'/gfx/2d',
'/image/src',
'/js/xpconnect/src',
'/js/xpconnect/wrappers',

Просмотреть файл

@ -404,8 +404,8 @@ nsContentList::nsContentList(nsINode* aRootNode,
mFuncMayDependOnAttr(false)
{
NS_ASSERTION(mRootNode, "Must have root");
if (nsGkAtoms::_asterix == mHTMLMatchAtom) {
NS_ASSERTION(mXMLMatchAtom == nsGkAtoms::_asterix, "HTML atom and XML atom are not both asterix?");
if (nsGkAtoms::_asterisk == mHTMLMatchAtom) {
NS_ASSERTION(mXMLMatchAtom == nsGkAtoms::_asterisk, "HTML atom and XML atom are not both asterisk?");
mMatchAll = true;
}
else {

Просмотреть файл

@ -171,6 +171,7 @@
#include "nsReferencedElement.h"
#include "nsSandboxFlags.h"
#include "nsScriptSecurityManager.h"
#include "nsStreamUtils.h"
#include "nsSVGFeatures.h"
#include "nsTextEditorState.h"
#include "nsTextFragment.h"
@ -7219,7 +7220,6 @@ nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables
mozilla::dom::nsIContentParent* aParent)
{
aIPC.Clear();
MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
if (aTransferables) {
uint32_t transferableCount = 0;
aTransferables->Count(&transferableCount);
@ -7227,75 +7227,135 @@ nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables
IPCDataTransfer* dt = aIPC.AppendElement();
nsCOMPtr<nsISupports> genericItem;
aTransferables->GetElementAt(i, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> item(do_QueryInterface(genericItem));
if (item) {
nsCOMPtr<nsISupportsArray> flavorList;
item->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
if (flavorList) {
uint32_t flavorCount = 0;
flavorList->Count(&flavorCount);
for (uint32_t j = 0; j < flavorCount; ++j) {
nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
if (!flavor) {
continue;
nsCOMPtr<nsITransferable> transferable(do_QueryInterface(genericItem));
TransferableToIPCTransferable(transferable, dt, aChild, aParent);
}
}
}
void
nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
IPCDataTransfer* aIPCDataTransfer,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent)
{
MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
if (aTransferable) {
nsCOMPtr<nsISupportsArray> flavorList;
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
if (flavorList) {
uint32_t flavorCount = 0;
flavorList->Count(&flavorCount);
for (uint32_t j = 0; j < flavorCount; ++j) {
nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
if (!flavor) {
continue;
}
nsAutoCString flavorStr;
flavor->GetData(flavorStr);
if (!flavorStr.Length()) {
continue;
}
nsCOMPtr<nsISupports> data;
uint32_t dataLen = 0;
aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
if (text) {
nsAutoString dataAsString;
text->GetData(dataAsString);
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = nsString(dataAsString);
} else if (ctext) {
nsAutoCString dataAsString;
ctext->GetData(dataAsString);
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = nsCString(dataAsString);
} else {
nsCOMPtr<nsISupportsInterfacePointer> sip =
do_QueryInterface(data);
if (sip) {
sip->GetData(getter_AddRefs(data));
}
// Images to be pasted on the clipboard are nsIInputStreams
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
if (stream) {
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
nsCString imageData;
NS_ConsumeStream(stream, UINT32_MAX, imageData);
item->data() = imageData;
continue;
}
// Images to be placed on the clipboard are imgIContainers.
nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
if (image) {
RefPtr<mozilla::gfx::SourceSurface> surface =
image->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
mozilla::RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
surface->GetDataSurface();
size_t length;
int32_t stride;
mozilla::UniquePtr<char[]> surfaceData =
nsContentUtils::GetSurfaceData(dataSurface, &length, &stride);
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = nsCString(surfaceData.get(), length);
IPCDataTransferImage& imageDetails = item->imageDetails();
mozilla::gfx::IntSize size = dataSurface->GetSize();
imageDetails.width() = size.width;
imageDetails.height() = size.height;
imageDetails.stride() = stride;
imageDetails.format() = static_cast<uint8_t>(dataSurface->GetFormat());
continue;
}
// Otherwise, handle this as a file.
nsCOMPtr<FileImpl> fileImpl;
nsCOMPtr<nsIFile> file = do_QueryInterface(data);
if (file) {
fileImpl = new FileImplFile(file, false);
ErrorResult rv;
fileImpl->GetSize(rv);
fileImpl->GetLastModified(rv);
} else {
fileImpl = do_QueryInterface(data);
}
if (fileImpl) {
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
if (aChild) {
item->data() =
mozilla::dom::BlobChild::GetOrCreate(aChild,
static_cast<FileImpl*>(fileImpl.get()));
} else if (aParent) {
item->data() =
mozilla::dom::BlobParent::GetOrCreate(aParent,
static_cast<FileImpl*>(fileImpl.get()));
}
nsAutoCString flavorStr;
flavor->GetData(flavorStr);
if (!flavorStr.Length()) {
continue;
}
nsCOMPtr<nsISupports> data;
uint32_t dataLen = 0;
item->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
if (text) {
nsAutoString dataAsString;
text->GetData(dataAsString);
IPCDataTransferItem* item = dt->items().AppendElement();
} else {
// This is a hack to support kFilePromiseMime.
// On Windows there just needs to be an entry for it,
// and for OSX we need to create
// nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = nsString(dataAsString);
} else {
nsCOMPtr<nsISupportsInterfacePointer> sip =
do_QueryInterface(data);
if (sip) {
sip->GetData(getter_AddRefs(data));
}
nsCOMPtr<FileImpl> fileImpl;
nsCOMPtr<nsIFile> file = do_QueryInterface(data);
if (file) {
fileImpl = new FileImplFile(file, false);
ErrorResult rv;
fileImpl->GetSize(rv);
fileImpl->GetLastModified(rv);
} else {
fileImpl = do_QueryInterface(data);
}
if (fileImpl) {
IPCDataTransferItem* item = dt->items().AppendElement();
item->flavor() = nsCString(flavorStr);
if (aChild) {
item->data() =
mozilla::dom::BlobChild::GetOrCreate(aChild,
static_cast<FileImpl*>(fileImpl.get()));
} else if (aParent) {
item->data() =
mozilla::dom::BlobParent::GetOrCreate(aParent,
static_cast<FileImpl*>(fileImpl.get()));
}
} else {
// This is a hack to support kFilePromiseMime.
// On Windows there just needs to be an entry for it,
// and for OSX we need to create
// nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
IPCDataTransferItem* item = dt->items().AppendElement();
item->flavor() = nsCString(flavorStr);
item->data() = NS_ConvertUTF8toUTF16(flavorStr);
}
}
item->data() = NS_ConvertUTF8toUTF16(flavorStr);
}
}
}
@ -7303,3 +7363,31 @@ nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables
}
}
}
mozilla::UniquePtr<char[]>
nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride)
{
mozilla::gfx::DataSourceSurface::MappedSurface map;
aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map);
mozilla::gfx::IntSize size = aSurface->GetSize();
mozilla::CheckedInt32 requiredBytes =
mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
size_t maxBufLen = requiredBytes.isValid() ? requiredBytes.value() : 0;
mozilla::gfx::SurfaceFormat format = aSurface->GetFormat();
// Surface data handling is totally nuts. This is the magic one needs to
// know to access the data.
size_t bufLen = maxBufLen - map.mStride + (size.width * BytesPerPixel(format));
// nsDependentCString wants null-terminated string.
mozilla::UniquePtr<char[]> surfaceData(new char[maxBufLen + 1]);
memcpy(surfaceData.get(), reinterpret_cast<char*>(map.mData), bufLen);
memset(surfaceData.get() + bufLen, 0, maxBufLen - bufLen + 1);
*aLength = maxBufLen;
*aStride = map.mStride;
aSurface->Unmap();
return surfaceData;
}

Просмотреть файл

@ -103,6 +103,7 @@ class nsTextFragment;
class nsViewportInfo;
class nsWrapperCache;
class nsAttrValue;
class nsITransferable;
struct JSPropertyDescriptor;
struct JSRuntime;
@ -129,6 +130,10 @@ class Selection;
class TabParent;
} // namespace dom
namespace gfx {
class DataSourceSurface;
} // namespace gfx
namespace layers {
class LayerManager;
} // namespace layers
@ -1277,8 +1282,9 @@ public:
* @param aResult the result. Out param.
* @return false on out of memory errors, true otherwise.
*/
MOZ_WARN_UNUSED_RESULT
static bool GetNodeTextContent(nsINode* aNode, bool aDeep,
nsAString& aResult) NS_WARN_UNUSED_RESULT;
nsAString& aResult);
/**
* Same as GetNodeTextContents but appends the result rather than sets it.
@ -1753,8 +1759,9 @@ public:
* @param aString the string to convert the newlines inside [in/out]
*/
static void PlatformToDOMLineBreaks(nsString &aString);
static NS_WARN_UNUSED_RESULT bool PlatformToDOMLineBreaks(nsString &aString,
const mozilla::fallible_t&);
MOZ_WARN_UNUSED_RESULT
static bool PlatformToDOMLineBreaks(nsString &aString,
const mozilla::fallible_t&);
/**
* Populates aResultString with the contents of the string-buffer aBuf, up
@ -2296,6 +2303,19 @@ public:
nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent);
static void TransferableToIPCTransferable(nsITransferable* aTransferable,
mozilla::dom::IPCDataTransfer* aIPCDataTransfer,
mozilla::dom::nsIContentChild* aChild,
mozilla::dom::nsIContentParent* aParent);
/*
* Get the pixel data from the given source surface and return it as a buffer.
* The length and stride will be assigned from the surface.
*/
static mozilla::UniquePtr<char[]> GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride);
private:
static bool InitializeEventTable();

Просмотреть файл

@ -34,10 +34,10 @@ public:
int32_t mNamespaceID;
/**
* The atom for attribute, weak ref. is fine as we only use it for the
* hashcode, we never dereference it.
* The atom for attribute, stored as void*, to make sure that we only use it
* for the hashcode, and we can never dereference it.
*/
nsIAtom* mLocalName;
void* mLocalName;
nsAttrKey(int32_t aNs, nsIAtom* aName)
: mNamespaceID(aNs), mLocalName(aName) {}

Просмотреть файл

@ -10831,8 +10831,8 @@ nsIDocument::Children()
{
if (!mChildrenCollection) {
mChildrenCollection = new nsContentList(this, kNameSpaceID_Wildcard,
nsGkAtoms::_asterix,
nsGkAtoms::_asterix,
nsGkAtoms::_asterisk,
nsGkAtoms::_asterisk,
false);
}

Просмотреть файл

@ -142,8 +142,9 @@ public:
virtual bool TextIsOnlyWhitespace() override;
virtual bool HasTextForTranslation() override;
virtual void AppendTextTo(nsAString& aResult) override;
MOZ_WARN_UNUSED_RESULT
virtual bool AppendTextTo(nsAString& aResult,
const mozilla::fallible_t&) override NS_WARN_UNUSED_RESULT;
const mozilla::fallible_t&) override;
virtual void DestroyContent() override;
virtual void SaveSubtreeState() override;

Просмотреть файл

@ -50,7 +50,7 @@ GK_ATOM(_moz_original_size, "_moz_original_size")
GK_ATOM(_moz_target, "_moz_target")
GK_ATOM(menuactive, "_moz-menuactive")
GK_ATOM(_poundDefault, "#default")
GK_ATOM(_asterix, "*")
GK_ATOM(_asterisk, "*")
GK_ATOM(a, "a")
GK_ATOM(abbr, "abbr")
GK_ATOM(abort, "abort")

Просмотреть файл

@ -36,7 +36,7 @@ class nsHTMLContentSerializer final : public nsXHTMLContentSerializer {
nsAString& aStr) override;
protected:
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool SerializeHTMLAttributes(nsIContent* aContent,
nsIContent *aOriginalElement,
nsAString& aTagPrefix,
@ -45,7 +45,7 @@ class nsHTMLContentSerializer final : public nsXHTMLContentSerializer {
int32_t aNamespace,
nsAString& aStr);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
nsAString& aOutputStr) override;

Просмотреть файл

@ -545,8 +545,8 @@ public:
* Append the text content to aResult.
* NOTE: This asserts and returns for elements
*/
virtual bool AppendTextTo(nsAString& aResult,
const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT = 0;
MOZ_WARN_UNUSED_RESULT
virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) = 0;
/**
* Check if this content is focusable and in the current tab order.

Просмотреть файл

@ -113,7 +113,6 @@ nsINode::nsSlots::~nsSlots()
{
if (mChildNodes) {
mChildNodes->DropReference();
NS_RELEASE(mChildNodes);
}
if (mWeakReference) {
@ -133,7 +132,6 @@ nsINode::nsSlots::Unlink()
{
if (mChildNodes) {
mChildNodes->DropReference();
NS_RELEASE(mChildNodes);
}
}
@ -371,9 +369,6 @@ nsINode::ChildNodes()
nsSlots* slots = Slots();
if (!slots->mChildNodes) {
slots->mChildNodes = new nsChildContentList(this);
if (slots->mChildNodes) {
NS_ADDREF(slots->mChildNodes);
}
}
return slots->mChildNodes;

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty
#include "nsIDOMNode.h"
#include "mozilla/dom/NodeInfo.h" // member (in nsCOMPtr)
#include "nsINodeList.h" // base class
#include "nsIVariant.h" // for use in GetUserData()
#include "nsNodeInfoManager.h" // for use in NodePrincipal()
#include "nsPropertyTable.h" // for typedefs
@ -41,7 +42,7 @@ class nsIDOMNodeList;
class nsIEditor;
class nsIFrame;
class nsIMutationObserver;
class nsINodeList;
class nsINode;
class nsIPresShell;
class nsIPrincipal;
class nsIURI;
@ -234,6 +235,50 @@ private:
static uint64_t sGeneration;
};
/**
* Class that implements the nsIDOMNodeList interface (a list of children of
* the content), by holding a reference to the content and delegating GetLength
* and Item to its existing child list.
* @see nsIDOMNodeList
*/
class nsChildContentList final : public nsINodeList
{
public:
explicit nsChildContentList(nsINode* aNode)
: mNode(aNode)
{
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList)
// nsWrapperCache
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
// nsIDOMNodeList interface
NS_DECL_NSIDOMNODELIST
// nsINodeList interface
virtual int32_t IndexOf(nsIContent* aContent) override;
virtual nsIContent* Item(uint32_t aIndex) override;
void DropReference()
{
mNode = nullptr;
}
virtual nsINode* GetParentObject() override
{
return mNode;
}
private:
~nsChildContentList() {}
// The node whose children make up the list (weak reference)
nsINode* mNode;
};
// This should be used for any nsINode sub-class that has fields of its own
// that it needs to measure; any sub-class that doesn't use it will inherit
// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be
@ -1021,8 +1066,7 @@ public:
{
public:
nsSlots()
: mChildNodes(nullptr),
mWeakReference(nullptr)
: mWeakReference(nullptr)
{
}
@ -1042,15 +1086,14 @@ public:
* An object implementing nsIDOMNodeList for this content (childNodes)
* @see nsIDOMNodeList
* @see nsGenericHTMLElement::GetChildNodes
*
* MSVC 7 doesn't like this as an nsRefPtr
*/
nsChildContentList* mChildNodes;
nsRefPtr<nsChildContentList> mChildNodes;
/**
* Weak reference to this node
* Weak reference to this node. This is cleared by the destructor of
* nsNodeWeakReference.
*/
nsNodeWeakReference* mWeakReference;
nsNodeWeakReference* MOZ_NON_OWNING_REF mWeakReference;
};
/**

Просмотреть файл

@ -8,13 +8,15 @@
#include "nsIDOMNodeList.h"
#include "nsWrapperCache.h"
#include "nsIContent.h"
// IID for the nsINodeList interface
#define NS_INODELIST_IID \
{ 0xadb5e54c, 0x6e96, 0x4102, \
{ 0x8d, 0x40, 0xe0, 0x12, 0x3d, 0xcf, 0x48, 0x7a } }
class nsIContent;
class nsINode;
/**
* An internal interface for a reasonably fast indexOf.
*/

Просмотреть файл

@ -129,13 +129,13 @@ private:
void *arg);
PLHashTable *mNodeInfoHash;
nsIDocument *mDocument; // WEAK
nsIDocument * MOZ_NON_OWNING_REF mDocument; // WEAK
uint32_t mNonDocumentNodeInfos;
nsCOMPtr<nsIPrincipal> mPrincipal; // Never null after Init() succeeds.
nsCOMPtr<nsIPrincipal> mDefaultPrincipal; // Never null after Init() succeeds
mozilla::dom::NodeInfo *mTextNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo *mCommentNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo *mDocumentNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mTextNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mCommentNodeInfo; // WEAK to avoid circular ownership
mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mDocumentNodeInfo; // WEAK to avoid circular ownership
nsRefPtr<nsBindingManager> mBindingManager;
};

Просмотреть файл

@ -76,6 +76,7 @@ nsScriptLoadRequestList::Clear()
{
while (!isEmpty()) {
nsRefPtr<nsScriptLoadRequest> first = StealFirst();
first->Cancel();
// And just let it go out of scope and die.
}
}
@ -1486,6 +1487,10 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
return aStatus;
}
if (aRequest->IsCanceled()) {
return NS_BINDING_ABORTED;
}
// If we don't have a document, then we need to abort further
// evaluation.
if (!mDocument) {
@ -1556,10 +1561,15 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// Mark this as loaded
aRequest->mLoading = false;
// And if it's async, move it to the loaded list.
// And if it's async, move it to the loaded list. aRequest->mIsAsync really
// _should_ be in a list, but the consequences if it's not are bad enough we
// want to avoid trying to move it if it's not.
if (aRequest->mIsAsync) {
nsRefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
mLoadedAsyncRequests.AppendElement(req);
MOZ_ASSERT(aRequest->isInList());
if (aRequest->isInList()) {
nsRefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
mLoadedAsyncRequests.AppendElement(req);
}
}
return NS_OK;
@ -1580,7 +1590,10 @@ nsScriptLoader::ParsingComplete(bool aTerminated)
mLoadedAsyncRequests.Clear();
mNonAsyncExternalScriptInsertedRequests.Clear();
mXSLTRequests.Clear();
mParserBlockingRequest = nullptr;
if (mParserBlockingRequest) {
mParserBlockingRequest->Cancel();
mParserBlockingRequest = nullptr;
}
}
// Have to call this even if aTerminated so we'll correctly unblock

Просмотреть файл

@ -64,6 +64,7 @@ public:
mIsAsync(false),
mIsNonAsyncScriptInserted(false),
mIsXSLT(false),
mIsCanceled(false),
mScriptTextBuf(nullptr),
mScriptTextLength(0),
mJSVersion(aVersion),
@ -89,6 +90,16 @@ public:
return mElement == nullptr;
}
void Cancel()
{
mIsCanceled = true;
}
bool IsCanceled() const
{
return mIsCanceled;
}
using super::getNext;
using super::isInList;
@ -100,6 +111,7 @@ public:
bool mIsAsync; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
bool mIsXSLT; // True if we live in mXSLTRequests.
bool mIsCanceled; // True if we have been explicitly canceled.
nsString mSourceMapURL; // Holds source map url for loaded scripts
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.

Просмотреть файл

@ -42,28 +42,19 @@ nsStructuredCloneContainer::~nsStructuredCloneContainer()
}
nsresult
nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData)
nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
JSContext* aCx)
{
NS_ENSURE_STATE(!mData);
uint64_t* jsBytes = nullptr;
bool success = false;
if (aData.isPrimitive()) {
// |aData| is a primitive, so the structured clone algorithm won't run
// script and we can just use AutoJSAPI.
dom::AutoJSAPI jsapi;
jsapi.Init();
success = JS_WriteStructuredClone(jsapi.cx(), aData, &jsBytes, &mSize,
success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
nullptr, nullptr,
JS::UndefinedHandleValue);
} else {
// |aData| is an object and the structured clone algorithm can run script as
// part of the "own" "deep clone" sub-steps, so we need an AutoEntryScript.
// http://www.whatwg.org/specs/web-apps/current-work/#internal-structured-cloning-algorithm
nsIGlobalObject* nativeGlobal =
xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&aData.toObject()));
dom::AutoEntryScript aes(nativeGlobal);
success = JS_WriteStructuredClone(aes.cx(), aData, &jsBytes, &mSize,
success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
nullptr, nullptr,
JS::UndefinedHandleValue);
}

Просмотреть файл

@ -134,8 +134,9 @@ public:
* Append the contents of this string fragment to aString
* @return false if an out of memory condition is detected, true otherwise
*/
MOZ_WARN_UNUSED_RESULT
bool AppendTo(nsAString& aString,
const mozilla::fallible_t& aFallible) const NS_WARN_UNUSED_RESULT {
const mozilla::fallible_t& aFallible) const {
if (mState.mIs2b) {
bool ok = aString.Append(m2b, mState.mLength, aFallible);
if (!ok) {
@ -167,8 +168,9 @@ public:
* @param aLength the length of the substring
* @return false if an out of memory condition is detected, true otherwise
*/
MOZ_WARN_UNUSED_RESULT
bool AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength,
const mozilla::fallible_t& aFallible) const NS_WARN_UNUSED_RESULT
const mozilla::fallible_t& aFallible) const
{
if (mState.mIs2b) {
bool ok = aString.Append(m2b + aOffset, aLength, aFallible);

Просмотреть файл

@ -46,13 +46,13 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
nsAString& aStr,
nsresult& aResult) override;
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AppendEndOfElementStart(nsIContent *aOriginalElement,
nsIAtom * aName,
int32_t aNamespaceID,
nsAString& aStr) override;
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AfterElementStart(nsIContent* aContent,
nsIContent* aOriginalElement,
nsAString& aStr) override;
@ -75,7 +75,7 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
virtual void MaybeEnterInPreContent(nsIContent* aNode) override;
virtual void MaybeLeaveFromPreContent(nsIContent* aNode) override;
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool SerializeAttributes(nsIContent* aContent,
nsIContent *aOriginalElement,
nsAString& aTagPrefix,
@ -87,13 +87,13 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
bool IsFirstChildOfOL(nsIContent* aElement);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool SerializeLIValueAttribute(nsIContent* aElement,
nsAString& aStr);
bool IsShorthandAttr(const nsIAtom* aAttrName,
const nsIAtom* aElementName);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
nsAString& aOutputStr) override;

Просмотреть файл

@ -72,14 +72,14 @@ class nsXMLContentSerializer : public nsIContentSerializer {
/**
* Appends a char16_t character and increments the column position
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendToString(const char16_t aChar,
nsAString& aOutputStr);
/**
* Appends a nsAString string and increments the column position
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendToString(const nsAString& aStr,
nsAString& aOutputStr);
@ -88,7 +88,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* by mLineBreak, except in the case of raw output.
* It increments the column position.
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendToStringConvertLF(const nsAString& aStr,
nsAString& aOutputStr);
@ -96,7 +96,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* Appends a string by wrapping it when necessary.
* It updates the column position.
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendToStringWrapped(const nsASingleFragmentString& aStr,
nsAString& aOutputStr);
@ -104,12 +104,12 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* Appends a string by formating and wrapping it when necessary
* It updates the column position.
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
nsAString& aOutputStr);
// used by AppendToStringWrapped
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendWrapped_WhitespaceSequence(
nsASingleFragmentString::const_char_iterator &aPos,
const nsASingleFragmentString::const_char_iterator aEnd,
@ -117,7 +117,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
nsAString &aOutputStr);
// used by AppendToStringFormatedWrapped
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendFormatedWrapped_WhitespaceSequence(
nsASingleFragmentString::const_char_iterator &aPos,
const nsASingleFragmentString::const_char_iterator aEnd,
@ -126,7 +126,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
nsAString &aOutputStr);
// used by AppendToStringWrapped and AppendToStringFormatedWrapped
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendWrapped_NonWhitespaceSequence(
nsASingleFragmentString::const_char_iterator &aPos,
const nsASingleFragmentString::const_char_iterator aEnd,
@ -139,7 +139,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* add mLineBreak to the string
* It updates the column position and other flags.
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendNewLineToString(nsAString& aOutputStr);
@ -147,7 +147,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* Appends a string by translating entities
* It doesn't increment the column position
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
nsAString& aOutputStr);
@ -197,7 +197,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
nsIContent *aOriginalElement,
const nsAString& aTagNamespaceURI);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool SerializeAttributes(nsIContent* aContent,
nsIContent *aOriginalElement,
nsAString& aTagPrefix,
@ -207,7 +207,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
uint32_t aSkipAttr,
bool aAddNSAttr);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool SerializeAttr(const nsAString& aPrefix,
const nsAString& aName,
const nsAString& aValue,
@ -236,7 +236,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* this method is responsible to finish the start tag,
* in particulary to append the "greater than" sign
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AppendEndOfElementStart(nsIContent *aOriginalElement,
nsIAtom * aName,
int32_t aNamespaceID,
@ -247,7 +247,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* after the serialization ot the start tag.
* (called at the end of AppendElementStart)
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
virtual bool AfterElementStart(nsIContent* aContent,
nsIContent* aOriginalElement,
nsAString& aStr) { return true; };
@ -296,16 +296,16 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* add intendation. Call only in the case of formating and if the current
* position is at 0. It updates the column position.
*/
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool AppendIndentation(nsAString& aStr);
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool IncrIndentation(nsIAtom* aName);
void DecrIndentation(nsIAtom* aName);
// Functions to check for newlines that needs to be added between nodes in
// the root of a document. See mAddNewlineForRootNode
NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
bool MaybeAddNewlineForRootNode(nsAString& aStr);
void MaybeFlagNewlineForRootNode(nsINode* aNode);

Просмотреть файл

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s
support-files =
file_binary-frames_wsh.py
file_check-binary-messages_wsh.py
@ -11,4 +10,4 @@ skip-if = buildapp == 'b2g' || toolkit == 'android'
[test_send-arraybuffer.html]
skip-if = buildapp == 'b2g' || toolkit == 'android'
[test_send-blob.html]
skip-if = buildapp == 'b2g' || toolkit == 'android'
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s

Просмотреть файл

@ -1,5 +1,2 @@
[DEFAULT]
skip-if = e10s
[test_battery_basics.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))

Просмотреть файл

@ -10446,7 +10446,7 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
# The deleter method has a boolean out-parameter. When a
# property is found, the out-param indicates whether it was
# successfully deleted.
decls = "bool result;\n"
decls = ""
if foundVar is None:
foundVar = "found"
decls += "bool found = false;\n"

Просмотреть файл

@ -66,16 +66,15 @@ public:
}
ErrorResult& operator=(ErrorResult&& aRHS);
explicit ErrorResult(nsresult aRv)
: ErrorResult()
{
AssignErrorCode(aRv);
}
void Throw(nsresult rv) {
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(rv != NS_ERROR_RANGE_ERR, "Use ThrowRangeError()");
MOZ_ASSERT(!IsErrorWithMessage(), "Don't overwrite errors with message");
MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
mResult = rv;
AssignErrorCode(rv);
}
void ThrowTypeError(const dom::ErrNum errorNumber, ...);
@ -141,14 +140,7 @@ public:
// Throw() here because people can easily pass success codes to
// this.
void operator=(nsresult rv) {
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(rv != NS_ERROR_RANGE_ERR, "Use ThrowRangeError()");
MOZ_ASSERT(!IsErrorWithMessage(), "Don't overwrite errors with message");
MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
mResult = rv;
AssignErrorCode(rv);
}
bool Failed() const {
@ -160,6 +152,24 @@ public:
}
private:
friend struct IPC::ParamTraits<ErrorResult>;
void SerializeMessage(IPC::Message* aMsg) const;
bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
void ThrowErrorWithMessage(va_list ap, const dom::ErrNum errorNumber,
nsresult errorType);
void AssignErrorCode(nsresult aRv) {
MOZ_ASSERT(aRv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(aRv != NS_ERROR_RANGE_ERR, "Use ThrowRangeError()");
MOZ_ASSERT(!IsErrorWithMessage(), "Don't overwrite errors with message");
MOZ_ASSERT(aRv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
MOZ_ASSERT(aRv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
mResult = aRv;
}
nsresult mResult;
struct Message;
// mMessage is set by ThrowErrorWithMessage and cleared (and deallocated) by
@ -171,10 +181,6 @@ private:
JS::Value mJSException; // valid when IsJSException()
};
friend struct IPC::ParamTraits<ErrorResult>;
void SerializeMessage(IPC::Message* aMsg) const;
bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
#ifdef DEBUG
// Used to keep track of codepaths that might throw JS exceptions,
// for assertion purposes.
@ -189,8 +195,6 @@ private:
// reference, not by value.
ErrorResult(const ErrorResult&) = delete;
void operator=(const ErrorResult&) = delete;
void ThrowErrorWithMessage(va_list ap, const dom::ErrNum errorNumber,
nsresult errorType);
};
/******************************************************************************

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsHashKeys.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
namespace mozilla {
@ -100,7 +101,8 @@ public:
this->EnumerateEntries(ValueEnumerator, &args);
}
DataType* AddEntry(const nsAString& aKey) NS_WARN_UNUSED_RESULT
MOZ_WARN_UNUSED_RESULT
DataType* AddEntry(const nsAString& aKey)
{
EntryType* ent = this->PutEntry(aKey, fallible);
if (!ent) {

2
dom/cache/ActorChild.cpp поставляемый
Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/cache/Feature.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
@ -32,6 +33,7 @@ ActorChild::SetFeature(Feature* aFeature)
void
ActorChild::RemoveFeature()
{
MOZ_ASSERT_IF(!NS_IsMainThread(), mFeature);
if (mFeature) {
mFeature->RemoveActor(this);
mFeature = nullptr;

620
dom/cache/AutoUtils.cpp поставляемый
Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/dom/cache/AutoUtils.h"
#include "mozilla/unused.h"
#include "mozilla/dom/cache/CacheParent.h"
#include "mozilla/dom/cache/CachePushStreamChild.h"
#include "mozilla/dom/cache/CacheStreamControlParent.h"
#include "mozilla/dom/cache/ReadStream.h"
@ -21,8 +22,8 @@ namespace {
using mozilla::unused;
using mozilla::dom::cache::CachePushStreamChild;
using mozilla::dom::cache::PCacheReadStream;
using mozilla::dom::cache::PCacheReadStreamOrVoid;
using mozilla::dom::cache::CacheReadStream;
using mozilla::dom::cache::CacheReadStreamOrVoid;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::FileDescriptorSetChild;
using mozilla::ipc::FileDescriptorSetParent;
@ -35,7 +36,7 @@ enum CleanupAction
};
void
CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction)
CleanupChildFds(CacheReadStream& aReadStream, CleanupAction aAction)
{
if (aReadStream.fds().type() !=
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
@ -59,7 +60,7 @@ CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction)
}
void
CleanupChildPushStream(PCacheReadStream& aReadStream, CleanupAction aAction)
CleanupChildPushStream(CacheReadStream& aReadStream, CleanupAction aAction)
{
if (!aReadStream.pushStreamChild()) {
return;
@ -78,24 +79,24 @@ CleanupChildPushStream(PCacheReadStream& aReadStream, CleanupAction aAction)
}
void
CleanupChild(PCacheReadStream& aReadStream, CleanupAction aAction)
CleanupChild(CacheReadStream& aReadStream, CleanupAction aAction)
{
CleanupChildFds(aReadStream, aAction);
CleanupChildPushStream(aReadStream, aAction);
}
void
CleanupChild(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
CleanupChild(CacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
{
if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
return;
}
CleanupChild(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
CleanupChild(aReadStreamOrVoid.get_CacheReadStream(), aAction);
}
void
CleanupParentFds(PCacheReadStream& aReadStream, CleanupAction aAction)
CleanupParentFds(CacheReadStream& aReadStream, CleanupAction aAction)
{
if (aReadStream.fds().type() !=
OptionalFileDescriptorSet::TPFileDescriptorSetParent) {
@ -119,13 +120,13 @@ CleanupParentFds(PCacheReadStream& aReadStream, CleanupAction aAction)
}
void
CleanupParentFds(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
CleanupParentFds(CacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
{
if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
return;
}
CleanupParentFds(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
CleanupParentFds(aReadStreamOrVoid.get_CacheReadStream(), aAction);
}
} // anonymous namespace
@ -136,171 +137,381 @@ namespace cache {
using mozilla::ipc::PBackgroundParent;
AutoChildBase::AutoChildBase(TypeUtils* aTypeUtils)
// --------------------------------------------
AutoChildOpArgs::AutoChildOpArgs(TypeUtils* aTypeUtils,
const CacheOpArgs& aOpArgs)
: mTypeUtils(aTypeUtils)
, mOpArgs(aOpArgs)
, mSent(false)
{
MOZ_ASSERT(mTypeUtils);
}
AutoChildBase::~AutoChildBase()
{
}
// --------------------------------------------
AutoChildRequest::AutoChildRequest(TypeUtils* aTypeUtils)
: AutoChildBase(aTypeUtils)
{
mRequestOrVoid = void_t();
}
AutoChildRequest::~AutoChildRequest()
{
if (mRequestOrVoid.type() != PCacheRequestOrVoid::TPCacheRequest) {
return;
}
CleanupAction action = mSent ? Forget : Delete;
CleanupChild(mRequestOrVoid.get_PCacheRequest().body(), action);
}
void
AutoChildRequest::Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv)
{
MOZ_ASSERT(!mSent);
MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t);
mRequestOrVoid = PCacheRequest();
mTypeUtils->ToPCacheRequest(mRequestOrVoid.get_PCacheRequest(), aRequest,
aBodyAction, aReferrerAction, aSchemeAction, aRv);
}
const PCacheRequest&
AutoChildRequest::SendAsRequest()
{
MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::TPCacheRequest);
return mRequestOrVoid.get_PCacheRequest();
}
const PCacheRequestOrVoid&
AutoChildRequest::SendAsRequestOrVoid()
{
return mRequestOrVoid;
}
// --------------------------------------------
AutoChildRequestList::AutoChildRequestList(TypeUtils* aTypeUtils,
uint32_t aCapacity)
: AutoChildBase(aTypeUtils)
{
mRequestList.SetCapacity(aCapacity);
}
AutoChildRequestList::~AutoChildRequestList()
AutoChildOpArgs::~AutoChildOpArgs()
{
CleanupAction action = mSent ? Forget : Delete;
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
CleanupChild(mRequestList[i].body(), action);
switch(mOpArgs.type()) {
case CacheOpArgs::TCacheMatchArgs:
{
CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
CleanupChild(args.request().body(), action);
break;
}
case CacheOpArgs::TCacheMatchAllArgs:
{
CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
if (args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t) {
break;
}
CleanupChild(args.requestOrVoid().get_CacheRequest().body(), action);
break;
}
case CacheOpArgs::TCacheAddAllArgs:
{
CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
auto& list = args.requestList();
for (uint32_t i = 0; i < list.Length(); ++i) {
CleanupChild(list[i].body(), action);
}
break;
}
case CacheOpArgs::TCachePutAllArgs:
{
CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
auto& list = args.requestResponseList();
for (uint32_t i = 0; i < list.Length(); ++i) {
CleanupChild(list[i].request().body(), action);
CleanupChild(list[i].response().body(), action);
}
break;
}
case CacheOpArgs::TCacheDeleteArgs:
{
CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
CleanupChild(args.request().body(), action);
break;
}
case CacheOpArgs::TCacheKeysArgs:
{
CacheKeysArgs& args = mOpArgs.get_CacheKeysArgs();
if (args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t) {
break;
}
CleanupChild(args.requestOrVoid().get_CacheRequest().body(), action);
break;
}
case CacheOpArgs::TStorageMatchArgs:
{
StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
CleanupChild(args.request().body(), action);
break;
}
default:
// Other types do not need cleanup
break;
}
}
void
AutoChildRequestList::Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv)
AutoChildOpArgs::Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv)
{
MOZ_ASSERT(!mSent);
// The FileDescriptorSetChild asserts in its destructor that all fds have
// been removed. The copy constructor, however, simply duplicates the
// fds without removing any. This means each temporary and copy must be
// explicitly cleaned up.
//
// Avoid a lot of this hassle by making sure we only create one here. On
// error we remove it.
switch(mOpArgs.type()) {
case CacheOpArgs::TCacheMatchArgs:
{
CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
break;
}
case CacheOpArgs::TCacheMatchAllArgs:
{
CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
args.requestOrVoid() = CacheRequest();
mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
aRequest, aBodyAction, aReferrerAction,
aSchemeAction, aRv);
break;
}
case CacheOpArgs::TCacheAddAllArgs:
{
CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
PCacheRequest* request = mRequestList.AppendElement();
mTypeUtils->ToPCacheRequest(*request, aRequest, aBodyAction, aReferrerAction,
aSchemeAction, aRv);
if (aRv.Failed()) {
mRequestList.RemoveElementAt(mRequestList.Length() - 1);
// The FileDescriptorSetChild asserts in its destructor that all fds have
// been removed. The copy constructor, however, simply duplicates the
// fds without removing any. This means each temporary and copy must be
// explicitly cleaned up.
//
// Avoid a lot of this hassle by making sure we only create one here. On
// error we remove it.
CacheRequest& request = *args.requestList().AppendElement();
mTypeUtils->ToCacheRequest(request, aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
if (aRv.Failed()) {
args.requestList().RemoveElementAt(args.requestList().Length() - 1);
}
break;
}
case CacheOpArgs::TCacheDeleteArgs:
{
CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
break;
}
case CacheOpArgs::TCacheKeysArgs:
{
CacheKeysArgs& args = mOpArgs.get_CacheKeysArgs();
MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
args.requestOrVoid() = CacheRequest();
mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
aRequest, aBodyAction, aReferrerAction,
aSchemeAction, aRv);
break;
}
case CacheOpArgs::TStorageMatchArgs:
{
StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
break;
}
default:
MOZ_CRASH("Cache args type cannot send a Request!");
}
}
const nsTArray<PCacheRequest>&
AutoChildRequestList::SendAsRequestList()
void
AutoChildOpArgs::Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
Response& aResponse, ErrorResult& aRv)
{
MOZ_ASSERT(!mSent);
switch(mOpArgs.type()) {
case CacheOpArgs::TCachePutAllArgs:
{
CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
// The FileDescriptorSetChild asserts in its destructor that all fds have
// been removed. The copy constructor, however, simply duplicates the
// fds without removing any. This means each temporary and copy must be
// explicitly cleaned up.
//
// Avoid a lot of this hassle by making sure we only create one here. On
// error we remove it.
CacheRequestResponse& pair = *args.requestResponseList().AppendElement();
pair.request().body() = void_t();
pair.response().body() = void_t();
mTypeUtils->ToCacheRequest(pair.request(), aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
if (!aRv.Failed()) {
mTypeUtils->ToCacheResponse(pair.response(), aResponse, aRv);
}
if (aRv.Failed()) {
CleanupChild(pair.request().body(), Delete);
args.requestResponseList().RemoveElementAt(
args.requestResponseList().Length() - 1);
}
break;
}
default:
MOZ_CRASH("Cache args type cannot send a Request/Response pair!");
}
}
const CacheOpArgs&
AutoChildOpArgs::SendAsOpArgs()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mRequestList;
return mOpArgs;
}
// --------------------------------------------
AutoChildRequestResponse::AutoChildRequestResponse(TypeUtils* aTypeUtils)
: AutoChildBase(aTypeUtils)
{
// Default IPC-generated constructor does not initialize these correctly
// and we check them later when cleaning up.
mRequestResponse.request().body() = void_t();
mRequestResponse.response().body() = void_t();
}
AutoChildRequestResponse::~AutoChildRequestResponse()
{
CleanupAction action = mSent ? Forget : Delete;
CleanupChild(mRequestResponse.request().body(), action);
CleanupChild(mRequestResponse.response().body(), action);
}
void
AutoChildRequestResponse::Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv)
{
MOZ_ASSERT(!mSent);
mTypeUtils->ToPCacheRequest(mRequestResponse.request(), aRequest, aBodyAction,
aReferrerAction, aSchemeAction, aRv);
}
void
AutoChildRequestResponse::Add(Response& aResponse, ErrorResult& aRv)
{
MOZ_ASSERT(!mSent);
mTypeUtils->ToPCacheResponse(mRequestResponse.response(), aResponse, aRv);
}
const CacheRequestResponse&
AutoChildRequestResponse::SendAsRequestResponse()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mRequestResponse;
}
// --------------------------------------------
AutoParentBase::AutoParentBase(PBackgroundParent* aManager)
AutoParentOpResult::AutoParentOpResult(mozilla::ipc::PBackgroundParent* aManager,
const CacheOpResult& aOpResult)
: mManager(aManager)
, mOpResult(aOpResult)
, mStreamControl(nullptr)
, mSent(false)
{
MOZ_ASSERT(mManager);
}
AutoParentBase::~AutoParentBase()
AutoParentOpResult::~AutoParentOpResult()
{
if (!mSent && mStreamControl) {
CleanupAction action = mSent ? Forget : Delete;
switch (mOpResult.type()) {
case CacheOpResult::TCacheMatchResult:
{
CacheMatchResult& result = mOpResult.get_CacheMatchResult();
if (result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t) {
break;
}
CleanupParentFds(result.responseOrVoid().get_CacheResponse().body(),
action);
break;
}
case CacheOpResult::TCacheMatchAllResult:
{
CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
for (uint32_t i = 0; i < result.responseList().Length(); ++i) {
CleanupParentFds(result.responseList()[i].body(), action);
}
break;
}
case CacheOpResult::TCacheKeysResult:
{
CacheKeysResult& result = mOpResult.get_CacheKeysResult();
for (uint32_t i = 0; i < result.requestList().Length(); ++i) {
CleanupParentFds(result.requestList()[i].body(), action);
}
break;
}
case CacheOpResult::TStorageMatchResult:
{
StorageMatchResult& result = mOpResult.get_StorageMatchResult();
if (result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t) {
break;
}
CleanupParentFds(result.responseOrVoid().get_CacheResponse().body(),
action);
break;
}
case CacheOpResult::TStorageOpenResult:
{
StorageOpenResult& result = mOpResult.get_StorageOpenResult();
if (action == Forget || result.actorParent() == nullptr) {
break;
}
unused << PCacheParent::Send__delete__(result.actorParent());
}
default:
// other types do not need clean up
break;
}
if (action == Delete && mStreamControl) {
unused << PCacheStreamControlParent::Send__delete__(mStreamControl);
}
}
void
AutoParentBase::SerializeReadStream(const nsID& aId, StreamList* aStreamList,
PCacheReadStream* aReadStreamOut)
AutoParentOpResult::Add(CacheId aOpenedCacheId, Manager* aManager)
{
MOZ_ASSERT(mOpResult.type() == CacheOpResult::TStorageOpenResult);
MOZ_ASSERT(mOpResult.get_StorageOpenResult().actorParent() == nullptr);
mOpResult.get_StorageOpenResult().actorParent() =
mManager->SendPCacheConstructor(new CacheParent(aManager, aOpenedCacheId));
}
void
AutoParentOpResult::Add(const SavedResponse& aSavedResponse,
StreamList* aStreamList)
{
MOZ_ASSERT(!mSent);
switch (mOpResult.type()) {
case CacheOpResult::TCacheMatchResult:
{
CacheMatchResult& result = mOpResult.get_CacheMatchResult();
MOZ_ASSERT(result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t);
result.responseOrVoid() = aSavedResponse.mValue;
SerializeResponseBody(aSavedResponse, aStreamList,
&result.responseOrVoid().get_CacheResponse());
break;
}
case CacheOpResult::TCacheMatchAllResult:
{
CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
result.responseList().AppendElement(aSavedResponse.mValue);
SerializeResponseBody(aSavedResponse, aStreamList,
&result.responseList().LastElement());
break;
}
case CacheOpResult::TStorageMatchResult:
{
StorageMatchResult& result = mOpResult.get_StorageMatchResult();
MOZ_ASSERT(result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t);
result.responseOrVoid() = aSavedResponse.mValue;
SerializeResponseBody(aSavedResponse, aStreamList,
&result.responseOrVoid().get_CacheResponse());
break;
}
default:
MOZ_CRASH("Cache result type cannot handle returning a Response!");
}
}
void
AutoParentOpResult::Add(const SavedRequest& aSavedRequest,
StreamList* aStreamList)
{
MOZ_ASSERT(!mSent);
switch (mOpResult.type()) {
case CacheOpResult::TCacheKeysResult:
{
CacheKeysResult& result = mOpResult.get_CacheKeysResult();
result.requestList().AppendElement(aSavedRequest.mValue);
CacheRequest& request = result.requestList().LastElement();
if (!aSavedRequest.mHasBodyId) {
request.body() = void_t();
break;
}
request.body() = CacheReadStream();
SerializeReadStream(aSavedRequest.mBodyId, aStreamList,
&request.body().get_CacheReadStream());
break;
}
default:
MOZ_CRASH("Cache result type cannot handle returning a Request!");
}
}
const CacheOpResult&
AutoParentOpResult::SendAsOpResult()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mOpResult;
}
void
AutoParentOpResult::SerializeResponseBody(const SavedResponse& aSavedResponse,
StreamList* aStreamList,
CacheResponse* aResponseOut)
{
MOZ_ASSERT(aResponseOut);
if (!aSavedResponse.mHasBodyId) {
aResponseOut->body() = void_t();
return;
}
aResponseOut->body() = CacheReadStream();
SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
&aResponseOut->body().get_CacheReadStream());
}
void
AutoParentOpResult::SerializeReadStream(const nsID& aId, StreamList* aStreamList,
CacheReadStream* aReadStreamOut)
{
MOZ_ASSERT(aStreamList);
MOZ_ASSERT(aReadStreamOut);
@ -328,139 +539,6 @@ AutoParentBase::SerializeReadStream(const nsID& aId, StreamList* aStreamList,
readStream->Serialize(aReadStreamOut);
}
// --------------------------------------------
AutoParentRequestList::AutoParentRequestList(PBackgroundParent* aManager,
uint32_t aCapacity)
: AutoParentBase(aManager)
{
mRequestList.SetCapacity(aCapacity);
}
AutoParentRequestList::~AutoParentRequestList()
{
CleanupAction action = mSent ? Forget : Delete;
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
CleanupParentFds(mRequestList[i].body(), action);
}
}
void
AutoParentRequestList::Add(const SavedRequest& aSavedRequest,
StreamList* aStreamList)
{
MOZ_ASSERT(!mSent);
mRequestList.AppendElement(aSavedRequest.mValue);
PCacheRequest& request = mRequestList.LastElement();
if (!aSavedRequest.mHasBodyId) {
request.body() = void_t();
return;
}
request.body() = PCacheReadStream();
SerializeReadStream(aSavedRequest.mBodyId, aStreamList,
&request.body().get_PCacheReadStream());
}
const nsTArray<PCacheRequest>&
AutoParentRequestList::SendAsRequestList()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mRequestList;
}
// --------------------------------------------
AutoParentResponseList::AutoParentResponseList(PBackgroundParent* aManager,
uint32_t aCapacity)
: AutoParentBase(aManager)
{
mResponseList.SetCapacity(aCapacity);
}
AutoParentResponseList::~AutoParentResponseList()
{
CleanupAction action = mSent ? Forget : Delete;
for (uint32_t i = 0; i < mResponseList.Length(); ++i) {
CleanupParentFds(mResponseList[i].body(), action);
}
}
void
AutoParentResponseList::Add(const SavedResponse& aSavedResponse,
StreamList* aStreamList)
{
MOZ_ASSERT(!mSent);
mResponseList.AppendElement(aSavedResponse.mValue);
PCacheResponse& response = mResponseList.LastElement();
if (!aSavedResponse.mHasBodyId) {
response.body() = void_t();
return;
}
response.body() = PCacheReadStream();
SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
&response.body().get_PCacheReadStream());
}
const nsTArray<PCacheResponse>&
AutoParentResponseList::SendAsResponseList()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mResponseList;
}
// --------------------------------------------
AutoParentResponseOrVoid::AutoParentResponseOrVoid(ipc::PBackgroundParent* aManager)
: AutoParentBase(aManager)
{
mResponseOrVoid = void_t();
}
AutoParentResponseOrVoid::~AutoParentResponseOrVoid()
{
if (mResponseOrVoid.type() != PCacheResponseOrVoid::TPCacheResponse) {
return;
}
CleanupAction action = mSent ? Forget : Delete;
CleanupParentFds(mResponseOrVoid.get_PCacheResponse().body(), action);
}
void
AutoParentResponseOrVoid::Add(const SavedResponse& aSavedResponse,
StreamList* aStreamList)
{
MOZ_ASSERT(!mSent);
mResponseOrVoid = aSavedResponse.mValue;
PCacheResponse& response = mResponseOrVoid.get_PCacheResponse();
if (!aSavedResponse.mHasBodyId) {
response.body() = void_t();
return;
}
response.body() = PCacheReadStream();
SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
&response.body().get_PCacheReadStream());
}
const PCacheResponseOrVoid&
AutoParentResponseOrVoid::SendAsResponseOrVoid()
{
MOZ_ASSERT(!mSent);
mSent = true;
return mResponseOrVoid;
}
} // namespace cache
} // namespace dom
} // namespace mozilla

139
dom/cache/AutoUtils.h поставляемый
Просмотреть файл

@ -8,7 +8,8 @@
#define mozilla_dom_cache_AutoUtils_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsTArray.h"
@ -29,6 +30,7 @@ class InternalRequest;
namespace cache {
class CacheStreamControlParent;
class Manager;
struct SavedRequest;
struct SavedResponse;
class StreamList;
@ -41,129 +43,56 @@ class StreamList;
// Note, these should only be used when *sending* streams across IPC. The
// deserialization case is handled by creating a ReadStream object.
class MOZ_STACK_CLASS AutoChildBase
class MOZ_STACK_CLASS AutoChildOpArgs final
{
protected:
public:
typedef TypeUtils::BodyAction BodyAction;
typedef TypeUtils::ReferrerAction ReferrerAction;
typedef TypeUtils::SchemeAction SchemeAction;
AutoChildBase(TypeUtils* aTypeUtils);
virtual ~AutoChildBase() = 0;
AutoChildOpArgs(TypeUtils* aTypeUtils, const CacheOpArgs& aOpArgs);
~AutoChildOpArgs();
void Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv);
void Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
Response& aResponse, ErrorResult& aRv);
const CacheOpArgs& SendAsOpArgs();
private:
TypeUtils* mTypeUtils;
CacheOpArgs mOpArgs;
bool mSent;
};
class MOZ_STACK_CLASS AutoChildRequest final : public AutoChildBase
class MOZ_STACK_CLASS AutoParentOpResult final
{
public:
explicit AutoChildRequest(TypeUtils* aTypeUtils);
~AutoChildRequest();
void Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv);
const PCacheRequest& SendAsRequest();
const PCacheRequestOrVoid& SendAsRequestOrVoid();
private:
PCacheRequestOrVoid mRequestOrVoid;
};
class MOZ_STACK_CLASS AutoChildRequestList final : public AutoChildBase
{
public:
AutoChildRequestList(TypeUtils* aTypeUtils, uint32_t aCapacity);
~AutoChildRequestList();
void Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv);
const nsTArray<PCacheRequest>& SendAsRequestList();
private:
// Allocates ~5k inline in the stack-only class
nsAutoTArray<PCacheRequest, 32> mRequestList;
};
class MOZ_STACK_CLASS AutoChildRequestResponse final : public AutoChildBase
{
public:
explicit AutoChildRequestResponse(TypeUtils* aTypeUtils);
~AutoChildRequestResponse();
void Add(InternalRequest* aRequest, BodyAction aBodyAction,
ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
ErrorResult& aRv);
void Add(Response& aResponse, ErrorResult& aRv);
const CacheRequestResponse& SendAsRequestResponse();
private:
CacheRequestResponse mRequestResponse;
};
class MOZ_STACK_CLASS AutoParentBase
{
protected:
explicit AutoParentBase(mozilla::ipc::PBackgroundParent* aManager);
virtual ~AutoParentBase() = 0;
void SerializeReadStream(const nsID& aId, StreamList* aStreamList,
PCacheReadStream* aReadStreamOut);
mozilla::ipc::PBackgroundParent* mManager;
CacheStreamControlParent* mStreamControl;
bool mSent;
};
class MOZ_STACK_CLASS AutoParentRequestList final : public AutoParentBase
{
public:
AutoParentRequestList(mozilla::ipc::PBackgroundParent* aManager,
uint32_t aCapacity);
~AutoParentRequestList();
AutoParentOpResult(mozilla::ipc::PBackgroundParent* aManager,
const CacheOpResult& aOpResult);
~AutoParentOpResult();
void Add(CacheId aOpenedCacheId, Manager* aManager);
void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
void Add(const SavedRequest& aSavedRequest, StreamList* aStreamList);
const nsTArray<PCacheRequest>& SendAsRequestList();
const CacheOpResult& SendAsOpResult();
private:
// Allocates ~5k inline in the stack-only class
nsAutoTArray<PCacheRequest, 32> mRequestList;
};
void SerializeResponseBody(const SavedResponse& aSavedResponse,
StreamList* aStreamList,
CacheResponse* aResponseOut);
class MOZ_STACK_CLASS AutoParentResponseList final : public AutoParentBase
{
public:
AutoParentResponseList(mozilla::ipc::PBackgroundParent* aManager,
uint32_t aCapacity);
~AutoParentResponseList();
void SerializeReadStream(const nsID& aId, StreamList* aStreamList,
CacheReadStream* aReadStreamOut);
void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
const nsTArray<PCacheResponse>& SendAsResponseList();
private:
// Allocates ~4k inline in the stack-only class
nsAutoTArray<PCacheResponse, 32> mResponseList;
};
class MOZ_STACK_CLASS AutoParentResponseOrVoid final : public AutoParentBase
{
public:
explicit AutoParentResponseOrVoid(mozilla::ipc::PBackgroundParent* aManager);
~AutoParentResponseOrVoid();
void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
const PCacheResponseOrVoid& SendAsResponseOrVoid();
private:
PCacheResponseOrVoid mResponseOrVoid;
mozilla::ipc::PBackgroundParent* mManager;
CacheOpResult mOpResult;
CacheStreamControlParent* mStreamControl;
bool mSent;
};
} // namespace cache

344
dom/cache/Cache.cpp поставляемый
Просмотреть файл

@ -16,7 +16,6 @@
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CachePushStreamChild.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
@ -79,17 +78,7 @@ using mozilla::dom::workers::WorkerPrivate;
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::Cache);
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::Cache);
NS_IMPL_CYCLE_COLLECTION_CLASS(mozilla::dom::cache::Cache)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(mozilla::dom::cache::Cache)
tmp->DisconnectFromActor();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal, mRequestPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(mozilla::dom::cache::Cache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal, mRequestPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(mozilla::dom::cache::Cache)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::Cache, mGlobal);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Cache)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@ -111,31 +100,22 @@ Cache::Match(const RequestOrUSVString& aRequest,
{
MOZ_ASSERT(mActor);
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
if (aRv.Failed()) {
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
AutoChildRequest request(this);
CacheQueryParams params;
ToCacheQueryParams(params, aOptions);
request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
if (aRv.Failed()) {
AutoChildOpArgs args(this, CacheMatchArgs(CacheRequest(), params));
args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
PCacheQueryParams params;
ToPCacheQueryParams(params, aOptions);
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendMatch(requestId, request.SendAsRequest(), params);
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -144,12 +124,10 @@ Cache::MatchAll(const Optional<RequestOrUSVString>& aRequest,
{
MOZ_ASSERT(mActor);
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
CacheQueryParams params;
ToCacheQueryParams(params, aOptions);
AutoChildRequest request(this);
AutoChildOpArgs args(this, CacheMatchAllArgs(void_t(), params));
if (aRequest.WasPassed()) {
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
@ -158,21 +136,13 @@ Cache::MatchAll(const Optional<RequestOrUSVString>& aRequest,
return nullptr;
}
request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
PCacheQueryParams params;
ToPCacheQueryParams(params, aOptions);
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendMatchAll(requestId, request.SendAsRequestOrVoid(),
params);
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -184,27 +154,19 @@ Cache::Add(const RequestOrUSVString& aRequest, ErrorResult& aRv)
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, ReadBody, aRv);
if (aRv.Failed()) {
return nullptr;
}
AutoChildRequestList requests(this, 1);
requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
AutoChildOpArgs args(this, CacheAddAllArgs());
args.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
if (aRv.Failed()) {
return nullptr;
}
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendAddAll(requestId, requests.SendAsRequestList());
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -213,18 +175,18 @@ Cache::AddAll(const Sequence<OwningRequestOrUSVString>& aRequests,
{
MOZ_ASSERT(mActor);
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
// If there is no work to do, then resolve immediately
if (aRequests.IsEmpty()) {
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
AutoChildRequestList requests(this, aRequests.Length());
AutoChildOpArgs args(this, CacheAddAllArgs());
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
if (!IsValidPutRequestMethod(aRequests[i], aRv)) {
@ -237,18 +199,13 @@ Cache::AddAll(const Sequence<OwningRequestOrUSVString>& aRequests,
return nullptr;
}
requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme,
aRv);
args.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendAddAll(requestId, requests.SendAsRequestList());
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -261,32 +218,20 @@ Cache::Put(const RequestOrUSVString& aRequest, Response& aResponse,
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, ReadBody, aRv);
if (aRv.Failed()) {
return nullptr;
}
AutoChildRequestResponse put(this);
put.Add(ir, ReadBody, PassThroughReferrer, TypeErrorOnInvalidScheme, aRv);
AutoChildOpArgs args(this, CachePutAllArgs());
args.Add(ir, ReadBody, PassThroughReferrer, TypeErrorOnInvalidScheme,
aResponse, aRv);
if (aRv.Failed()) {
return nullptr;
}
put.Add(aResponse, aRv);
if (aRv.Failed()) {
return nullptr;
}
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendPut(requestId, put.SendAsRequestResponse());
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -295,30 +240,22 @@ Cache::Delete(const RequestOrUSVString& aRequest,
{
MOZ_ASSERT(mActor);
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
if (aRv.Failed()) {
return nullptr;
}
AutoChildRequest request(this);
request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
CacheQueryParams params;
ToCacheQueryParams(params, aOptions);
AutoChildOpArgs args(this, CacheDeleteArgs(CacheRequest(), params));
args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
if (aRv.Failed()) {
return nullptr;
}
PCacheQueryParams params;
ToPCacheQueryParams(params, aOptions);
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendDelete(requestId, request.SendAsRequest(), params);
return promise.forget();
return ExecuteOp(args, aRv);
}
already_AddRefed<Promise>
@ -327,12 +264,10 @@ Cache::Keys(const Optional<RequestOrUSVString>& aRequest,
{
MOZ_ASSERT(mActor);
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
CacheQueryParams params;
ToCacheQueryParams(params, aOptions);
AutoChildRequest request(this);
AutoChildOpArgs args(this, CacheKeysArgs(void_t(), params));
if (aRequest.WasPassed()) {
nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
@ -341,20 +276,13 @@ Cache::Keys(const Optional<RequestOrUSVString>& aRequest,
return nullptr;
}
request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
PCacheQueryParams params;
ToPCacheQueryParams(params, aOptions);
RequestId requestId = AddRequestPromise(promise, aRv);
unused << mActor->SendKeys(requestId, request.SendAsRequestOrVoid(), params);
return promise.forget();
return ExecuteOp(args, aRv);
}
// static
@ -401,123 +329,6 @@ Cache::DestroyInternal(CacheChild* aActor)
mActor = nullptr;
}
void
Cache::RecvMatchResponse(RequestId aRequestId, nsresult aRv,
const PCacheResponseOrVoid& aResponse)
{
// Convert the response immediately if its present. This ensures that
// any stream actors are cleaned up, even if we error out below.
nsRefPtr<Response> response;
if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) {
response = ToResponse(aResponse);
}
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
if (!response) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return;
}
promise->MaybeResolve(response);
}
void
Cache::RecvMatchAllResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<PCacheResponse>& aResponses)
{
// Convert responses immediately. This ensures that any stream actors are
// cleaned up, even if we error out below.
nsAutoTArray<nsRefPtr<Response>, 256> responses;
responses.SetCapacity(aResponses.Length());
for (uint32_t i = 0; i < aResponses.Length(); ++i) {
nsRefPtr<Response> response = ToResponse(aResponses[i]);
responses.AppendElement(response.forget());
}
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(responses);
}
void
Cache::RecvAddAllResponse(RequestId aRequestId,
const mozilla::ErrorResult& aError)
{
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (aError.Failed()) {
// TODO: Remove this const_cast (bug 1152078).
// It is safe for now since this ErrorResult is handed off to us by IPDL
// and is thrown into the trash afterwards.
promise->MaybeReject(const_cast<ErrorResult&>(aError));
return;
}
promise->MaybeResolve(JS::UndefinedHandleValue);
}
void
Cache::RecvPutResponse(RequestId aRequestId, nsresult aRv)
{
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(JS::UndefinedHandleValue);
}
void
Cache::RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess)
{
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(aSuccess);
}
void
Cache::RecvKeysResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<PCacheRequest>& aRequests)
{
// Convert requests immediately. This ensures that any stream actors are
// cleaned up, even if we error out below.
nsAutoTArray<nsRefPtr<Request>, 256> requests;
requests.SetCapacity(aRequests.Length());
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
nsRefPtr<Request> request = ToRequest(aRequests[i]);
requests.AppendElement(request.forget());
}
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(requests);
}
nsIGlobalObject*
Cache::GetGlobalObject() const
{
@ -538,36 +349,12 @@ Cache::CreatePushStream(nsIAsyncInputStream* aStream)
NS_ASSERT_OWNINGTHREAD(Cache);
MOZ_ASSERT(mActor);
MOZ_ASSERT(aStream);
auto actor = mActor->SendPCachePushStreamConstructor(
new CachePushStreamChild(mActor->GetFeature(), aStream));
MOZ_ASSERT(actor);
return static_cast<CachePushStreamChild*>(actor);
}
void
Cache::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
// Do nothing. The Promise will automatically drop the ref to us after
// calling the callback. This is what we want as we only registered in order
// to be held alive via the Promise handle.
}
void
Cache::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
// Do nothing. The Promise will automatically drop the ref to us after
// calling the callback. This is what we want as we only registered in order
// to be held alive via the Promise handle.
return mActor->CreatePushStream(aStream);
}
Cache::~Cache()
{
DisconnectFromActor();
}
void
Cache::DisconnectFromActor()
{
NS_ASSERT_OWNINGTHREAD(Cache);
if (mActor) {
mActor->StartDestroy();
// DestroyInternal() is called synchronously by StartDestroy(). So we
@ -576,43 +363,16 @@ Cache::DisconnectFromActor()
}
}
RequestId
Cache::AddRequestPromise(Promise* aPromise, ErrorResult& aRv)
{
MOZ_ASSERT(aPromise);
MOZ_ASSERT(!mRequestPromises.Contains(aPromise));
// Register ourself as a promise handler so that the promise will hold us
// alive. This allows the client code to drop the ref to the Cache
// object and just keep their promise. This is fairly common in promise
// chaining code.
aPromise->AppendNativeHandler(this);
mRequestPromises.AppendElement(aPromise);
// (Ab)use the promise pointer as our request ID. This is a fast, thread-safe
// way to get a unique ID for the promise to be resolved later.
return reinterpret_cast<RequestId>(aPromise);
}
already_AddRefed<Promise>
Cache::RemoveRequestPromise(RequestId aRequestId)
Cache::ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv)
{
MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID);
for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) {
nsRefPtr<Promise>& promise = mRequestPromises.ElementAt(i);
// To be safe, only cast promise pointers to our integer RequestId
// type and never cast an integer to a pointer.
if (aRequestId == reinterpret_cast<RequestId>(promise.get())) {
nsRefPtr<Promise> ref;
ref.swap(promise);
mRequestPromises.RemoveElementAt(i);
return ref.forget();
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!");
return nullptr;
mActor->ExecuteOp(mGlobal, promise, aOpArgs.SendAsOpArgs());
return promise.forget();
}
} // namespace cache

34
dom/cache/Cache.h поставляемый
Просмотреть файл

@ -7,7 +7,6 @@
#ifndef mozilla_dom_cache_Cache_h
#define mozilla_dom_cache_Cache_h
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsCOMPtr.h"
@ -33,12 +32,10 @@ template<typename T> class Sequence;
namespace cache {
class AutoChildOpArgs;
class CacheChild;
class PCacheRequest;
class PCacheResponse;
class PCacheResponseOrVoid;
class Cache final : public PromiseNativeHandler
class Cache final : public nsISupports
, public nsWrapperCache
, public TypeUtils
{
@ -76,20 +73,6 @@ public:
// Called when CacheChild actor is being destroyed
void DestroyInternal(CacheChild* aActor);
// methods forwarded from CacheChild
void RecvMatchResponse(RequestId aRequestId, nsresult aRv,
const PCacheResponseOrVoid& aResponse);
void RecvMatchAllResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<PCacheResponse>& aResponses);
void RecvAddAllResponse(RequestId aRequestId,
const mozilla::ErrorResult& aError);
void RecvPutResponse(RequestId aRequestId, nsresult aRv);
void RecvDeleteResponse(RequestId aRequestId, nsresult aRv,
bool aSuccess);
void RecvKeysResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<PCacheRequest>& aRequests);
// TypeUtils methods
virtual nsIGlobalObject*
GetGlobalObject() const override;
@ -101,26 +84,17 @@ public:
virtual CachePushStreamChild*
CreatePushStream(nsIAsyncInputStream* aStream) override;
// PromiseNativeHandler methods
virtual void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
virtual void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
private:
~Cache();
// Called when we're destroyed or CCed.
void DisconnectFromActor();
// TODO: Replace with actor-per-request model during refactor (bug 1110485)
RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv);
already_AddRefed<Promise> RemoveRequestPromise(RequestId aRequestId);
already_AddRefed<Promise>
ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv);
nsCOMPtr<nsIGlobalObject> mGlobal;
CacheChild* mActor;
nsTArray<nsRefPtr<Promise>> mRequestPromises;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS

139
dom/cache/CacheChild.cpp поставляемый
Просмотреть файл

@ -9,8 +9,8 @@
#include "mozilla/unused.h"
#include "mozilla/dom/cache/ActorUtils.h"
#include "mozilla/dom/cache/Cache.h"
#include "mozilla/dom/cache/PCachePushStreamChild.h"
#include "mozilla/dom/cache/StreamUtils.h"
#include "mozilla/dom/cache/CacheOpChild.h"
#include "mozilla/dom/cache/CachePushStreamChild.h"
namespace mozilla {
namespace dom {
@ -32,6 +32,7 @@ DeallocPCacheChild(PCacheChild* aActor)
CacheChild::CacheChild()
: mListener(nullptr)
, mNumChildActors(0)
{
MOZ_COUNT_CTOR(cache::CacheChild);
}
@ -41,6 +42,7 @@ CacheChild::~CacheChild()
MOZ_COUNT_DTOR(cache::CacheChild);
NS_ASSERT_OWNINGTHREAD(CacheChild);
MOZ_ASSERT(!mListener);
MOZ_ASSERT(!mNumChildActors);
}
void
@ -60,6 +62,25 @@ CacheChild::ClearListener()
mListener = nullptr;
}
void
CacheChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
const CacheOpArgs& aArgs)
{
mNumChildActors += 1;
MOZ_ALWAYS_TRUE(SendPCacheOpConstructor(
new CacheOpChild(GetFeature(), aGlobal, aPromise), aArgs));
}
CachePushStreamChild*
CacheChild::CreatePushStream(nsIAsyncInputStream* aStream)
{
mNumChildActors += 1;
auto actor = SendPCachePushStreamConstructor(
new CachePushStreamChild(GetFeature(), aStream));
MOZ_ASSERT(actor);
return static_cast<CachePushStreamChild*>(actor);
}
void
CacheChild::StartDestroy()
{
@ -77,6 +98,14 @@ CacheChild::StartDestroy()
// Cache listener should call ClearListener() in DestroyInternal()
MOZ_ASSERT(!mListener);
// If we have outstanding child actors, then don't destroy ourself yet.
// The child actors should be short lived and we should allow them to complete
// if possible. SendTeardown() will be called when the count drops to zero
// in NoteDeletedActor().
if (mNumChildActors) {
return;
}
// Start actor destruction from parent process
unused << SendTeardown();
}
@ -95,6 +124,21 @@ CacheChild::ActorDestroy(ActorDestroyReason aReason)
RemoveFeature();
}
PCacheOpChild*
CacheChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs)
{
MOZ_CRASH("CacheOpChild should be manually constructed.");
return nullptr;
}
bool
CacheChild::DeallocPCacheOpChild(PCacheOpChild* aActor)
{
delete aActor;
NoteDeletedActor();
return true;
}
PCachePushStreamChild*
CacheChild::AllocPCachePushStreamChild()
{
@ -106,96 +150,17 @@ bool
CacheChild::DeallocPCachePushStreamChild(PCachePushStreamChild* aActor)
{
delete aActor;
NoteDeletedActor();
return true;
}
bool
CacheChild::RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
const PCacheResponseOrVoid& aResponse)
void
CacheChild::NoteDeletedActor()
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
AddFeatureToStreamChild(aResponse, GetFeature());
nsRefPtr<Cache> listener = mListener;
if (!listener) {
StartDestroyStreamChild(aResponse);
return true;
mNumChildActors -= 1;
if (!mNumChildActors && !mListener) {
unused << SendTeardown();
}
listener->RecvMatchResponse(requestId, aRv, aResponse);
return true;
}
bool
CacheChild::RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv,
nsTArray<PCacheResponse>&& aResponses)
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
AddFeatureToStreamChild(aResponses, GetFeature());
nsRefPtr<Cache> listener = mListener;
if (!listener) {
StartDestroyStreamChild(aResponses);
return true;
}
listener->RecvMatchAllResponse(requestId, aRv, aResponses);
return true;
}
bool
CacheChild::RecvAddAllResponse(const RequestId& requestId,
const mozilla::ErrorResult& aError)
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
nsRefPtr<Cache> listener = mListener;
if (listener) {
listener->RecvAddAllResponse(requestId, aError);
}
return true;
}
bool
CacheChild::RecvPutResponse(const RequestId& aRequestId, const nsresult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
nsRefPtr<Cache> listener = mListener;
if (listener) {
listener->RecvPutResponse(aRequestId, aRv);
}
return true;
}
bool
CacheChild::RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv,
const bool& result)
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
nsRefPtr<Cache> listener = mListener;
if (listener) {
listener->RecvDeleteResponse(requestId, aRv, result);
}
return true;
}
bool
CacheChild::RecvKeysResponse(const RequestId& requestId, const nsresult& aRv,
nsTArray<PCacheRequest>&& aRequests)
{
NS_ASSERT_OWNINGTHREAD(CacheChild);
AddFeatureToStreamChild(aRequests, GetFeature());
nsRefPtr<Cache> listener = mListener;
if (!listener) {
StartDestroyStreamChild(aRequests);
return true;
}
listener->RecvKeysResponse(requestId, aRv, aRequests);
return true;
}
} // namespace cache

43
dom/cache/CacheChild.h поставляемый
Просмотреть файл

@ -10,11 +10,19 @@
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/cache/PCacheChild.h"
class nsIAsyncInputStream;
class nsIGlobalObject;
namespace mozilla {
namespace dom {
class Promise;
namespace cache {
class Cache;
class CacheOpArgs;
class CachePushStreamChild;
class CacheChild final : public PCacheChild
, public ActorChild
@ -30,6 +38,13 @@ public:
// trigger ActorDestroy() if it has not been called yet.
void ClearListener();
void
ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
const CacheOpArgs& aArgs);
CachePushStreamChild*
CreatePushStream(nsIAsyncInputStream* aStream);
// ActorChild methods
// Synchronously call ActorDestroy on our Cache listener and then start the
@ -41,35 +56,27 @@ private:
virtual void
ActorDestroy(ActorDestroyReason aReason) override;
virtual PCacheOpChild*
AllocPCacheOpChild(const CacheOpArgs& aOpArgs) override;
virtual bool
DeallocPCacheOpChild(PCacheOpChild* aActor) override;
virtual PCachePushStreamChild*
AllocPCachePushStreamChild() override;
virtual bool
DeallocPCachePushStreamChild(PCachePushStreamChild* aActor) override;
virtual bool
RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
const PCacheResponseOrVoid& aResponse) override;
virtual bool
RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv,
nsTArray<PCacheResponse>&& responses) override;
virtual bool
RecvAddAllResponse(const RequestId& requestId,
const mozilla::ErrorResult& aError) override;
virtual bool
RecvPutResponse(const RequestId& aRequestId,
const nsresult& aRv) override;
virtual bool
RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv,
const bool& result) override;
virtual bool
RecvKeysResponse(const RequestId& requestId, const nsresult& aRv,
nsTArray<PCacheRequest>&& requests) override;
// utility methods
void
NoteDeletedActor();
// Use a weak ref so actor does not hold DOM object alive past content use.
// The Cache object must call ClearListener() to null this before its
// destroyed.
Cache* MOZ_NON_OWNING_REF mListener;
uint32_t mNumChildActors;
NS_DECL_OWNINGTHREAD
};

24
dom/cache/CacheInitData.ipdlh поставляемый
Просмотреть файл

@ -1,24 +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/. */
include PBackgroundSharedTypes;
using mozilla::dom::cache::Namespace from "mozilla/dom/cache/Types.h";
namespace mozilla {
namespace dom {
namespace cache {
// Data needed to initialize a CacheStorage or Cache backend. Don't put
// this with the other types in PCacheTypes.ipdlh since we want to import
// it into PBackground.ipdl.
struct CacheInitData
{
Namespace namespaceEnum;
PrincipalInfo principalInfo;
};
} // namespace cache
} // namespace dom
} // namespace mozilla

248
dom/cache/CacheOpChild.cpp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,248 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/cache/CacheOpChild.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Request.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/cache/Cache.h"
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CacheStreamControlChild.h"
namespace mozilla {
namespace dom {
namespace cache {
namespace {
void
AddFeatureToStreamChild(const CacheReadStream& aReadStream, Feature* aFeature)
{
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
CacheStreamControlChild* cacheControl =
static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
if (cacheControl) {
cacheControl->SetFeature(aFeature);
}
}
void
AddFeatureToStreamChild(const CacheResponse& aResponse, Feature* aFeature)
{
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
if (aResponse.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
return;
}
AddFeatureToStreamChild(aResponse.body().get_CacheReadStream(), aFeature);
}
void
AddFeatureToStreamChild(const CacheRequest& aRequest, Feature* aFeature)
{
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
if (aRequest.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
return;
}
AddFeatureToStreamChild(aRequest.body().get_CacheReadStream(), aFeature);
}
} // anonymous namespace
CacheOpChild::CacheOpChild(Feature* aFeature, nsIGlobalObject* aGlobal,
Promise* aPromise)
: mGlobal(aGlobal)
, mPromise(aPromise)
{
MOZ_ASSERT(mGlobal);
MOZ_ASSERT(mPromise);
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
SetFeature(aFeature);
}
CacheOpChild::~CacheOpChild()
{
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
MOZ_ASSERT(!mPromise);
}
void
CacheOpChild::ActorDestroy(ActorDestroyReason aReason)
{
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
// If the actor was terminated for some unknown reason, then indicate the
// operation is dead.
if (mPromise) {
mPromise->MaybeReject(NS_ERROR_FAILURE);
mPromise = nullptr;
}
RemoveFeature();
}
bool
CacheOpChild::Recv__delete__(const ErrorResult& aRv,
const CacheOpResult& aResult)
{
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
if (aRv.Failed()) {
MOZ_ASSERT(aResult.type() == CacheOpResult::Tvoid_t);
// TODO: Remove this const_cast (bug 1152078).
// It is safe for now since this ErrorResult is handed off to us by IPDL
// and is thrown into the trash afterwards.
mPromise->MaybeReject(const_cast<ErrorResult&>(aRv));
mPromise = nullptr;
return true;
}
switch (aResult.type()) {
case CacheOpResult::TCacheMatchResult:
{
HandleResponse(aResult.get_CacheMatchResult().responseOrVoid());
break;
}
case CacheOpResult::TCacheMatchAllResult:
{
HandleResponseList(aResult.get_CacheMatchAllResult().responseList());
break;
}
case CacheOpResult::TCacheAddAllResult:
case CacheOpResult::TCachePutAllResult:
{
mPromise->MaybeResolve(JS::UndefinedHandleValue);
break;
}
case CacheOpResult::TCacheDeleteResult:
{
mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success());
break;
}
case CacheOpResult::TCacheKeysResult:
{
HandleRequestList(aResult.get_CacheKeysResult().requestList());
break;
}
case CacheOpResult::TStorageMatchResult:
{
HandleResponse(aResult.get_StorageMatchResult().responseOrVoid());
break;
}
case CacheOpResult::TStorageHasResult:
{
mPromise->MaybeResolve(aResult.get_StorageHasResult().success());
break;
}
case CacheOpResult::TStorageOpenResult:
{
auto actor = static_cast<CacheChild*>(
aResult.get_StorageOpenResult().actorChild());
actor->SetFeature(GetFeature());
nsRefPtr<Cache> cache = new Cache(mGlobal, actor);
mPromise->MaybeResolve(cache);
break;
}
case CacheOpResult::TStorageDeleteResult:
{
mPromise->MaybeResolve(aResult.get_StorageDeleteResult().success());
break;
}
case CacheOpResult::TStorageKeysResult:
{
mPromise->MaybeResolve(aResult.get_StorageKeysResult().keyList());
break;
}
default:
MOZ_CRASH("Unknown Cache op result type!");
}
mPromise = nullptr;
return true;
}
void
CacheOpChild::StartDestroy()
{
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
// Do not cancel on-going operations when Feature calls this. Instead, keep
// the Worker alive until we are done.
}
nsIGlobalObject*
CacheOpChild::GetGlobalObject() const
{
return mGlobal;
}
#ifdef DEBUG
void
CacheOpChild::AssertOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(CacheOpChild);
}
#endif
CachePushStreamChild*
CacheOpChild::CreatePushStream(nsIAsyncInputStream* aStream)
{
MOZ_CRASH("CacheOpChild should never create a push stream actor!");
}
void
CacheOpChild::HandleResponse(const CacheResponseOrVoid& aResponseOrVoid)
{
if (aResponseOrVoid.type() == CacheResponseOrVoid::Tvoid_t) {
mPromise->MaybeResolve(JS::UndefinedHandleValue);
return;
}
const CacheResponse& cacheResponse = aResponseOrVoid.get_CacheResponse();
AddFeatureToStreamChild(cacheResponse, GetFeature());
nsRefPtr<Response> response = ToResponse(cacheResponse);
mPromise->MaybeResolve(response);
}
void
CacheOpChild::HandleResponseList(const nsTArray<CacheResponse>& aResponseList)
{
nsAutoTArray<nsRefPtr<Response>, 256> responses;
responses.SetCapacity(aResponseList.Length());
for (uint32_t i = 0; i < aResponseList.Length(); ++i) {
AddFeatureToStreamChild(aResponseList[i], GetFeature());
responses.AppendElement(ToResponse(aResponseList[i]));
}
mPromise->MaybeResolve(responses);
}
void
CacheOpChild::HandleRequestList(const nsTArray<CacheRequest>& aRequestList)
{
nsAutoTArray<nsRefPtr<Request>, 256> requests;
requests.SetCapacity(aRequestList.Length());
for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
AddFeatureToStreamChild(aRequestList[i], GetFeature());
requests.AppendElement(ToRequest(aRequestList[i]));
}
mPromise->MaybeResolve(requests);
}
} // namespace cache
} // namespace dom
} // namespace mozilla

80
dom/cache/CacheOpChild.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_cache_CacheOpChild_h
#define mozilla_dom_cache_CacheOpChild_h
#include "mozilla/dom/cache/ActorChild.h"
#include "mozilla/dom/cache/PCacheOpChild.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsRefPtr.h"
class nsIGlobalObject;
namespace mozilla {
namespace dom {
class Promise;
namespace cache {
class CacheOpChild final : public PCacheOpChild
, public ActorChild
, public TypeUtils
{
friend class CacheChild;
friend class CacheStorageChild;
private:
// This class must be constructed by CacheChild or CacheStorageChild using
// their ExecuteOp() factory method.
CacheOpChild(Feature* aFeature, nsIGlobalObject* aGlobal, Promise* aPromise);
~CacheOpChild();
// PCacheOpChild methods
virtual void
ActorDestroy(ActorDestroyReason aReason) override;
virtual bool
Recv__delete__(const ErrorResult& aRv, const CacheOpResult& aResult) override;
// ActorChild methods
virtual void
StartDestroy() override;
// TypeUtils methods
virtual nsIGlobalObject*
GetGlobalObject() const override;
#ifdef DEBUG
virtual void
AssertOwningThread() const override;
#endif
virtual CachePushStreamChild*
CreatePushStream(nsIAsyncInputStream* aStream) override;
// Utility methods
void
HandleResponse(const CacheResponseOrVoid& aResponseOrVoid);
void
HandleResponseList(const nsTArray<CacheResponse>& aResponseList);
void
HandleRequestList(const nsTArray<CacheRequest>& aRequestList);
nsCOMPtr<nsIGlobalObject> mGlobal;
nsRefPtr<Promise> mPromise;
NS_DECL_OWNINGTHREAD
};
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_CacheOpChild_h

287
dom/cache/CacheOpParent.cpp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,287 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/cache/CacheOpParent.h"
#include "mozilla/unused.h"
#include "mozilla/dom/cache/AutoUtils.h"
#include "mozilla/dom/cache/CachePushStreamParent.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/SavedTypes.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
namespace mozilla {
namespace dom {
namespace cache {
using mozilla::ipc::FileDescriptorSetParent;
using mozilla::ipc::PBackgroundParent;
CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager, CacheId aCacheId,
const CacheOpArgs& aOpArgs)
: mIpcManager(aIpcManager)
, mCacheId(aCacheId)
, mNamespace(INVALID_NAMESPACE)
, mOpArgs(aOpArgs)
{
MOZ_ASSERT(mIpcManager);
}
CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager,
Namespace aNamespace, const CacheOpArgs& aOpArgs)
: mIpcManager(aIpcManager)
, mCacheId(INVALID_CACHE_ID)
, mNamespace(aNamespace)
, mOpArgs(aOpArgs)
{
MOZ_ASSERT(mIpcManager);
}
CacheOpParent::~CacheOpParent()
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
}
void
CacheOpParent::Execute(ManagerId* aManagerId)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
MOZ_ASSERT(!mManager);
MOZ_ASSERT(!mVerifier);
nsRefPtr<Manager> manager;
nsresult rv = Manager::GetOrCreate(aManagerId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
unused << Send__delete__(this, ErrorResult(rv), void_t());
return;
}
Execute(manager);
}
void
CacheOpParent::Execute(Manager* aManager)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
MOZ_ASSERT(!mManager);
MOZ_ASSERT(!mVerifier);
mManager = aManager;
// Handle add/addAll op with a FetchPut object
if (mOpArgs.type() == CacheOpArgs::TCacheAddAllArgs) {
MOZ_ASSERT(mCacheId != INVALID_CACHE_ID);
const CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
const nsTArray<CacheRequest>& list = args.requestList();
nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreamList;
for (uint32_t i = 0; i < list.Length(); ++i) {
requestStreamList.AppendElement(DeserializeCacheStream(list[i].body()));
}
nsRefPtr<FetchPut> fetchPut;
nsresult rv = FetchPut::Create(this, mManager, mCacheId, list,
requestStreamList, getter_AddRefs(fetchPut));
if (NS_WARN_IF(NS_FAILED(rv))) {
OnOpComplete(ErrorResult(rv), CacheAddAllResult());
return;
}
mFetchPutList.AppendElement(fetchPut.forget());
return;
}
// Handle put op
if (mOpArgs.type() == CacheOpArgs::TCachePutAllArgs) {
MOZ_ASSERT(mCacheId != INVALID_CACHE_ID);
const CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
const nsTArray<CacheRequestResponse>& list = args.requestResponseList();
nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreamList;
nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> responseStreamList;
for (uint32_t i = 0; i < list.Length(); ++i) {
requestStreamList.AppendElement(
DeserializeCacheStream(list[i].request().body()));
responseStreamList.AppendElement(
DeserializeCacheStream(list[i].response().body()));
}
mManager->ExecutePutAll(this, mCacheId, args.requestResponseList(),
requestStreamList, responseStreamList);
return;
}
// Handle all other cache ops
if (mCacheId != INVALID_CACHE_ID) {
MOZ_ASSERT(mNamespace == INVALID_NAMESPACE);
mManager->ExecuteCacheOp(this, mCacheId, mOpArgs);
return;
}
// Handle all storage ops
MOZ_ASSERT(mNamespace != INVALID_NAMESPACE);
mManager->ExecuteStorageOp(this, mNamespace, mOpArgs);
}
void
CacheOpParent::WaitForVerification(PrincipalVerifier* aVerifier)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
MOZ_ASSERT(!mManager);
MOZ_ASSERT(!mVerifier);
mVerifier = aVerifier;
mVerifier->AddListener(this);
}
void
CacheOpParent::ActorDestroy(ActorDestroyReason aReason)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
if (mVerifier) {
mVerifier->RemoveListener(this);
mVerifier = nullptr;
}
for (uint32_t i = 0; i < mFetchPutList.Length(); ++i) {
mFetchPutList[i]->ClearListener();
}
mFetchPutList.Clear();
if (mManager) {
mManager->RemoveListener(this);
mManager = nullptr;
}
mIpcManager = nullptr;
}
void
CacheOpParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
mVerifier->RemoveListener(this);
mVerifier = nullptr;
if (NS_WARN_IF(NS_FAILED(aRv))) {
unused << Send__delete__(this, ErrorResult(aRv), void_t());
return;
}
Execute(aManagerId);
}
void
CacheOpParent::OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId,
const nsTArray<SavedResponse>& aSavedResponseList,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
MOZ_ASSERT(mIpcManager);
MOZ_ASSERT(mManager);
// Never send an op-specific result if we have an error. Instead, send
// void_t() to ensure that we don't leak actors on the child side.
if (aRv.Failed()) {
unused << Send__delete__(this, aRv, void_t());
aRv.ClearMessage(); // This may contain a TypeError.
return;
}
// The result must contain the appropriate type at this point. It may
// or may not contain the additional result data yet. For types that
// do not need special processing, it should already be set. If the
// result requires actor-specific operations, then we do that below.
// If the type and data types don't match, then we will trigger an
// assertion in AutoParentOpResult::Add().
AutoParentOpResult result(mIpcManager, aResult);
if (aOpenedCacheId != INVALID_CACHE_ID) {
result.Add(aOpenedCacheId, mManager);
}
for (uint32_t i = 0; i < aSavedResponseList.Length(); ++i) {
result.Add(aSavedResponseList[i], aStreamList);
}
for (uint32_t i = 0; i < aSavedRequestList.Length(); ++i) {
result.Add(aSavedRequestList[i], aStreamList);
}
unused << Send__delete__(this, aRv, result.SendAsOpResult());
}
void
CacheOpParent::OnFetchPut(FetchPut* aFetchPut, ErrorResult&& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheOpParent);
MOZ_ASSERT(aFetchPut);
aFetchPut->ClearListener();
MOZ_ALWAYS_TRUE(mFetchPutList.RemoveElement(aFetchPut));
OnOpComplete(Move(aRv), CacheAddAllResult());
}
already_AddRefed<nsIInputStream>
CacheOpParent::DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid)
{
if (aStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
return nullptr;
}
nsCOMPtr<nsIInputStream> stream;
const CacheReadStream& readStream = aStreamOrVoid.get_CacheReadStream();
// Option 1: A push stream actor was sent for nsPipe data
if (readStream.pushStreamParent()) {
MOZ_ASSERT(!readStream.controlParent());
CachePushStreamParent* pushStream =
static_cast<CachePushStreamParent*>(readStream.pushStreamParent());
stream = pushStream->TakeReader();
MOZ_ASSERT(stream);
return stream.forget();
}
// Option 2: One of our own ReadStreams was passed back to us with a stream
// control actor.
stream = ReadStream::Create(readStream);
if (stream) {
return stream.forget();
}
// Option 3: A stream was serialized using normal methods.
nsAutoTArray<FileDescriptor, 4> fds;
if (readStream.fds().type() ==
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
FileDescriptorSetParent* fdSetActor =
static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent());
MOZ_ASSERT(fdSetActor);
fdSetActor->ForgetFileDescriptors(fds);
MOZ_ASSERT(!fds.IsEmpty());
if (!fdSetActor->Send__delete__(fdSetActor)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to delete fd set actor.");
}
}
return DeserializeInputStream(readStream.params(), fds);
}
} // namespace cache
} // namespace dom
} // namespace mozilla

87
dom/cache/CacheOpParent.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_cache_CacheOpParent_h
#define mozilla_dom_cache_CacheOpParent_h
#include "mozilla/dom/cache/FetchPut.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/PCacheOpParent.h"
#include "mozilla/dom/cache/PrincipalVerifier.h"
#include "nsTArray.h"
namespace mozilla {
namespace ipc {
class PBackgroundParent;
}
namespace dom {
namespace cache {
class CacheOpParent final : public PCacheOpParent
, public PrincipalVerifier::Listener
, public Manager::Listener
, public FetchPut::Listener
{
// to allow use of convenience overrides
using Manager::Listener::OnOpComplete;
public:
CacheOpParent(mozilla::ipc::PBackgroundParent* aIpcManager, CacheId aCacheId,
const CacheOpArgs& aOpArgs);
CacheOpParent(mozilla::ipc::PBackgroundParent* aIpcManager,
Namespace aNamespace, const CacheOpArgs& aOpArgs);
~CacheOpParent();
void
Execute(ManagerId* aManagerId);
void
Execute(Manager* aManager);
void
WaitForVerification(PrincipalVerifier* aVerifier);
private:
// PCacheOpParent methods
virtual void
ActorDestroy(ActorDestroyReason aReason) override;
// PrincipalVerifier::Listener methods
virtual void
OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId) override;
// Manager::Listener methods
virtual void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId,
const nsTArray<SavedResponse>& aSavedResponseList,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList) override;
// FetchPut::Listener methods
virtual void
OnFetchPut(FetchPut* aFetchPut, ErrorResult&& aRv) override;
// utility methods
already_AddRefed<nsIInputStream>
DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid);
mozilla::ipc::PBackgroundParent* mIpcManager;
const CacheId mCacheId;
const Namespace mNamespace;
const CacheOpArgs mOpArgs;
nsRefPtr<Manager> mManager;
nsRefPtr<PrincipalVerifier> mVerifier;
nsTArray<nsRefPtr<FetchPut>> mFetchPutList;
NS_DECL_OWNINGTHREAD
};
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_CacheOpParent_h

285
dom/cache/CacheParent.cpp поставляемый
Просмотреть файл

@ -6,27 +6,14 @@
#include "mozilla/dom/cache/CacheParent.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/cache/AutoUtils.h"
#include "mozilla/dom/cache/CacheOpParent.h"
#include "mozilla/dom/cache/CachePushStreamParent.h"
#include "mozilla/dom/cache/CacheStreamControlParent.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/SavedTypes.h"
#include "mozilla/dom/cache/StreamList.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/PFileDescriptorSetParent.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace dom {
namespace cache {
using mozilla::dom::ErrNum;
using mozilla::ipc::FileDescriptorSetParent;
using mozilla::ipc::PFileDescriptorSetParent;
// Declared in ActorUtils.h
void
DeallocPCacheParent(PCacheParent* aActor)
@ -47,22 +34,48 @@ CacheParent::~CacheParent()
{
MOZ_COUNT_DTOR(cache::CacheParent);
MOZ_ASSERT(!mManager);
MOZ_ASSERT(mFetchPutList.IsEmpty());
}
void
CacheParent::ActorDestroy(ActorDestroyReason aReason)
{
MOZ_ASSERT(mManager);
for (uint32_t i = 0; i < mFetchPutList.Length(); ++i) {
mFetchPutList[i]->ClearListener();
}
mFetchPutList.Clear();
mManager->RemoveListener(this);
mManager->ReleaseCacheId(mCacheId);
mManager = nullptr;
}
PCacheOpParent*
CacheParent::AllocPCacheOpParent(const CacheOpArgs& aOpArgs)
{
if (aOpArgs.type() != CacheOpArgs::TCacheMatchArgs &&
aOpArgs.type() != CacheOpArgs::TCacheMatchAllArgs &&
aOpArgs.type() != CacheOpArgs::TCacheAddAllArgs &&
aOpArgs.type() != CacheOpArgs::TCachePutAllArgs &&
aOpArgs.type() != CacheOpArgs::TCacheDeleteArgs &&
aOpArgs.type() != CacheOpArgs::TCacheKeysArgs)
{
MOZ_CRASH("Invalid operation sent to Cache actor!");
}
return new CacheOpParent(Manager(), mCacheId, aOpArgs);
}
bool
CacheParent::DeallocPCacheOpParent(PCacheOpParent* aActor)
{
delete aActor;
return true;
}
bool
CacheParent::RecvPCacheOpConstructor(PCacheOpParent* aActor,
const CacheOpArgs& aOpArgs)
{
auto actor = static_cast<CacheOpParent*>(aActor);
actor->Execute(mManager);
return true;
}
PCachePushStreamParent*
CacheParent::AllocPCachePushStreamParent()
{
@ -86,238 +99,6 @@ CacheParent::RecvTeardown()
return true;
}
bool
CacheParent::RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
const PCacheQueryParams& aParams)
{
MOZ_ASSERT(mManager);
mManager->CacheMatch(this, aRequestId, mCacheId, aRequest,
aParams);
return true;
}
bool
CacheParent::RecvMatchAll(const RequestId& aRequestId,
const PCacheRequestOrVoid& aRequest,
const PCacheQueryParams& aParams)
{
MOZ_ASSERT(mManager);
mManager->CacheMatchAll(this, aRequestId, mCacheId, aRequest, aParams);
return true;
}
bool
CacheParent::RecvAddAll(const RequestId& aRequestId,
nsTArray<PCacheRequest>&& aRequests)
{
nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreams;
requestStreams.SetCapacity(aRequests.Length());
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
requestStreams.AppendElement(DeserializeCacheStream(aRequests[i].body()));
}
nsRefPtr<FetchPut> fetchPut;
nsresult rv = FetchPut::Create(this, mManager, aRequestId, mCacheId,
aRequests, requestStreams,
getter_AddRefs(fetchPut));
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR);
ErrorResult error;
error.Throw(rv);
if (!SendAddAllResponse(aRequestId, error)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send AddAll response.");
}
return true;
}
mFetchPutList.AppendElement(fetchPut.forget());
return true;
}
bool
CacheParent::RecvPut(const RequestId& aRequestId,
const CacheRequestResponse& aPut)
{
MOZ_ASSERT(mManager);
nsAutoTArray<CacheRequestResponse, 1> putList;
putList.AppendElement(aPut);
nsAutoTArray<nsCOMPtr<nsIInputStream>, 1> requestStreamList;
nsAutoTArray<nsCOMPtr<nsIInputStream>, 1> responseStreamList;
requestStreamList.AppendElement(
DeserializeCacheStream(aPut.request().body()));
responseStreamList.AppendElement(
DeserializeCacheStream(aPut.response().body()));
mManager->CachePutAll(this, aRequestId, mCacheId, putList, requestStreamList,
responseStreamList);
return true;
}
bool
CacheParent::RecvDelete(const RequestId& aRequestId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams)
{
MOZ_ASSERT(mManager);
mManager->CacheDelete(this, aRequestId, mCacheId, aRequest, aParams);
return true;
}
bool
CacheParent::RecvKeys(const RequestId& aRequestId,
const PCacheRequestOrVoid& aRequest,
const PCacheQueryParams& aParams)
{
MOZ_ASSERT(mManager);
mManager->CacheKeys(this, aRequestId, mCacheId, aRequest, aParams);
return true;
}
void
CacheParent::OnCacheMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aSavedResponse,
StreamList* aStreamList)
{
AutoParentResponseOrVoid response(Manager());
// no match
if (NS_FAILED(aRv) || !aSavedResponse || !aStreamList) {
if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send Match response.");
}
return;
}
if (aSavedResponse) {
response.Add(*aSavedResponse, aStreamList);
}
if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send Match response.");
}
}
void
CacheParent::OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedResponse>& aSavedResponses,
StreamList* aStreamList)
{
AutoParentResponseList responses(Manager(), aSavedResponses.Length());
for (uint32_t i = 0; i < aSavedResponses.Length(); ++i) {
responses.Add(aSavedResponses[i], aStreamList);
}
if (!SendMatchAllResponse(aRequestId, aRv, responses.SendAsResponseList())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send MatchAll response.");
}
}
void
CacheParent::OnCachePutAll(RequestId aRequestId, nsresult aRv)
{
if (!SendPutResponse(aRequestId, aRv)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send Put response.");
}
}
void
CacheParent::OnCacheDelete(RequestId aRequestId, nsresult aRv, bool aSuccess)
{
if (!SendDeleteResponse(aRequestId, aRv, aSuccess)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send Delete response.");
}
}
void
CacheParent::OnCacheKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedRequest>& aSavedRequests,
StreamList* aStreamList)
{
AutoParentRequestList requests(Manager(), aSavedRequests.Length());
for (uint32_t i = 0; i < aSavedRequests.Length(); ++i) {
requests.Add(aSavedRequests[i], aStreamList);
}
if (!SendKeysResponse(aRequestId, aRv, requests.SendAsRequestList())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send Keys response.");
}
}
void
CacheParent::OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, const ErrorResult& aRv)
{
aFetchPut->ClearListener();
mFetchPutList.RemoveElement(aFetchPut);
if (!SendAddAllResponse(aRequestId, aRv)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to send AddAll response.");
}
}
already_AddRefed<nsIInputStream>
CacheParent::DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid)
{
if (aStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
return nullptr;
}
nsCOMPtr<nsIInputStream> stream;
const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream();
// Option 1: A push stream actor was sent for nsPipe data
if (readStream.pushStreamParent()) {
MOZ_ASSERT(!readStream.controlParent());
CachePushStreamParent* pushStream =
static_cast<CachePushStreamParent*>(readStream.pushStreamParent());
stream = pushStream->TakeReader();
MOZ_ASSERT(stream);
return stream.forget();
}
// Option 2: One of our own ReadStreams was passed back to us with a stream
// control actor.
stream = ReadStream::Create(readStream);
if (stream) {
return stream.forget();
}
// Option 3: A stream was serialized using normal methods.
nsAutoTArray<FileDescriptor, 4> fds;
if (readStream.fds().type() ==
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
FileDescriptorSetParent* fdSetActor =
static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent());
MOZ_ASSERT(fdSetActor);
fdSetActor->ForgetFileDescriptors(fds);
MOZ_ASSERT(!fds.IsEmpty());
if (!fdSetActor->Send__delete__(fdSetActor)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("Cache failed to delete fd set actor.");
}
}
return DeserializeInputStream(readStream.params(), fds);
}
} // namespace cache
} // namespace dom
} // namesapce mozilla

67
dom/cache/CacheParent.h поставляемый
Просмотреть файл

@ -7,77 +7,46 @@
#ifndef mozilla_dom_cache_CacheParent_h
#define mozilla_dom_cache_CacheParent_h
#include "mozilla/dom/cache/FetchPut.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/PCacheParent.h"
#include "mozilla/dom/cache/Types.h"
struct nsID;
template <class T> class nsRefPtr;
namespace mozilla {
namespace dom {
namespace cache {
struct SavedResponse;
class Manager;
class CacheParent final : public PCacheParent
, public Manager::Listener
, public FetchPut::Listener
{
public:
CacheParent(cache::Manager* aManager, CacheId aCacheId);
virtual ~CacheParent();
private:
// PCacheParent method
// PCacheParent methods
virtual void ActorDestroy(ActorDestroyReason aReason) override;
virtual PCachePushStreamParent* AllocPCachePushStreamParent() override;
virtual bool DeallocPCachePushStreamParent(PCachePushStreamParent* aActor) override;
virtual bool RecvTeardown() override;
virtual bool
RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
const PCacheQueryParams& aParams) override;
virtual bool
RecvMatchAll(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest,
const PCacheQueryParams& aParams) override;
virtual bool
RecvAddAll(const RequestId& aRequestId,
nsTArray<PCacheRequest>&& aRequests) override;
virtual bool
RecvPut(const RequestId& aRequestId,
const CacheRequestResponse& aPut) override;
virtual bool
RecvDelete(const RequestId& aRequestId, const PCacheRequest& aRequest,
const PCacheQueryParams& aParams) override;
virtual bool
RecvKeys(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest,
const PCacheQueryParams& aParams) override;
// Manager::Listener methods
virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aSavedResponse,
StreamList* aStreamList) override;
virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedResponse>& aSavedResponses,
StreamList* aStreamList) override;
virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) override;
virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv,
bool aSuccess) override;
virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedRequest>& aSavedRequests,
StreamList* aStreamList) override;
virtual PCacheOpParent*
AllocPCacheOpParent(const CacheOpArgs& aOpArgs) override;
// FetchPut::Listener methods
virtual void OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId,
const mozilla::ErrorResult& aRv) override;
virtual bool
DeallocPCacheOpParent(PCacheOpParent* aActor) override;
already_AddRefed<nsIInputStream>
DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid);
virtual bool
RecvPCacheOpConstructor(PCacheOpParent* actor,
const CacheOpArgs& aOpArgs) override;
virtual PCachePushStreamParent*
AllocPCachePushStreamParent() override;
virtual bool
DeallocPCachePushStreamParent(PCachePushStreamParent* aActor) override;
virtual bool
RecvTeardown() override;
nsRefPtr<cache::Manager> mManager;
const CacheId mCacheId;
nsTArray<nsRefPtr<FetchPut>> mFetchPutList;
};
} // namespace cache

11
dom/cache/CachePushStreamChild.h поставляемый
Просмотреть файл

@ -20,17 +20,20 @@ namespace cache {
class CachePushStreamChild final : public PCachePushStreamChild
, public ActorChild
{
friend class CacheChild;
public:
CachePushStreamChild(Feature* aFeature, nsIAsyncInputStream* aStream);
~CachePushStreamChild();
void Start();
virtual void StartDestroy() override;
void Start();
private:
class Callback;
// This class must be constructed using CacheChild::CreatePushStream()
CachePushStreamChild(Feature* aFeature, nsIAsyncInputStream* aStream);
~CachePushStreamChild();
// PCachePushStreamChild methods
virtual void
ActorDestroy(ActorDestroyReason aReason) override;

367
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -41,24 +41,26 @@ using mozilla::ipc::PrincipalToPrincipalInfo;
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage);
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage);
NS_IMPL_CYCLE_COLLECTION_CLASS(mozilla::dom::cache::CacheStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(mozilla::dom::cache::CacheStorage)
tmp->DisconnectFromActor();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal, mRequestPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(mozilla::dom::cache::CacheStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal, mRequestPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(mozilla::dom::cache::CacheStorage)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::CacheStorage,
mGlobal);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIIPCBackgroundChildCreateCallback)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
NS_INTERFACE_MAP_END
// We cannot reference IPC types in a webidl binding implementation header. So
// define this in the .cpp and use heap storage in the mPendingRequests list.
struct CacheStorage::Entry final
{
nsRefPtr<Promise> mPromise;
CacheOpArgs mArgs;
// We cannot add the requests until after the actor is present. So store
// the request data separately for now.
nsRefPtr<InternalRequest> mRequest;
};
// static
already_AddRefed<CacheStorage>
CacheStorage::CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal,
@ -175,29 +177,31 @@ CacheStorage::Match(const RequestOrUSVString& aRequest,
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mFailedActor) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<InternalRequest> request = ToInternalRequest(aRequest, IgnoreBody,
aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
if (mFailedActor) {
promise->MaybeReject(NS_ERROR_UNEXPECTED);
return promise.forget();
}
CacheQueryParams params;
ToCacheQueryParams(params, aOptions);
RequestId requestId = AddRequestPromise(promise, aRv);
Entry entry;
entry.mRequestId = requestId;
entry.mOp = OP_MATCH;
entry.mOptions = aOptions;
entry.mRequest = ToInternalRequest(aRequest, IgnoreBody, aRv);
if (aRv.Failed()) {
return nullptr;
}
mPendingRequests.AppendElement(entry);
nsAutoPtr<Entry> entry(new Entry());
entry->mPromise = promise;
entry->mArgs = StorageMatchArgs(CacheRequest(), params);
entry->mRequest = request;
mPendingRequests.AppendElement(entry.forget());
MaybeRunPendingRequests();
return promise.forget();
@ -208,23 +212,21 @@ CacheStorage::Has(const nsAString& aKey, ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mFailedActor) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
if (mFailedActor) {
promise->MaybeReject(NS_ERROR_UNEXPECTED);
return promise.forget();
}
RequestId requestId = AddRequestPromise(promise, aRv);
Entry* entry = mPendingRequests.AppendElement();
entry->mRequestId = requestId;
entry->mOp = OP_HAS;
entry->mKey = aKey;
nsAutoPtr<Entry> entry(new Entry());
entry->mPromise = promise;
entry->mArgs = StorageHasArgs(nsString(aKey));
mPendingRequests.AppendElement(entry.forget());
MaybeRunPendingRequests();
return promise.forget();
@ -235,23 +237,21 @@ CacheStorage::Open(const nsAString& aKey, ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mFailedActor) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
if (mFailedActor) {
promise->MaybeReject(NS_ERROR_UNEXPECTED);
return promise.forget();
}
RequestId requestId = AddRequestPromise(promise, aRv);
Entry* entry = mPendingRequests.AppendElement();
entry->mRequestId = requestId;
entry->mOp = OP_OPEN;
entry->mKey = aKey;
nsAutoPtr<Entry> entry(new Entry());
entry->mPromise = promise;
entry->mArgs = StorageOpenArgs(nsString(aKey));
mPendingRequests.AppendElement(entry.forget());
MaybeRunPendingRequests();
return promise.forget();
@ -262,23 +262,21 @@ CacheStorage::Delete(const nsAString& aKey, ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mFailedActor) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
if (mFailedActor) {
promise->MaybeReject(NS_ERROR_UNEXPECTED);
return promise.forget();
}
RequestId requestId = AddRequestPromise(promise, aRv);
Entry* entry = mPendingRequests.AppendElement();
entry->mRequestId = requestId;
entry->mOp = OP_DELETE;
entry->mKey = aKey;
nsAutoPtr<Entry> entry(new Entry());
entry->mPromise = promise;
entry->mArgs = StorageDeleteArgs(nsString(aKey));
mPendingRequests.AppendElement(entry.forget());
MaybeRunPendingRequests();
return promise.forget();
@ -289,22 +287,21 @@ CacheStorage::Keys(ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mFailedActor) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (!promise) {
return nullptr;
}
if (mFailedActor) {
promise->MaybeReject(NS_ERROR_UNEXPECTED);
return promise.forget();
}
RequestId requestId = AddRequestPromise(promise, aRv);
Entry* entry = mPendingRequests.AppendElement();
entry->mRequestId = requestId;
entry->mOp = OP_KEYS;
nsAutoPtr<Entry> entry(new Entry());
entry->mPromise = promise;
entry->mArgs = StorageKeysArgs();
mPendingRequests.AppendElement(entry.forget());
MaybeRunPendingRequests();
return promise.forget();
@ -371,9 +368,8 @@ CacheStorage::ActorFailed()
mFeature = nullptr;
for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
RequestId requestId = mPendingRequests[i].mRequestId;
nsRefPtr<Promise> promise = RemoveRequestPromise(requestId);
promise->MaybeReject(NS_ERROR_UNEXPECTED);
nsAutoPtr<Entry> entry(mPendingRequests[i].forget());
entry->mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
}
mPendingRequests.Clear();
}
@ -392,117 +388,6 @@ CacheStorage::DestroyInternal(CacheStorageChild* aActor)
ActorFailed();
}
void
CacheStorage::RecvMatchResponse(RequestId aRequestId, nsresult aRv,
const PCacheResponseOrVoid& aResponse)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
// Convert the response immediately if its present. This ensures that
// any stream actors are cleaned up, even if we error out below.
nsRefPtr<Response> response;
if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) {
response = ToResponse(aResponse);
}
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
// If cache name was specified in the request options and the cache does
// not exist, then an error code will already have been set. If we
// still do not have a response, then we just resolve undefined like a
// normal Cache::Match.
if (!response) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return;
}
promise->MaybeResolve(response);
}
void
CacheStorage::RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(aSuccess);
}
void
CacheStorage::RecvOpenResponse(RequestId aRequestId, nsresult aRv,
CacheChild* aActor)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
// Unlike most of our async callback Recv*() methods, this one gets back
// an actor. We need to make sure to clean it up in case of error.
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
if (aActor) {
// We cannot use the CacheChild::StartDestroy() method because there
// is no Cache object associated with the actor yet. Instead, just
// send the underlying Teardown message.
unused << aActor->SendTeardown();
}
promise->MaybeReject(aRv);
return;
}
if (!aActor) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
nsRefPtr<Cache> cache = new Cache(mGlobal, aActor);
promise->MaybeResolve(cache);
}
void
CacheStorage::RecvDeleteResponse(RequestId aRequestId, nsresult aRv,
bool aSuccess)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(aSuccess);
}
void
CacheStorage::RecvKeysResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<nsString>& aKeys)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
if (NS_FAILED(aRv)) {
promise->MaybeReject(aRv);
return;
}
promise->MaybeResolve(aKeys);
}
nsIGlobalObject*
CacheStorage::GetGlobalObject() const
{
@ -524,32 +409,9 @@ CacheStorage::CreatePushStream(nsIAsyncInputStream* aStream)
MOZ_CRASH("CacheStorage should never create a push stream.");
}
void
CacheStorage::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
// Do nothing. The Promise will automatically drop the ref to us after
// calling the callback. This is what we want as we only registered in order
// to be held alive via the Promise handle.
}
void
CacheStorage::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
// Do nothing. The Promise will automatically drop the ref to us after
// calling the callback. This is what we want as we only registered in order
// to be held alive via the Promise handle.
}
CacheStorage::~CacheStorage()
{
DisconnectFromActor();
}
void
CacheStorage::DisconnectFromActor()
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
if (mActor) {
mActor->StartDestroy();
// DestroyInternal() is called synchronously by StartDestroy(). So we
@ -566,89 +428,22 @@ CacheStorage::MaybeRunPendingRequests()
}
for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
// Note, the entry can be modified below due to Request/Response body
// being marked used.
Entry& entry = mPendingRequests[i];
RequestId requestId = entry.mRequestId;
switch(entry.mOp) {
case OP_MATCH:
{
AutoChildRequest request(this);
ErrorResult rv;
request.Add(entry.mRequest, IgnoreBody, PassThroughReferrer,
IgnoreInvalidScheme, rv);
if (NS_WARN_IF(rv.Failed())) {
nsRefPtr<Promise> promise = RemoveRequestPromise(requestId);
promise->MaybeReject(rv);
break;
}
PCacheQueryParams params;
ToPCacheQueryParams(params, entry.mOptions);
unused << mActor->SendMatch(requestId, request.SendAsRequest(), params);
break;
}
case OP_HAS:
unused << mActor->SendHas(requestId, entry.mKey);
break;
case OP_OPEN:
unused << mActor->SendOpen(requestId, entry.mKey);
break;
case OP_DELETE:
unused << mActor->SendDelete(requestId, entry.mKey);
break;
case OP_KEYS:
unused << mActor->SendKeys(requestId);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown pending CacheStorage op.");
ErrorResult rv;
nsAutoPtr<Entry> entry(mPendingRequests[i].forget());
AutoChildOpArgs args(this, entry->mArgs);
if (entry->mRequest) {
args.Add(entry->mRequest, IgnoreBody, PassThroughReferrer,
IgnoreInvalidScheme, rv);
}
if (rv.Failed()) {
entry->mPromise->MaybeReject(rv);
continue;
}
mActor->ExecuteOp(mGlobal, entry->mPromise, args.SendAsOpArgs());
}
mPendingRequests.Clear();
}
RequestId
CacheStorage::AddRequestPromise(Promise* aPromise, ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
MOZ_ASSERT(aPromise);
MOZ_ASSERT(!mRequestPromises.Contains(aPromise));
// Register ourself as a promise handler so that the promise will hold us
// alive. This allows the client code to drop the ref to the CacheStorage
// object and just keep their promise. This is fairly common in promise
// chaining code.
aPromise->AppendNativeHandler(this);
mRequestPromises.AppendElement(aPromise);
// (Ab)use the promise pointer as our request ID. This is a fast, thread-safe
// way to get a unique ID for the promise to be resolved later.
return reinterpret_cast<RequestId>(aPromise);
}
already_AddRefed<Promise>
CacheStorage::RemoveRequestPromise(RequestId aRequestId)
{
NS_ASSERT_OWNINGTHREAD(CacheStorage);
MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID);
for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) {
nsRefPtr<Promise>& promise = mRequestPromises.ElementAt(i);
// To be safe, only cast promise pointers to our integer RequestId
// type and never cast an integer to a pointer.
if (aRequestId == reinterpret_cast<RequestId>(promise.get())) {
nsRefPtr<Promise> ref;
ref.swap(promise);
mRequestPromises.RemoveElementAt(i);
return ref.forget();
}
}
MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!");
return nullptr;
}
} // namespace cache
} // namespace dom
} // namespace mozilla

58
dom/cache/CacheStorage.h поставляемый
Просмотреть файл

@ -8,7 +8,6 @@
#define mozilla_dom_cache_CacheStorage_h
#include "mozilla/dom/CacheBinding.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsAutoPtr.h"
@ -38,15 +37,12 @@ namespace workers {
namespace cache {
class CacheChild;
class CacheStorageChild;
class Feature;
class PCacheResponseOrVoid;
class CacheStorage final : public nsIIPCBackgroundChildCreateCallback
, public nsWrapperCache
, public TypeUtils
, public PromiseNativeHandler
{
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
@ -81,16 +77,6 @@ public:
// Called when CacheStorageChild actor is being destroyed
void DestroyInternal(CacheStorageChild* aActor);
// Methods forwarded from CacheStorageChild
void RecvMatchResponse(RequestId aRequestId, nsresult aRv,
const PCacheResponseOrVoid& aResponse);
void RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
void RecvOpenResponse(RequestId aRequestId, nsresult aRv,
CacheChild* aActor);
void RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
void RecvKeysResponse(RequestId aRequestId, nsresult aRv,
const nsTArray<nsString>& aKeys);
// TypeUtils methods
virtual nsIGlobalObject* GetGlobalObject() const override;
#ifdef DEBUG
@ -100,60 +86,24 @@ public:
virtual CachePushStreamChild*
CreatePushStream(nsIAsyncInputStream* aStream) override;
// PromiseNativeHandler methods
virtual void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
virtual void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
private:
CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo, Feature* aFeature);
~CacheStorage();
// Called when we're destroyed or CCed.
void DisconnectFromActor();
void MaybeRunPendingRequests();
RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv);
already_AddRefed<Promise> RemoveRequestPromise(RequestId aRequestId);
// Would like to use CacheInitData here, but we cannot because
// its an IPC struct which breaks webidl by including windows.h.
const Namespace mNamespace;
nsCOMPtr<nsIGlobalObject> mGlobal;
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
nsRefPtr<Feature> mFeature;
// weak ref cleared in DestroyInternal
CacheStorageChild* mActor;
nsTArray<nsRefPtr<Promise>> mRequestPromises;
enum Op
{
OP_MATCH,
OP_HAS,
OP_OPEN,
OP_DELETE,
OP_KEYS
};
struct Entry;
nsTArray<nsAutoPtr<Entry>> mPendingRequests;
struct Entry
{
RequestId mRequestId;
Op mOp;
// Would prefer to use PCacheRequest/PCacheCacheQueryOptions, but can't
// because they introduce a header dependency on windows.h which
// breaks the bindings build.
nsRefPtr<InternalRequest> mRequest;
CacheQueryOptions mOptions;
// It would also be nice to union the key with the match args above,
// but VS2013 doesn't like these types in unions because of copy
// constructors.
nsString mKey;
};
nsTArray<Entry> mPendingRequests;
bool mFailedActor;
public:

109
dom/cache/CacheStorageChild.cpp поставляемый
Просмотреть файл

@ -8,8 +8,8 @@
#include "mozilla/unused.h"
#include "mozilla/dom/cache/CacheChild.h"
#include "mozilla/dom/cache/CacheOpChild.h"
#include "mozilla/dom/cache/CacheStorage.h"
#include "mozilla/dom/cache/StreamUtils.h"
namespace mozilla {
namespace dom {
@ -24,6 +24,7 @@ DeallocPCacheStorageChild(PCacheStorageChild* aActor)
CacheStorageChild::CacheStorageChild(CacheStorage* aListener, Feature* aFeature)
: mListener(aListener)
, mNumChildActors(0)
{
MOZ_COUNT_CTOR(cache::CacheStorageChild);
MOZ_ASSERT(mListener);
@ -46,6 +47,15 @@ CacheStorageChild::ClearListener()
mListener = nullptr;
}
void
CacheStorageChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
const CacheOpArgs& aArgs)
{
mNumChildActors += 1;
unused << SendPCacheOpConstructor(
new CacheOpChild(GetFeature(), aGlobal, aPromise), aArgs);
}
void
CacheStorageChild::StartDestroy()
{
@ -65,6 +75,14 @@ CacheStorageChild::StartDestroy()
// CacheStorage listener should call ClearListener() in DestroyInternal()
MOZ_ASSERT(!mListener);
// If we have outstanding child actors, then don't destroy ourself yet.
// The child actors should be short lived and we should allow them to complete
// if possible. SendTeardown() will be called when the count drops to zero
// in NoteDeletedActor().
if (mNumChildActors) {
return;
}
// Start actor destruction from parent process
unused << SendTeardown();
}
@ -83,92 +101,29 @@ CacheStorageChild::ActorDestroy(ActorDestroyReason aReason)
RemoveFeature();
}
bool
CacheStorageChild::RecvMatchResponse(const RequestId& aRequestId,
const nsresult& aRv,
const PCacheResponseOrVoid& aResponseOrVoid)
PCacheOpChild*
CacheStorageChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs)
{
NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
AddFeatureToStreamChild(aResponseOrVoid, GetFeature());
nsRefPtr<CacheStorage> listener = mListener;
if (!listener) {
StartDestroyStreamChild(aResponseOrVoid);
return true;
}
listener->RecvMatchResponse(aRequestId, aRv, aResponseOrVoid);
return true;
MOZ_CRASH("CacheOpChild should be manually constructed.");
return nullptr;
}
bool
CacheStorageChild::RecvHasResponse(const RequestId& aRequestId,
const nsresult& aRv,
const bool& aSuccess)
CacheStorageChild::DeallocPCacheOpChild(PCacheOpChild* aActor)
{
NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
nsRefPtr<CacheStorage> listener = mListener;
if (listener) {
listener->RecvHasResponse(aRequestId, aRv, aSuccess);
}
delete aActor;
NoteDeletedActor();
return true;
}
bool
CacheStorageChild::RecvOpenResponse(const RequestId& aRequestId,
const nsresult& aRv,
PCacheChild* aActor)
void
CacheStorageChild::NoteDeletedActor()
{
NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
nsRefPtr<CacheStorage> listener = mListener;
if (!listener || FeatureNotified()) {
if (aActor) {
unused << aActor->SendTeardown();
}
return true;
MOZ_ASSERT(mNumChildActors);
mNumChildActors -= 1;
if (!mNumChildActors && !mListener) {
unused << SendTeardown();
}
CacheChild* cacheChild = static_cast<CacheChild*>(aActor);
// Since FeatureNotified() returned false above, we are guaranteed that
// the feature won't try to shutdown the actor until after we create the
// Cache DOM object in the listener's RecvOpenResponse() method. This
// is important because StartShutdown() expects a Cache object listener.
if (cacheChild) {
cacheChild->SetFeature(GetFeature());
}
listener->RecvOpenResponse(aRequestId, aRv, cacheChild);
return true;
}
bool
CacheStorageChild::RecvDeleteResponse(const RequestId& aRequestId,
const nsresult& aRv,
const bool& aResult)
{
NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
nsRefPtr<CacheStorage> listener = mListener;
if (listener) {
listener->RecvDeleteResponse(aRequestId, aRv, aResult);
}
return true;
}
bool
CacheStorageChild::RecvKeysResponse(const RequestId& aRequestId,
const nsresult& aRv,
nsTArray<nsString>&& aKeys)
{
NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
nsRefPtr<CacheStorage> listener = mListener;
if (listener) {
listener->RecvKeysResponse(aRequestId, aRv, aKeys);
}
return true;
}
} // namespace cache

37
dom/cache/CacheStorageChild.h поставляемый
Просмотреть файл

@ -11,10 +11,16 @@
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/PCacheStorageChild.h"
class nsIGlobalObject;
namespace mozilla {
namespace dom {
class Promise;
namespace cache {
class CacheOpArgs;
class CacheStorage;
class PCacheChild;
class Feature;
@ -27,11 +33,15 @@ public:
~CacheStorageChild();
// Must be called by the associated CacheStorage listener in its
// ActorDestroy() method. Also, CacheStorage must Send__delete__() the
// ActorDestroy() method. Also, CacheStorage must call SendDestroy() on the
// actor in its destructor to trigger ActorDestroy() if it has not been
// called yet.
void ClearListener();
void
ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
const CacheOpArgs& aArgs);
// ActorChild methods
// Synchronously call ActorDestroy on our CacheStorage listener and then start
@ -42,26 +52,21 @@ private:
// PCacheStorageChild methods
virtual void ActorDestroy(ActorDestroyReason aReason) override;
virtual bool RecvMatchResponse(const RequestId& aRequestId,
const nsresult& aRv,
const PCacheResponseOrVoid& response) override;
virtual bool RecvHasResponse(const cache::RequestId& aRequestId,
const nsresult& aRv,
const bool& aSuccess) override;
virtual bool RecvOpenResponse(const cache::RequestId& aRequestId,
const nsresult& aRv,
PCacheChild* aActor) override;
virtual bool RecvDeleteResponse(const cache::RequestId& aRequestId,
const nsresult& aRv,
const bool& aResult) override;
virtual bool RecvKeysResponse(const cache::RequestId& aRequestId,
const nsresult& aRv,
nsTArray<nsString>&& aKeys) override;
virtual PCacheOpChild*
AllocPCacheOpChild(const CacheOpArgs& aOpArgs) override;
virtual bool
DeallocPCacheOpChild(PCacheOpChild* aActor) override;
// utility methods
void
NoteDeletedActor();
// Use a weak ref so actor does not hold DOM object alive past content use.
// The CacheStorage object must call ClearListener() to null this before its
// destroyed.
CacheStorage* MOZ_NON_OWNING_REF mListener;
uint32_t mNumChildActors;
NS_DECL_OWNINGTHREAD
};

402
dom/cache/CacheStorageParent.cpp поставляемый
Просмотреть файл

@ -6,28 +6,18 @@
#include "mozilla/dom/cache/CacheStorageParent.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/cache/ActorUtils.h"
#include "mozilla/dom/cache/AutoUtils.h"
#include "mozilla/dom/cache/CacheParent.h"
#include "mozilla/dom/cache/CacheStreamControlParent.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/CacheOpParent.h"
#include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/SavedTypes.h"
#include "mozilla/dom/cache/StreamList.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/PFileDescriptorSetParent.h"
#include "mozilla/DebugOnly.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace dom {
namespace cache {
using mozilla::ipc::PBackgroundParent;
using mozilla::ipc::PFileDescriptorSetParent;
using mozilla::ipc::PrincipalInfo;
// declared in ActorUtils.h
@ -65,22 +55,60 @@ CacheStorageParent::~CacheStorageParent()
{
MOZ_COUNT_DTOR(cache::CacheStorageParent);
MOZ_ASSERT(!mVerifier);
MOZ_ASSERT(!mManager);
}
void
CacheStorageParent::ActorDestroy(ActorDestroyReason aReason)
{
if (mVerifier) {
mVerifier->ClearListener();
mVerifier->RemoveListener(this);
mVerifier = nullptr;
}
}
if (mManager) {
MOZ_ASSERT(!mActiveRequests.IsEmpty());
mManager->RemoveListener(this);
mManager = nullptr;
PCacheOpParent*
CacheStorageParent::AllocPCacheOpParent(const CacheOpArgs& aOpArgs)
{
if (aOpArgs.type() != CacheOpArgs::TStorageMatchArgs &&
aOpArgs.type() != CacheOpArgs::TStorageHasArgs &&
aOpArgs.type() != CacheOpArgs::TStorageOpenArgs &&
aOpArgs.type() != CacheOpArgs::TStorageDeleteArgs &&
aOpArgs.type() != CacheOpArgs::TStorageKeysArgs)
{
MOZ_CRASH("Invalid operation sent to CacheStorage actor!");
}
return new CacheOpParent(Manager(), mNamespace, aOpArgs);
}
bool
CacheStorageParent::DeallocPCacheOpParent(PCacheOpParent* aActor)
{
delete aActor;
return true;
}
bool
CacheStorageParent::RecvPCacheOpConstructor(PCacheOpParent* aActor,
const CacheOpArgs& aOpArgs)
{
auto actor = static_cast<CacheOpParent*>(aActor);
if (mVerifier) {
MOZ_ASSERT(!mManagerId);
actor->WaitForVerification(mVerifier);
return true;
}
if (NS_FAILED(mVerifiedStatus)) {
unused << CacheOpParent::Send__delete__(actor, ErrorResult(mVerifiedStatus),
void_t());
return true;
}
MOZ_ASSERT(mManagerId);
actor->Execute(mManagerId);
return true;
}
bool
@ -93,190 +121,11 @@ CacheStorageParent::RecvTeardown()
return true;
}
bool
CacheStorageParent::RecvMatch(const RequestId& aRequestId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams)
{
if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
if (!SendMatchResponse(aRequestId, mVerifiedStatus, void_t())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Match response.");
}
return true;
}
// queue requests if we are still waiting for principal verification
if (!mManagerId) {
Entry* entry = mPendingRequests.AppendElement();
entry->mOp = OP_MATCH;
entry->mRequestId = aRequestId;
entry->mRequest = aRequest;
entry->mParams = aParams;
return true;
}
nsRefPtr<cache::Manager> manager;
nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendMatchResponse(aRequestId, rv, void_t())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Match response.");
}
return true;
}
manager->StorageMatch(this, aRequestId, mNamespace, aRequest,
aParams);
return true;
}
bool
CacheStorageParent::RecvHas(const RequestId& aRequestId, const nsString& aKey)
{
if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
if (!SendHasResponse(aRequestId, mVerifiedStatus, false)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Has response.");
}
return true;
}
// queue requests if we are still waiting for principal verification
if (!mManagerId) {
Entry* entry = mPendingRequests.AppendElement();
entry->mOp = OP_HAS;
entry->mRequestId = aRequestId;
entry->mKey = aKey;
return true;
}
nsRefPtr<cache::Manager> manager;
nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendHasResponse(aRequestId, rv, false)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Has response.");
}
return true;
}
manager->StorageHas(this, aRequestId, mNamespace, aKey);
return true;
}
bool
CacheStorageParent::RecvOpen(const RequestId& aRequestId, const nsString& aKey)
{
if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
if (!SendOpenResponse(aRequestId, mVerifiedStatus, nullptr)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Open response.");
}
return true;
}
// queue requests if we are still waiting for principal verification
if (!mManagerId) {
Entry* entry = mPendingRequests.AppendElement();
entry->mOp = OP_OPEN;
entry->mRequestId = aRequestId;
entry->mKey = aKey;
return true;
}
nsRefPtr<cache::Manager> manager;
nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendOpenResponse(aRequestId, rv, nullptr)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Open response.");
}
return true;
}
manager->StorageOpen(this, aRequestId, mNamespace, aKey);
return true;
}
bool
CacheStorageParent::RecvDelete(const RequestId& aRequestId,
const nsString& aKey)
{
if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
if (!SendDeleteResponse(aRequestId, mVerifiedStatus, false)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Delete response.");
}
return true;
}
// queue requests if we are still waiting for principal verification
if (!mManagerId) {
Entry* entry = mPendingRequests.AppendElement();
entry->mOp = OP_DELETE;
entry->mRequestId = aRequestId;
entry->mKey = aKey;
return true;
}
nsRefPtr<cache::Manager> manager;
nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendDeleteResponse(aRequestId, rv, false)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Delete response.");
}
return true;
}
manager->StorageDelete(this, aRequestId, mNamespace, aKey);
return true;
}
bool
CacheStorageParent::RecvKeys(const RequestId& aRequestId)
{
if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
if (!SendKeysResponse(aRequestId, mVerifiedStatus, nsTArray<nsString>())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Keys response.");
}
}
// queue requests if we are still waiting for principal verification
if (!mManagerId) {
Entry* entry = mPendingRequests.AppendElement();
entry->mOp = OP_DELETE;
entry->mRequestId = aRequestId;
return true;
}
nsRefPtr<cache::Manager> manager;
nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendKeysResponse(aRequestId, rv, nsTArray<nsString>())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Keys response.");
}
return true;
}
manager->StorageKeys(this, aRequestId, mNamespace);
return true;
}
void
CacheStorageParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
{
MOZ_ASSERT(mVerifier);
MOZ_ASSERT(!mManagerId);
MOZ_ASSERT(!mManager);
MOZ_ASSERT(NS_SUCCEEDED(mVerifiedStatus));
if (NS_WARN_IF(NS_FAILED(aRv))) {
@ -284,165 +133,8 @@ CacheStorageParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
}
mManagerId = aManagerId;
mVerifier->ClearListener();
mVerifier->RemoveListener(this);
mVerifier = nullptr;
RetryPendingRequests();
}
void
CacheStorageParent::OnStorageMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aSavedResponse,
StreamList* aStreamList)
{
PCacheResponseOrVoid responseOrVoid;
ReleaseManager(aRequestId);
AutoParentResponseOrVoid response(Manager());
// no match
if (NS_FAILED(aRv) || !aSavedResponse) {
if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Match response.");
}
return;
}
if (aSavedResponse) {
response.Add(*aSavedResponse, aStreamList);
}
if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Match response.");
}
}
void
CacheStorageParent::OnStorageHas(RequestId aRequestId, nsresult aRv,
bool aCacheFound)
{
ReleaseManager(aRequestId);
if (!SendHasResponse(aRequestId, aRv, aCacheFound)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Has response.");
}
}
void
CacheStorageParent::OnStorageOpen(RequestId aRequestId, nsresult aRv,
CacheId aCacheId)
{
if (NS_FAILED(aRv)) {
ReleaseManager(aRequestId);
if (!SendOpenResponse(aRequestId, aRv, nullptr)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Open response.");
}
return;
}
MOZ_ASSERT(mManager);
CacheParent* actor = new CacheParent(mManager, aCacheId);
ReleaseManager(aRequestId);
PCacheParent* base = Manager()->SendPCacheConstructor(actor);
actor = static_cast<CacheParent*>(base);
if (!SendOpenResponse(aRequestId, aRv, actor)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Open response.");
}
}
void
CacheStorageParent::OnStorageDelete(RequestId aRequestId, nsresult aRv,
bool aCacheDeleted)
{
ReleaseManager(aRequestId);
if (!SendDeleteResponse(aRequestId, aRv, aCacheDeleted)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Delete response.");
}
}
void
CacheStorageParent::OnStorageKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<nsString>& aKeys)
{
ReleaseManager(aRequestId);
if (!SendKeysResponse(aRequestId, aRv, aKeys)) {
// child process is gone, warn and allow actor to clean up normally
NS_WARNING("CacheStorage failed to send Keys response.");
}
}
void
CacheStorageParent::RetryPendingRequests()
{
MOZ_ASSERT(mManagerId || NS_FAILED(mVerifiedStatus));
for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
const Entry& entry = mPendingRequests[i];
switch(entry.mOp) {
case OP_MATCH:
RecvMatch(entry.mRequestId, entry.mRequest, entry.mParams);
break;
case OP_HAS:
RecvHas(entry.mRequestId, entry.mKey);
break;
case OP_OPEN:
RecvOpen(entry.mRequestId, entry.mKey);
break;
case OP_DELETE:
RecvDelete(entry.mRequestId, entry.mKey);
break;
case OP_KEYS:
RecvKeys(entry.mRequestId);
break;
default:
MOZ_ASSERT_UNREACHABLE("Pending request within unknown op");
}
}
mPendingRequests.Clear();
mPendingRequests.Compact();
}
nsresult
CacheStorageParent::RequestManager(RequestId aRequestId,
cache::Manager** aManagerOut)
{
MOZ_ASSERT(!mActiveRequests.Contains(aRequestId));
nsRefPtr<cache::Manager> ref = mManager;
if (!ref) {
MOZ_ASSERT(mActiveRequests.IsEmpty());
nsresult rv = cache::Manager::GetOrCreate(mManagerId, getter_AddRefs(ref));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
mManager = ref;
}
mActiveRequests.AppendElement(aRequestId);
ref.forget(aManagerOut);
return NS_OK;
}
void
CacheStorageParent::ReleaseManager(RequestId aRequestId)
{
// Note that if the child process dies we also clean up the mManager in
// ActorDestroy(). There is no race with this method, however, because
// ActorDestroy removes this object from the Manager's listener list.
// Therefore ReleaseManager() should never be called after ActorDestroy()
// runs.
MOZ_ASSERT(mManager);
MOZ_ASSERT(!mActiveRequests.IsEmpty());
MOZ_ALWAYS_TRUE(mActiveRequests.RemoveElement(aRequestId));
if (mActiveRequests.IsEmpty()) {
mManager->RemoveListener(this);
mManager = nullptr;
}
}
} // namespace cache

78
dom/cache/CacheStorageParent.h поставляемый
Просмотреть файл

@ -7,24 +7,18 @@
#ifndef mozilla_dom_cache_CacheStorageParent_h
#define mozilla_dom_cache_CacheStorageParent_h
#include "mozilla/dom/cache/CacheInitData.h"
#include "mozilla/dom/cache/PCacheStorageParent.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/PrincipalVerifier.h"
#include "mozilla/dom/cache/Types.h"
template <class T> class nsRefPtr;
namespace mozilla {
namespace dom {
namespace cache {
class CacheStreamControlParent;
class ManagerId;
class CacheStorageParent final : public PCacheStorageParent
, public PrincipalVerifier::Listener
, public Manager::Listener
{
public:
CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace,
@ -33,72 +27,30 @@ public:
private:
// PCacheStorageParent methods
virtual void ActorDestroy(ActorDestroyReason aReason) override;
virtual bool RecvTeardown() override;
virtual bool RecvMatch(const RequestId& aRequestId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams) override;
virtual bool RecvHas(const RequestId& aRequestId,
const nsString& aKey) override;
virtual bool RecvOpen(const RequestId& aRequestId,
const nsString& aKey) override;
virtual bool RecvDelete(const RequestId& aRequestId,
const nsString& aKey) override;
virtual bool RecvKeys(const RequestId& aRequestId) override;
virtual void
ActorDestroy(ActorDestroyReason aReason) override;
virtual PCacheOpParent*
AllocPCacheOpParent(const CacheOpArgs& aOpArgs) override;
virtual bool
DeallocPCacheOpParent(PCacheOpParent* aActor) override;
virtual bool
RecvPCacheOpConstructor(PCacheOpParent* actor,
const CacheOpArgs& aOpArgs) override;
virtual bool
RecvTeardown() override;
// PrincipalVerifier::Listener methods
virtual void OnPrincipalVerified(nsresult aRv,
ManagerId* aManagerId) override;
// Manager::Listener methods
virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aResponse,
StreamList* aStreamList) override;
virtual void OnStorageHas(RequestId aRequestId, nsresult aRv,
bool aCacheFound) override;
virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv,
CacheId aCacheId) override;
virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv,
bool aCacheDeleted) override;
virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<nsString>& aKeys) override;
CacheStreamControlParent*
SerializeReadStream(CacheStreamControlParent *aStreamControl, const nsID& aId,
StreamList* aStreamList,
PCacheReadStream* aReadStreamOut);
void RetryPendingRequests();
nsresult RequestManager(RequestId aRequestId, cache::Manager** aManagerOut);
void ReleaseManager(RequestId aRequestId);
const Namespace mNamespace;
nsRefPtr<PrincipalVerifier> mVerifier;
nsresult mVerifiedStatus;
nsRefPtr<ManagerId> mManagerId;
nsRefPtr<cache::Manager> mManager;
enum Op
{
OP_MATCH,
OP_HAS,
OP_OPEN,
OP_DELETE,
OP_KEYS
};
struct Entry
{
Op mOp;
RequestId mRequestId;
nsString mKey;
PCacheRequest mRequest;
PCacheQueryParams mParams;
};
nsTArray<Entry> mPendingRequests;
nsTArray<RequestId> mActiveRequests;
};
} // namesapce cache

33
dom/cache/CacheStreamControlChild.cpp поставляемый
Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/unused.h"
#include "mozilla/dom/cache/ActorUtils.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
@ -41,6 +41,7 @@ DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor)
CacheStreamControlChild::CacheStreamControlChild()
: mDestroyStarted(false)
, mDestroyDelayed(false)
{
MOZ_COUNT_CTOR(cache::CacheStreamControlChild);
}
@ -63,13 +64,28 @@ CacheStreamControlChild::StartDestroy()
}
mDestroyStarted = true;
// If any of the streams have started to be read, then wait for them to close
// naturally.
if (HasEverBeenRead()) {
// Note that we are delaying so that we can re-check for active streams
// in NoteClosedAfterForget().
mDestroyDelayed = true;
return;
}
// Otherwise, if the streams have not been touched then just pre-emptively
// close them now. This handles the case where someone retrieves a Response
// from the Cache, but never accesses the body. We should not keep the
// Worker alive until that Response is GC'd just because of its ignored
// body stream.
// Begin shutting down all streams. This is the same as if the parent had
// asked us to shutdown. So simulate the CloseAll IPC message.
RecvCloseAll();
}
void
CacheStreamControlChild::SerializeControl(PCacheReadStream* aReadStreamOut)
CacheStreamControlChild::SerializeControl(CacheReadStream* aReadStreamOut)
{
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
aReadStreamOut->controlParent() = nullptr;
@ -77,7 +93,7 @@ CacheStreamControlChild::SerializeControl(PCacheReadStream* aReadStreamOut)
}
void
CacheStreamControlChild::SerializeFds(PCacheReadStream* aReadStreamOut,
CacheStreamControlChild::SerializeFds(CacheReadStream* aReadStreamOut,
const nsTArray<FileDescriptor>& aFds)
{
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
@ -97,7 +113,7 @@ CacheStreamControlChild::SerializeFds(PCacheReadStream* aReadStreamOut,
}
void
CacheStreamControlChild::DeserializeFds(const PCacheReadStream& aReadStream,
CacheStreamControlChild::DeserializeFds(const CacheReadStream& aReadStream,
nsTArray<FileDescriptor>& aFdsOut)
{
if (aReadStream.fds().type() !=
@ -120,6 +136,15 @@ CacheStreamControlChild::NoteClosedAfterForget(const nsID& aId)
{
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
unused << SendNoteClosed(aId);
// A stream has closed. If we delayed StartDestry() due to this stream
// being read, then we should check to see if any of the remaining streams
// are active. If none of our other streams have been read, then we can
// proceed with the shutdown now.
if (mDestroyDelayed && !HasEverBeenRead()) {
mDestroyDelayed = false;
RecvCloseAll();
}
}
#ifdef DEBUG

7
dom/cache/CacheStreamControlChild.h поставляемый
Просмотреть файл

@ -31,14 +31,14 @@ public:
// StreamControl methods
virtual void
SerializeControl(PCacheReadStream* aReadStreamOut) override;
SerializeControl(CacheReadStream* aReadStreamOut) override;
virtual void
SerializeFds(PCacheReadStream* aReadStreamOut,
SerializeFds(CacheReadStream* aReadStreamOut,
const nsTArray<mozilla::ipc::FileDescriptor>& aFds) override;
virtual void
DeserializeFds(const PCacheReadStream& aReadStream,
DeserializeFds(const CacheReadStream& aReadStream,
nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) override;
private:
@ -56,6 +56,7 @@ private:
virtual bool RecvCloseAll() override;
bool mDestroyStarted;
bool mDestroyDelayed;
NS_DECL_OWNINGTHREAD
};

8
dom/cache/CacheStreamControlParent.cpp поставляемый
Просмотреть файл

@ -8,7 +8,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/unused.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/StreamList.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
@ -45,7 +45,7 @@ CacheStreamControlParent::~CacheStreamControlParent()
}
void
CacheStreamControlParent::SerializeControl(PCacheReadStream* aReadStreamOut)
CacheStreamControlParent::SerializeControl(CacheReadStream* aReadStreamOut)
{
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
aReadStreamOut->controlChild() = nullptr;
@ -53,7 +53,7 @@ CacheStreamControlParent::SerializeControl(PCacheReadStream* aReadStreamOut)
}
void
CacheStreamControlParent::SerializeFds(PCacheReadStream* aReadStreamOut,
CacheStreamControlParent::SerializeFds(CacheReadStream* aReadStreamOut,
const nsTArray<FileDescriptor>& aFds)
{
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
@ -73,7 +73,7 @@ CacheStreamControlParent::SerializeFds(PCacheReadStream* aReadStreamOut,
}
void
CacheStreamControlParent::DeserializeFds(const PCacheReadStream& aReadStream,
CacheStreamControlParent::DeserializeFds(const CacheReadStream& aReadStream,
nsTArray<FileDescriptor>& aFdsOut)
{
if (aReadStream.fds().type() !=

6
dom/cache/CacheStreamControlParent.h поставляемый
Просмотреть файл

@ -32,14 +32,14 @@ public:
// StreamControl methods
virtual void
SerializeControl(PCacheReadStream* aReadStreamOut) override;
SerializeControl(CacheReadStream* aReadStreamOut) override;
virtual void
SerializeFds(PCacheReadStream* aReadStreamOut,
SerializeFds(CacheReadStream* aReadStreamOut,
const nsTArray<mozilla::ipc::FileDescriptor>& aFds) override;
virtual void
DeserializeFds(const PCacheReadStream& aReadStream,
DeserializeFds(const CacheReadStream& aReadStream,
nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) override;
private:

244
dom/cache/CacheTypes.ipdlh поставляемый Normal file
Просмотреть файл

@ -0,0 +1,244 @@
/* 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 PCache;
include protocol PCachePushStream;
include protocol PCacheStreamControl;
include InputStreamParams;
using HeadersGuardEnum from "mozilla/dom/cache/IPCUtils.h";
using RequestCredentials from "mozilla/dom/cache/IPCUtils.h";
using RequestMode from "mozilla/dom/cache/IPCUtils.h";
using RequestCache from "mozilla/dom/cache/IPCUtils.h";
using RequestContext from "mozilla/dom/cache/IPCUtils.h";
using ResponseType from "mozilla/dom/cache/IPCUtils.h";
using mozilla::void_t from "ipc/IPCMessageUtils.h";
using struct nsID from "nsID.h";
namespace mozilla {
namespace dom {
namespace cache {
struct CacheQueryParams
{
bool ignoreSearch;
bool ignoreMethod;
bool ignoreVary;
bool cacheNameSet;
nsString cacheName;
};
struct CacheReadStream
{
nsID id;
OptionalInputStreamParams params;
OptionalFileDescriptorSet fds;
nullable PCacheStreamControl control;
nullable PCachePushStream pushStream;
};
union CacheReadStreamOrVoid
{
void_t;
CacheReadStream;
};
struct HeadersEntry
{
nsCString name;
nsCString value;
};
struct CacheRequest
{
nsCString method;
nsString url;
nsString urlWithoutQuery;
HeadersEntry[] headers;
HeadersGuardEnum headersGuard;
nsString referrer;
RequestMode mode;
RequestCredentials credentials;
CacheReadStreamOrVoid body;
uint32_t contentPolicyType;
RequestContext context;
RequestCache requestCache;
};
union CacheRequestOrVoid
{
void_t;
CacheRequest;
};
struct CacheResponse
{
ResponseType type;
nsString url;
uint32_t status;
nsCString statusText;
HeadersEntry[] headers;
HeadersGuardEnum headersGuard;
CacheReadStreamOrVoid body;
nsCString securityInfo;
};
union CacheResponseOrVoid
{
void_t;
CacheResponse;
};
struct CacheRequestResponse
{
CacheRequest request;
CacheResponse response;
};
struct CacheMatchArgs
{
CacheRequest request;
CacheQueryParams params;
};
struct CacheMatchAllArgs
{
CacheRequestOrVoid requestOrVoid;
CacheQueryParams params;
};
struct CacheAddAllArgs
{
CacheRequest[] requestList;
};
struct CachePutAllArgs
{
CacheRequestResponse[] requestResponseList;
};
struct CacheDeleteArgs
{
CacheRequest request;
CacheQueryParams params;
};
struct CacheKeysArgs
{
CacheRequestOrVoid requestOrVoid;
CacheQueryParams params;
};
struct StorageMatchArgs
{
CacheRequest request;
CacheQueryParams params;
};
struct StorageHasArgs
{
nsString key;
};
struct StorageOpenArgs
{
nsString key;
};
struct StorageDeleteArgs
{
nsString key;
};
struct StorageKeysArgs
{
};
union CacheOpArgs
{
CacheMatchArgs;
CacheMatchAllArgs;
CacheAddAllArgs;
CachePutAllArgs;
CacheDeleteArgs;
CacheKeysArgs;
StorageMatchArgs;
StorageHasArgs;
StorageOpenArgs;
StorageDeleteArgs;
StorageKeysArgs;
};
struct CacheMatchResult
{
CacheResponseOrVoid responseOrVoid;
};
struct CacheMatchAllResult
{
CacheResponse[] responseList;
};
struct CacheAddAllResult
{
};
struct CachePutAllResult
{
};
struct CacheDeleteResult
{
bool success;
};
struct CacheKeysResult
{
CacheRequest[] requestList;
};
struct StorageMatchResult
{
CacheResponseOrVoid responseOrVoid;
};
struct StorageHasResult
{
bool success;
};
struct StorageOpenResult
{
nullable PCache actor;
};
struct StorageDeleteResult
{
bool success;
};
struct StorageKeysResult
{
nsString[] keyList;
};
union CacheOpResult
{
void_t;
CacheMatchResult;
CacheMatchAllResult;
CacheAddAllResult;
CachePutAllResult;
CacheDeleteResult;
CacheKeysResult;
StorageMatchResult;
StorageHasResult;
StorageOpenResult;
StorageDeleteResult;
StorageKeysResult;
};
} // namespace cache
} // namespace dom
} // namespace mozilla

10
dom/cache/Context.cpp поставляемый
Просмотреть файл

@ -732,6 +732,7 @@ Context::Dispatch(nsIEventTarget* aTarget, Action* aAction)
MOZ_ASSERT(aTarget);
MOZ_ASSERT(aAction);
MOZ_ASSERT(mState != STATE_CONTEXT_CANCELED);
if (mState == STATE_CONTEXT_CANCELED) {
return;
} else if (mState == STATE_CONTEXT_INIT) {
@ -766,11 +767,18 @@ Context::CancelAll()
AllowToClose();
}
bool
Context::IsCanceled() const
{
NS_ASSERT_OWNINGTHREAD(Context);
return mState == STATE_CONTEXT_CANCELED;
}
void
Context::Invalidate()
{
NS_ASSERT_OWNINGTHREAD(Context);
mManager->Invalidate();
mManager->NoteClosing();
CancelAll();
}

3
dom/cache/Context.h поставляемый
Просмотреть файл

@ -126,6 +126,9 @@ public:
// Only callable from the thread that created the Context.
void CancelAll();
// True if CancelAll() has been called.
bool IsCanceled() const;
// Like CancelAll(), but also marks the Manager as "invalid".
void Invalidate();

7
dom/cache/DBAction.cpp поставляемый
Просмотреть файл

@ -14,6 +14,7 @@
#include "nsIFile.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "DBSchema.h"
#include "FileUtils.h"
@ -146,7 +147,7 @@ DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
int32_t schemaVersion = 0;
rv = conn->GetSchemaVersion(&schemaVersion);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (schemaVersion > 0 && schemaVersion < DBSchema::kMaxWipeSchemaVersion) {
if (schemaVersion > 0 && schemaVersion < db::kMaxWipeSchemaVersion) {
conn = nullptr;
rv = WipeDatabase(dbFile, aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -154,7 +155,7 @@ DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
}
rv = DBSchema::InitializeConnection(conn);
rv = db::InitializeConnection(conn);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
conn.forget(aConnOut);
@ -169,7 +170,7 @@ DBAction::WipeDatabase(nsIFile* aDBFile, nsIFile* aDBDir)
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// Delete the morgue as well.
rv = FileUtils::BodyDeleteDir(aDBDir);
rv = BodyDeleteDir(aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
return rv;

1
dom/cache/DBAction.h поставляемый
Просмотреть файл

@ -8,7 +8,6 @@
#define mozilla_dom_cache_DBAction_h
#include "mozilla/dom/cache/Action.h"
#include "mozilla/dom/cache/CacheInitData.h"
#include "nsRefPtr.h"
#include "nsString.h"

260
dom/cache/DBSchema.cpp поставляемый
Просмотреть файл

@ -8,8 +8,10 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/SavedTypes.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "nsCOMPtr.h"
@ -19,16 +21,21 @@
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/ResponseBinding.h"
#include "Types.h"
#include "nsIContentPolicy.h"
namespace mozilla {
namespace dom {
namespace cache {
namespace db {
const int32_t DBSchema::kMaxWipeSchemaVersion = 6;
const int32_t DBSchema::kLatestSchemaVersion = 6;
const int32_t DBSchema::kMaxEntriesPerStatement = 255;
const int32_t kMaxWipeSchemaVersion = 6;
namespace {
const int32_t kLatestSchemaVersion = 6;
const int32_t kMaxEntriesPerStatement = 255;
} // anonymous namespace
// If any of the static_asserts below fail, it means that you have changed
// the corresponding WebIDL enum in a way that may be incompatible with the
@ -140,11 +147,48 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_IMAGESET == 21,
"nsContentPolicytType values are as expected");
using mozilla::void_t;
namespace {
typedef int32_t EntryId;
static nsresult QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<EntryId>& aEntryIdListOut);
static nsresult QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<EntryId>& aEntryIdListOut,
uint32_t aMaxResults = UINT32_MAX);
static nsresult MatchByVaryHeader(mozIStorageConnection* aConn,
const CacheRequest& aRequest,
EntryId entryId, bool* aSuccessOut);
static nsresult DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
uint32_t aPos=0, int32_t aLen=-1);
static nsresult InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId);
static nsresult ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
SavedResponse* aSavedResponseOut);
static nsresult ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
SavedRequest* aSavedRequestOut);
static void AppendListParamsToQuery(nsACString& aQuery,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen);
static nsresult BindListParamsToQuery(mozIStorageStatement* aState,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen);
static nsresult BindId(mozIStorageStatement* aState, uint32_t aPos,
const nsID* aId);
static nsresult ExtractId(mozIStorageStatement* aState, uint32_t aPos,
nsID* aIdOut);
} // anonymous namespace
// static
nsresult
DBSchema::CreateSchema(mozIStorageConnection* aConn)
CreateSchema(mozIStorageConnection* aConn)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -284,9 +328,8 @@ DBSchema::CreateSchema(mozIStorageConnection* aConn)
return rv;
}
// static
nsresult
DBSchema::InitializeConnection(mozIStorageConnection* aConn)
InitializeConnection(mozIStorageConnection* aConn)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -315,9 +358,8 @@ DBSchema::InitializeConnection(mozIStorageConnection* aConn)
return NS_OK;
}
// static
nsresult
DBSchema::CreateCache(mozIStorageConnection* aConn, CacheId* aCacheIdOut)
CreateCacheId(mozIStorageConnection* aConn, CacheId* aCacheIdOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -345,10 +387,9 @@ DBSchema::CreateCache(mozIStorageConnection* aConn, CacheId* aCacheIdOut)
return rv;
}
// static
nsresult
DBSchema::DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut)
DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -379,10 +420,9 @@ DBSchema::DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::IsCacheOrphaned(mozIStorageConnection* aConn,
CacheId aCacheId, bool* aOrphanedOut)
IsCacheOrphaned(mozIStorageConnection* aConn, CacheId aCacheId,
bool* aOrphanedOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -414,13 +454,12 @@ DBSchema::IsCacheOrphaned(mozIStorageConnection* aConn,
return rv;
}
// static
nsresult
DBSchema::CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut)
CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -446,19 +485,18 @@ DBSchema::CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams,
nsTArray<SavedResponse>& aSavedResponsesOut)
CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequestOrVoid& aRequestOrVoid,
const CacheQueryParams& aParams,
nsTArray<SavedResponse>& aSavedResponsesOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
nsresult rv;
nsAutoTArray<EntryId, 256> matches;
if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) {
if (aRequestOrVoid.type() == CacheRequestOrVoid::Tvoid_t) {
rv = QueryAll(aConn, aCacheId, matches);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
} else {
@ -478,19 +516,18 @@ DBSchema::CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const nsID* aRequestBodyId,
const PCacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut)
CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
PCacheQueryParams params(false, false, false, false,
CacheQueryParams params(false, false, false, false,
NS_LITERAL_STRING(""));
nsAutoTArray<EntryId, 256> matches;
nsresult rv = QueryCache(aConn, aCacheId, aRequest, params, matches);
@ -506,12 +543,11 @@ DBSchema::CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut, bool* aSuccessOut)
CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut, bool* aSuccessOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -535,19 +571,18 @@ DBSchema::CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams,
nsTArray<SavedRequest>& aSavedRequestsOut)
CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequestOrVoid& aRequestOrVoid,
const CacheQueryParams& aParams,
nsTArray<SavedRequest>& aSavedRequestsOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
nsresult rv;
nsAutoTArray<EntryId, 256> matches;
if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) {
if (aRequestOrVoid.type() == CacheRequestOrVoid::Tvoid_t) {
rv = QueryAll(aConn, aCacheId, matches);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
} else {
@ -567,14 +602,13 @@ DBSchema::CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::StorageMatch(mozIStorageConnection* aConn,
Namespace aNamespace,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut)
StorageMatch(mozIStorageConnection* aConn,
Namespace aNamespace,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -639,11 +673,10 @@ DBSchema::StorageMatch(mozIStorageConnection* aConn,
return NS_OK;
}
// static
nsresult
DBSchema::StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, bool* aFoundCacheOut,
CacheId* aCacheIdOut)
StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, bool* aFoundCacheOut,
CacheId* aCacheIdOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -679,10 +712,9 @@ DBSchema::StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace,
return rv;
}
// static
nsresult
DBSchema::StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, CacheId aCacheId)
StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, CacheId aCacheId)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -708,10 +740,9 @@ DBSchema::StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace,
return rv;
}
// static
nsresult
DBSchema::StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey)
StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -734,10 +765,9 @@ DBSchema::StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace,
return rv;
}
// static
nsresult
DBSchema::StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
nsTArray<nsString>& aKeysOut)
StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
nsTArray<nsString>& aKeysOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -762,10 +792,11 @@ DBSchema::StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
return rv;
}
// static
namespace {
nsresult
DBSchema::QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<EntryId>& aEntryIdListOut)
QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<EntryId>& aEntryIdListOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -790,13 +821,12 @@ DBSchema::QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
nsTArray<EntryId>& aEntryIdListOut,
uint32_t aMaxResults)
QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<EntryId>& aEntryIdListOut,
uint32_t aMaxResults)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -868,11 +898,10 @@ DBSchema::QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn,
const PCacheRequest& aRequest,
EntryId entryId, bool* aSuccessOut)
MatchByVaryHeader(mozIStorageConnection* aConn,
const CacheRequest& aRequest,
EntryId entryId, bool* aSuccessOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -913,7 +942,8 @@ DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn,
rv = state->BindInt32Parameter(0, entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsRefPtr<InternalHeaders> cachedHeaders = new InternalHeaders(HeadersGuardEnum::None);
nsRefPtr<InternalHeaders> cachedHeaders =
new InternalHeaders(HeadersGuardEnum::None);
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
nsAutoCString name;
@ -930,7 +960,8 @@ DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn,
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsRefPtr<InternalHeaders> queryHeaders = new InternalHeaders(aRequest.headers());
nsRefPtr<InternalHeaders> queryHeaders =
TypeUtils::ToInternalHeaders(aRequest.headers());
// Assume the vary headers match until we find a conflict
bool varyHeadersMatch = true;
@ -979,12 +1010,11 @@ DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn,
return rv;
}
// static
nsresult
DBSchema::DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
uint32_t aPos, int32_t aLen)
DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
uint32_t aPos, int32_t aLen)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -1068,13 +1098,12 @@ DBSchema::DeleteEntries(mozIStorageConnection* aConn,
return rv;
}
// static
nsresult
DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const nsID* aRequestBodyId,
const PCacheResponse& aResponse,
const nsID* aResponseBodyId)
InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -1195,7 +1224,7 @@ DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
const nsTArray<PHeadersEntry>& requestHeaders = aRequest.headers();
const nsTArray<HeadersEntry>& requestHeaders = aRequest.headers();
for (uint32_t i = 0; i < requestHeaders.Length(); ++i) {
rv = state->BindUTF8StringParameter(0, requestHeaders[i].name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1219,7 +1248,7 @@ DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
const nsTArray<PHeadersEntry>& responseHeaders = aResponse.headers();
const nsTArray<HeadersEntry>& responseHeaders = aResponse.headers();
for (uint32_t i = 0; i < responseHeaders.Length(); ++i) {
rv = state->BindUTF8StringParameter(0, responseHeaders[i].name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1237,10 +1266,9 @@ DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
// static
nsresult
DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
SavedResponse* aSavedResponseOut)
ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
SavedResponse* aSavedResponseOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -1320,7 +1348,7 @@ DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
PHeadersEntry header;
HeadersEntry header;
rv = state->GetUTF8String(0, header.name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1334,10 +1362,9 @@ DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
return rv;
}
// static
nsresult
DBSchema::ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
SavedRequest* aSavedRequestOut)
ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
SavedRequest* aSavedRequestOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
@ -1439,7 +1466,7 @@ DBSchema::ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
PHeadersEntry header;
HeadersEntry header;
rv = state->GetUTF8String(0, header.name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1453,11 +1480,10 @@ DBSchema::ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
return rv;
}
// static
void
DBSchema::AppendListParamsToQuery(nsACString& aQuery,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen)
AppendListParamsToQuery(nsACString& aQuery,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT((aPos + aLen) <= aEntryIdList.Length());
@ -1470,11 +1496,10 @@ DBSchema::AppendListParamsToQuery(nsACString& aQuery,
}
}
// static
nsresult
DBSchema::BindListParamsToQuery(mozIStorageStatement* aState,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen)
BindListParamsToQuery(mozIStorageStatement* aState,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT((aPos + aLen) <= aEntryIdList.Length());
@ -1485,9 +1510,8 @@ DBSchema::BindListParamsToQuery(mozIStorageStatement* aState,
return NS_OK;
}
// static
nsresult
DBSchema::BindId(mozIStorageStatement* aState, uint32_t aPos, const nsID* aId)
BindId(mozIStorageStatement* aState, uint32_t aPos, const nsID* aId)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aState);
@ -1507,9 +1531,8 @@ DBSchema::BindId(mozIStorageStatement* aState, uint32_t aPos, const nsID* aId)
return rv;
}
// static
nsresult
DBSchema::ExtractId(mozIStorageStatement* aState, uint32_t aPos, nsID* aIdOut)
ExtractId(mozIStorageStatement* aState, uint32_t aPos, nsID* aIdOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aState);
@ -1525,6 +1548,9 @@ DBSchema::ExtractId(mozIStorageStatement* aState, uint32_t aPos, nsID* aIdOut)
return rv;
}
} // anonymouns namespace
} // namespace db
} // namespace cache
} // namespace dom
} // namespace mozilla

177
dom/cache/DBSchema.h поставляемый
Просмотреть файл

@ -14,129 +14,100 @@
#include "nsTArrayForwardDeclare.h"
class mozIStorageConnection;
class mozIStorageStatement;
struct nsID;
namespace mozilla {
namespace dom {
namespace cache {
class PCacheQueryParams;
class PCacheRequest;
class PCacheRequestOrVoid;
class PCacheResponse;
class CacheQueryParams;
class CacheRequest;
class CacheRequestOrVoid;
class CacheResponse;
struct SavedRequest;
struct SavedResponse;
// TODO: remove static class and use functions in cache namespace (bug 1110485)
class DBSchema final
{
public:
static nsresult CreateSchema(mozIStorageConnection* aConn);
static nsresult InitializeConnection(mozIStorageConnection* aConn);
namespace db {
static nsresult CreateCache(mozIStorageConnection* aConn,
CacheId* aCacheIdOut);
// TODO: improve naming (confusing with CacheDelete) (bug 1110485)
static nsresult DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut);
nsresult
CreateSchema(mozIStorageConnection* aConn);
// TODO: Consider removing unused IsCacheOrphaned after writing cleanup code. (bug 1110446)
static nsresult IsCacheOrphaned(mozIStorageConnection* aConn,
CacheId aCacheId, bool* aOrphanedOut);
nsresult
InitializeConnection(mozIStorageConnection* aConn);
static nsresult CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut);
static nsresult CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams,
nsTArray<SavedResponse>& aSavedResponsesOut);
static nsresult CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const nsID* aRequestBodyId,
const PCacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut);
static nsresult CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut,
bool* aSuccessOut);
static nsresult CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams,
nsTArray<SavedRequest>& aSavedRequestsOut);
nsresult
CreateCacheId(mozIStorageConnection* aConn, CacheId* aCacheIdOut);
static nsresult StorageMatch(mozIStorageConnection* aConn,
Namespace aNamespace,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut);
static nsresult StorageGetCacheId(mozIStorageConnection* aConn,
Namespace aNamespace, const nsAString& aKey,
bool* aFoundCacheOut, CacheId* aCacheIdOut);
static nsresult StoragePutCache(mozIStorageConnection* aConn,
Namespace aNamespace, const nsAString& aKey,
CacheId aCacheId);
static nsresult StorageForgetCache(mozIStorageConnection* aConn,
Namespace aNamespace,
const nsAString& aKey);
static nsresult StorageGetKeys(mozIStorageConnection* aConn,
Namespace aNamespace,
nsTArray<nsString>& aKeysOut);
nsresult
DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut);
// We will wipe out databases with a schema versions less than this.
static const int32_t kMaxWipeSchemaVersion;
// TODO: Consider removing unused IsCacheOrphaned after writing cleanup code. (bug 1110446)
nsresult
IsCacheOrphaned(mozIStorageConnection* aConn, CacheId aCacheId,
bool* aOrphanedOut);
private:
typedef int32_t EntryId;
nsresult
CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest, const CacheQueryParams& aParams,
bool* aFoundResponseOut, SavedResponse* aSavedResponseOut);
static nsresult QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<EntryId>& aEntryIdListOut);
static nsresult QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams,
nsTArray<EntryId>& aEntryIdListOut,
uint32_t aMaxResults = UINT32_MAX);
static nsresult MatchByVaryHeader(mozIStorageConnection* aConn,
const PCacheRequest& aRequest,
EntryId entryId, bool* aSuccessOut);
static nsresult DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
uint32_t aPos=0, int32_t aLen=-1);
static nsresult InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
const PCacheRequest& aRequest,
const nsID* aRequestBodyId,
const PCacheResponse& aResponse,
const nsID* aResponseBodyId);
static nsresult ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
SavedResponse* aSavedResponseOut);
static nsresult ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
SavedRequest* aSavedRequestOut);
nsresult
CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequestOrVoid& aRequestOrVoid,
const CacheQueryParams& aParams,
nsTArray<SavedResponse>& aSavedResponsesOut);
static void AppendListParamsToQuery(nsACString& aQuery,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen);
static nsresult BindListParamsToQuery(mozIStorageStatement* aState,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen);
static nsresult BindId(mozIStorageStatement* aState, uint32_t aPos,
const nsID* aId);
static nsresult ExtractId(mozIStorageStatement* aState, uint32_t aPos,
nsID* aIdOut);
nsresult
CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut);
DBSchema() = delete;
~DBSchema() = delete;
nsresult
CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut,
bool* aSuccessOut);
static const int32_t kLatestSchemaVersion;
static const int32_t kMaxEntriesPerStatement;
};
nsresult
CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequestOrVoid& aRequestOrVoid,
const CacheQueryParams& aParams,
nsTArray<SavedRequest>& aSavedRequestsOut);
nsresult
StorageMatch(mozIStorageConnection* aConn,
Namespace aNamespace,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
bool* aFoundResponseOut,
SavedResponse* aSavedResponseOut);
nsresult
StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, bool* aFoundCacheOut,
CacheId* aCacheIdOut);
nsresult
StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey, CacheId aCacheId);
nsresult
StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace,
const nsAString& aKey);
nsresult
StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
nsTArray<nsString>& aKeysOut);
// We will wipe out databases with a schema versions less than this.
extern const int32_t kMaxWipeSchemaVersion;
} // namespace db
} // namespace cache
} // namespace dom
} // namespace mozilla

70
dom/cache/FetchPut.cpp поставляемый
Просмотреть файл

@ -16,7 +16,6 @@
#include "mozilla/dom/ResponseBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
@ -98,9 +97,8 @@ private:
// static
nsresult
FetchPut::Create(Listener* aListener, Manager* aManager,
RequestId aRequestId, CacheId aCacheId,
const nsTArray<PCacheRequest>& aRequests,
FetchPut::Create(Listener* aListener, Manager* aManager, CacheId aCacheId,
const nsTArray<CacheRequest>& aRequests,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams,
FetchPut** aFetchPutOut)
{
@ -115,7 +113,7 @@ FetchPut::Create(Listener* aListener, Manager* aManager,
}
#endif
nsRefPtr<FetchPut> ref = new FetchPut(aListener, aManager, aRequestId, aCacheId,
nsRefPtr<FetchPut> ref = new FetchPut(aListener, aManager, aCacheId,
aRequests, aRequestStreams);
nsresult rv = ref->DispatchToMainThread();
@ -133,13 +131,11 @@ FetchPut::ClearListener()
mListener = nullptr;
}
FetchPut::FetchPut(Listener* aListener, Manager* aManager,
RequestId aRequestId, CacheId aCacheId,
const nsTArray<PCacheRequest>& aRequests,
FetchPut::FetchPut(Listener* aListener, Manager* aManager, CacheId aCacheId,
const nsTArray<CacheRequest>& aRequests,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams)
: mListener(aListener)
, mManager(aManager)
, mRequestId(aRequestId)
, mCacheId(aCacheId)
, mInitiatingThread(NS_GetCurrentThread())
, mStateList(aRequests.Length())
@ -151,7 +147,7 @@ FetchPut::FetchPut(Listener* aListener, Manager* aManager,
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
State* s = mStateList.AppendElement();
s->mPCacheRequest = aRequests[i];
s->mCacheRequest = aRequests[i];
s->mRequestStream = aRequestStreams[i];
}
@ -211,14 +207,14 @@ FetchPut::DoFetchOnMainThread()
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal);
if (NS_WARN_IF(NS_FAILED(rv))) {
MaybeSetError(rv);
MaybeSetError(ErrorResult(rv));
MaybeCompleteOnMainThread();
return;
}
for (uint32_t i = 0; i < mStateList.Length(); ++i) {
nsRefPtr<InternalRequest> internalRequest =
ToInternalRequest(mStateList[i].mPCacheRequest);
ToInternalRequest(mStateList[i].mCacheRequest);
// If there is a stream we must clone it so that its still available
// to store in the cache later;
@ -240,7 +236,7 @@ FetchPut::DoFetchOnMainThread()
mStateList[i].mFetchObserver = new FetchObserver(this);
rv = fetchDriver->Fetch(mStateList[i].mFetchObserver);
if (NS_WARN_IF(NS_FAILED(rv))) {
MaybeSetError(rv);
MaybeSetError(ErrorResult(rv));
mStateList[i].mFetchObserver = nullptr;
mPendingCount -= 1;
continue;
@ -258,16 +254,16 @@ FetchPut::FetchComplete(FetchObserver* aObserver,
MOZ_ASSERT(NS_IsMainThread());
if (aInternalResponse->IsError() && !mResult.Failed()) {
MaybeSetError(NS_ERROR_FAILURE);
MaybeSetError(ErrorResult(NS_ERROR_FAILURE));
}
for (uint32_t i = 0; i < mStateList.Length(); ++i) {
if (mStateList[i].mFetchObserver == aObserver) {
ErrorResult rv;
ToPCacheResponseWithoutBody(mStateList[i].mPCacheResponse,
ToCacheResponseWithoutBody(mStateList[i].mCacheResponse,
*aInternalResponse, rv);
if (rv.Failed()) {
mResult = Move(rv);
MaybeSetError(Move(rv));
} else {
aInternalResponse->GetBody(getter_AddRefs(mStateList[i].mResponseStream));
}
@ -316,27 +312,27 @@ FetchPut::DoPutOnWorkerThread()
for (uint32_t i = 0; i < mStateList.Length(); ++i) {
// The spec requires us to catch if content tries to insert a set of
// requests that would overwrite each other.
if (MatchInPutList(mStateList[i].mPCacheRequest, putList)) {
MaybeSetError(NS_ERROR_DOM_INVALID_STATE_ERR);
if (MatchInPutList(mStateList[i].mCacheRequest, putList)) {
MaybeSetError(ErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
MaybeNotifyListener();
return;
}
CacheRequestResponse* entry = putList.AppendElement();
entry->request() = mStateList[i].mPCacheRequest;
entry->response() = mStateList[i].mPCacheResponse;
entry->request() = mStateList[i].mCacheRequest;
entry->response() = mStateList[i].mCacheResponse;
requestStreamList.AppendElement(mStateList[i].mRequestStream.forget());
responseStreamList.AppendElement(mStateList[i].mResponseStream.forget());
}
mStateList.Clear();
mManager->CachePutAll(this, mRequestId, mCacheId, putList, requestStreamList,
responseStreamList);
mManager->ExecutePutAll(this, mCacheId, putList, requestStreamList,
responseStreamList);
}
// static
bool
FetchPut::MatchInPutList(const PCacheRequest& aRequest,
FetchPut::MatchInPutList(const CacheRequest& aRequest,
const nsTArray<CacheRequestResponse>& aPutList)
{
// This method implements the SW spec QueryCache algorithm against an
@ -351,11 +347,11 @@ FetchPut::MatchInPutList(const PCacheRequest& aRequest,
}
nsRefPtr<InternalHeaders> requestHeaders =
new InternalHeaders(aRequest.headers());
ToInternalHeaders(aRequest.headers());
for (uint32_t i = 0; i < aPutList.Length(); ++i) {
const PCacheRequest& cachedRequest = aPutList[i].request();
const PCacheResponse& cachedResponse = aPutList[i].response();
const CacheRequest& cachedRequest = aPutList[i].request();
const CacheResponse& cachedResponse = aPutList[i].response();
// If the URLs don't match, then just skip to the next entry.
if (aRequest.url() != cachedRequest.url()) {
@ -363,10 +359,10 @@ FetchPut::MatchInPutList(const PCacheRequest& aRequest,
}
nsRefPtr<InternalHeaders> cachedRequestHeaders =
new InternalHeaders(cachedRequest.headers());
ToInternalHeaders(cachedRequest.headers());
nsRefPtr<InternalHeaders> cachedResponseHeaders =
new InternalHeaders(cachedResponse.headers());
ToInternalHeaders(cachedResponse.headers());
nsAutoTArray<nsCString, 16> varyHeaders;
ErrorResult rv;
@ -426,20 +422,25 @@ FetchPut::MatchInPutList(const PCacheRequest& aRequest,
}
void
FetchPut::OnCachePutAll(RequestId aRequestId, nsresult aRv)
FetchPut::OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId,
const nsTArray<SavedResponse>& aSavedResponseList,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList)
{
MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread());
MaybeSetError(aRv);
MOZ_ASSERT(aResult.type() == CacheOpResult::TCachePutAllResult);
MaybeSetError(Move(aRv));
MaybeNotifyListener();
}
void
FetchPut::MaybeSetError(nsresult aRv)
FetchPut::MaybeSetError(ErrorResult&& aRv)
{
if (mResult.Failed() || NS_SUCCEEDED(aRv)) {
if (mResult.Failed() || !aRv.Failed()) {
return;
}
mResult.Throw(aRv);
mResult = Move(aRv);
}
void
@ -453,8 +454,7 @@ FetchPut::MaybeNotifyListener()
// object is removed from CacheParent::mFetchPutList, so make sure that
// doesn't happen until this method returns.
nsRefPtr<FetchPut> kungFuDeathGrip(this);
mListener->OnFetchPut(this, mRequestId, mResult);
mResult.ClearMessage(); // This may contain a TypeError.
mListener->OnFetchPut(this, Move(mResult));
}
nsIGlobalObject*

31
dom/cache/FetchPut.h поставляемый
Просмотреть файл

@ -11,7 +11,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsRefPtr.h"
@ -40,13 +40,12 @@ public:
{
public:
virtual void
OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, const ErrorResult& aRv) = 0;
OnFetchPut(FetchPut* aFetchPut, ErrorResult&& aRv) = 0;
};
static nsresult
Create(Listener* aListener, Manager* aManager,
RequestId aRequestId, CacheId aCacheId,
const nsTArray<PCacheRequest>& aRequests,
Create(Listener* aListener, Manager* aManager, CacheId aCacheId,
const nsTArray<CacheRequest>& aRequests,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams,
FetchPut** aFetchPutOut);
@ -58,19 +57,18 @@ private:
friend class FetchObserver;
struct State
{
PCacheRequest mPCacheRequest;
CacheRequest mCacheRequest;
nsCOMPtr<nsIInputStream> mRequestStream;
nsRefPtr<FetchObserver> mFetchObserver;
PCacheResponse mPCacheResponse;
CacheResponse mCacheResponse;
nsCOMPtr<nsIInputStream> mResponseStream;
nsRefPtr<Request> mRequest;
nsRefPtr<Response> mResponse;
};
FetchPut(Listener* aListener, Manager* aManager,
RequestId aRequestId, CacheId aCacheId,
const nsTArray<PCacheRequest>& aRequests,
FetchPut(Listener* aListener, Manager* aManager, CacheId aCacheId,
const nsTArray<CacheRequest>& aRequests,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams);
~FetchPut();
@ -83,11 +81,17 @@ private:
void MaybeCompleteOnMainThread();
void DoPutOnWorkerThread();
static bool MatchInPutList(const PCacheRequest& aRequest,
static bool MatchInPutList(const CacheRequest& aRequest,
const nsTArray<CacheRequestResponse>& aPutList);
virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) override;
void MaybeSetError(nsresult aRv);
virtual void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId,
const nsTArray<SavedResponse>& aSavedResponseList,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList) override;
void MaybeSetError(ErrorResult&& aRv);
void MaybeNotifyListener();
// TypeUtils methods
@ -101,7 +105,6 @@ private:
Listener* mListener;
nsRefPtr<Manager> mManager;
const RequestId mRequestId;
const CacheId mCacheId;
nsCOMPtr<nsIThread> mInitiatingThread;
nsTArray<State> mStateList;

51
dom/cache/FileUtils.cpp поставляемый
Просмотреть файл

@ -23,11 +23,24 @@ namespace cache {
using mozilla::dom::quota::FileInputStream;
using mozilla::dom::quota::FileOutputStream;
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
using mozilla::unused;
namespace {
enum BodyFileType
{
BODY_FILE_FINAL,
BODY_FILE_TMP
};
nsresult
BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
nsIFile** aBodyFileOut);
} // anonymous namespace
// static
nsresult
FileUtils::BodyCreateDir(nsIFile* aBaseDir)
BodyCreateDir(nsIFile* aBaseDir)
{
MOZ_ASSERT(aBaseDir);
@ -49,7 +62,7 @@ FileUtils::BodyCreateDir(nsIFile* aBaseDir)
// static
nsresult
FileUtils::BodyDeleteDir(nsIFile* aBaseDir)
BodyDeleteDir(nsIFile* aBaseDir)
{
MOZ_ASSERT(aBaseDir);
@ -72,8 +85,7 @@ FileUtils::BodyDeleteDir(nsIFile* aBaseDir)
// static
nsresult
FileUtils::BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId,
nsIFile** aCacheDirOut)
BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId, nsIFile** aCacheDirOut)
{
MOZ_ASSERT(aBaseDir);
MOZ_ASSERT(aCacheDirOut);
@ -107,11 +119,11 @@ FileUtils::BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId,
// static
nsresult
FileUtils::BodyStartWriteStream(const QuotaInfo& aQuotaInfo,
nsIFile* aBaseDir, nsIInputStream* aSource,
void* aClosure,
nsAsyncCopyCallbackFun aCallback, nsID* aIdOut,
nsISupports** aCopyContextOut)
BodyStartWriteStream(const QuotaInfo& aQuotaInfo,
nsIFile* aBaseDir, nsIInputStream* aSource,
void* aClosure,
nsAsyncCopyCallbackFun aCallback, nsID* aIdOut,
nsISupports** aCopyContextOut)
{
MOZ_ASSERT(aBaseDir);
MOZ_ASSERT(aSource);
@ -168,7 +180,7 @@ FileUtils::BodyStartWriteStream(const QuotaInfo& aQuotaInfo,
// static
void
FileUtils::BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext)
BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext)
{
MOZ_ASSERT(aBaseDir);
MOZ_ASSERT(aCopyContext);
@ -182,7 +194,7 @@ FileUtils::BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext)
// static
nsresult
FileUtils::BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId)
BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId)
{
MOZ_ASSERT(aBaseDir);
@ -206,8 +218,8 @@ FileUtils::BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId)
// static
nsresult
FileUtils::BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
const nsID& aId, nsIInputStream** aStreamOut)
BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
nsIInputStream** aStreamOut)
{
MOZ_ASSERT(aBaseDir);
MOZ_ASSERT(aStreamOut);
@ -234,7 +246,7 @@ FileUtils::BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
// static
nsresult
FileUtils::BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList)
BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList)
{
nsresult rv = NS_OK;
@ -273,10 +285,11 @@ FileUtils::BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList)
return NS_OK;
}
// static
namespace {
nsresult
FileUtils::BodyIdToFile(nsIFile* aBaseDir, const nsID& aId,
BodyFileType aType, nsIFile** aBodyFileOut)
BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
nsIFile** aBodyFileOut)
{
MOZ_ASSERT(aBaseDir);
MOZ_ASSERT(aBodyFileOut);
@ -304,6 +317,8 @@ FileUtils::BodyIdToFile(nsIFile* aBaseDir, const nsID& aId,
return rv;
}
} // anonymous namespace
} // namespace cache
} // namespace dom
} // namespace mozilla

61
dom/cache/FileUtils.h поставляемый
Просмотреть файл

@ -19,51 +19,36 @@ namespace mozilla {
namespace dom {
namespace cache {
// TODO: remove static class and use functions in cache namespace (bug 1110485)
class FileUtils final
{
public:
enum BodyFileType
{
BODY_FILE_FINAL,
BODY_FILE_TMP
};
nsresult
BodyCreateDir(nsIFile* aBaseDir);
static nsresult BodyCreateDir(nsIFile* aBaseDir);
// Note that this function can only be used during the initialization of the
// database. We're unlikely to be able to delete the DB successfully past
// that point due to the file being in use.
static nsresult BodyDeleteDir(nsIFile* aBaseDir);
static nsresult BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId,
nsIFile** aCacheDirOut);
// Note that this function can only be used during the initialization of the
// database. We're unlikely to be able to delete the DB successfully past
// that point due to the file being in use.
nsresult
BodyDeleteDir(nsIFile* aBaseDir);
static nsresult
BodyStartWriteStream(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
nsIInputStream* aSource, void* aClosure,
nsAsyncCopyCallbackFun aCallback, nsID* aIdOut,
nsISupports** aCopyContextOut);
nsresult
BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId, nsIFile** aCacheDirOut);
static void
BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext);
nsresult
BodyStartWriteStream(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
nsIInputStream* aSource, void* aClosure,
nsAsyncCopyCallbackFun aCallback, nsID* aIdOut,
nsISupports** aCopyContextOut);
static nsresult
BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId);
void
BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext);
static nsresult
BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
nsIInputStream** aStreamOut);
nsresult
BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId);
static nsresult
BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList);
nsresult
BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
nsIInputStream** aStreamOut);
private:
static nsresult
BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
nsIFile** aBodyFileOut);
FileUtils() = delete;
~FileUtils() = delete;
};
nsresult
BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList);
} // namespace cache
} // namespace dom

37
dom/cache/IPCUtils.h поставляемый
Просмотреть файл

@ -8,10 +8,47 @@
#define mozilla_dom_cache_IPCUtils_h
#include "ipc/IPCMessageUtils.h"
// Fix X11 header brain damage that conflicts with HeadersGuardEnum::None
#undef None
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/ResponseBinding.h"
#include "mozilla/dom/cache/Types.h"
namespace IPC {
template<>
struct ParamTraits<mozilla::dom::HeadersGuardEnum> :
public ContiguousEnumSerializer<mozilla::dom::HeadersGuardEnum,
mozilla::dom::HeadersGuardEnum::None,
mozilla::dom::HeadersGuardEnum::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::RequestMode> :
public ContiguousEnumSerializer<mozilla::dom::RequestMode,
mozilla::dom::RequestMode::Same_origin,
mozilla::dom::RequestMode::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::RequestCredentials> :
public ContiguousEnumSerializer<mozilla::dom::RequestCredentials,
mozilla::dom::RequestCredentials::Omit,
mozilla::dom::RequestCredentials::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::RequestCache> :
public ContiguousEnumSerializer<mozilla::dom::RequestCache,
mozilla::dom::RequestCache::Default,
mozilla::dom::RequestCache::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::RequestContext> :
public ContiguousEnumSerializer<mozilla::dom::RequestContext,
mozilla::dom::RequestContext::Audio,
mozilla::dom::RequestContext::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::ResponseType> :
public ContiguousEnumSerializer<mozilla::dom::ResponseType,
mozilla::dom::ResponseType::Basic,
mozilla::dom::ResponseType::EndGuard_> {};
template<>
struct ParamTraits<mozilla::dom::cache::Namespace> :
public ContiguousEnumSerializer<mozilla::dom::cache::Namespace,
mozilla::dom::cache::DEFAULT_NAMESPACE,

656
dom/cache/Manager.cpp поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

103
dom/cache/Manager.h поставляемый
Просмотреть файл

@ -7,11 +7,10 @@
#ifndef mozilla_dom_cache_Manager_h
#define mozilla_dom_cache_Manager_h
#include "mozilla/dom/cache/CacheInitData.h"
#include "mozilla/dom/cache/PCacheStreamControlParent.h"
#include "mozilla/dom/cache/Types.h"
#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"
#include "nsRefPtr.h"
#include "nsString.h"
#include "nsTArray.h"
@ -22,12 +21,11 @@ namespace mozilla {
namespace dom {
namespace cache {
class CacheOpArgs;
class CacheOpResult;
class CacheRequestResponse;
class Context;
class ManagerId;
class PCacheQueryParams;
class PCacheRequest;
class PCacheRequestOrVoid;
struct SavedRequest;
struct SavedResponse;
class StreamList;
@ -86,30 +84,36 @@ public:
class Listener
{
public:
virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aResponse,
StreamList* aStreamList) { }
virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedResponse>& aSavedResponses,
StreamList* aStreamList) { }
virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) { }
virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv,
bool aSuccess) { }
virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<SavedRequest>& aSavedRequests,
StreamList* aStreamList) { }
// convenience routines
void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult);
virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv,
const SavedResponse* aResponse,
StreamList* aStreamList) { }
virtual void OnStorageHas(RequestId aRequestId, nsresult aRv,
bool aCacheFound) { }
virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv,
CacheId aCacheId) { }
virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv,
bool aCacheDeleted) { }
virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv,
const nsTArray<nsString>& aKeys) { }
void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId);
void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
const SavedResponse& aSavedResponse,
StreamList* aStreamList);
void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
const nsTArray<SavedResponse>& aSavedResponseList,
StreamList* aStreamList);
void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList);
// interface to be implemented
virtual void
OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
CacheId aOpenedCacheId,
const nsTArray<SavedResponse>& aSavedResponseList,
const nsTArray<SavedRequest>& aSavedRequestList,
StreamList* aStreamList) { }
protected:
~Listener() { }
@ -129,8 +133,8 @@ public:
// Marks the Manager "invalid". Once the Context completes no new operations
// will be permitted with this Manager. New actors will get a new Manager.
void Invalidate();
bool IsValid() const;
void NoteClosing();
bool IsClosing() const;
// If an actor represents a long term reference to a cache or body stream,
// then they must call AddRefCacheId() or AddRefBodyId(). This will
@ -150,35 +154,15 @@ public:
void AddStreamList(StreamList* aStreamList);
void RemoveStreamList(StreamList* aStreamList);
// TODO: consider moving CacheId up in the argument lists below (bug 1110485)
void CacheMatch(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
const PCacheRequest& aRequest,
const PCacheQueryParams& aParams);
void CacheMatchAll(Listener* aListener, RequestId aRequestId,
CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams);
void CachePutAll(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
const nsTArray<CacheRequestResponse>& aPutList,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList);
void CacheDelete(Listener* aListener, RequestId aRequestId,
CacheId aCacheId, const PCacheRequest& aRequest,
const PCacheQueryParams& aParams);
void CacheKeys(Listener* aListener, RequestId aRequestId,
CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid,
const PCacheQueryParams& aParams);
void ExecuteCacheOp(Listener* aListener, CacheId aCacheId,
const CacheOpArgs& aOpArgs);
void ExecutePutAll(Listener* aListener, CacheId aCacheId,
const nsTArray<CacheRequestResponse>& aPutList,
const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList);
void StorageMatch(Listener* aListener, RequestId aRequestId,
Namespace aNamespace, const PCacheRequest& aRequest,
const PCacheQueryParams& aParams);
void StorageHas(Listener* aListener, RequestId aRequestId,
Namespace aNamespace, const nsAString& aKey);
void StorageOpen(Listener* aListener, RequestId aRequestId,
Namespace aNamespace, const nsAString& aKey);
void StorageDelete(Listener* aListener, RequestId aRequestId,
Namespace aNamespace, const nsAString& aKey);
void StorageKeys(Listener* aListener, RequestId aRequestId,
Namespace aNamespace);
void ExecuteStorageOp(Listener* aListener, Namespace aNamespace,
const CacheOpArgs& aOpArgs);
private:
class Factory;
@ -201,6 +185,7 @@ private:
Manager(ManagerId* aManagerId, nsIThread* aIOThread);
~Manager();
void Init();
void Shutdown();
already_AddRefed<Context> CurrentContext();
@ -264,7 +249,7 @@ private:
nsTArray<StreamList*> mStreamLists;
bool mShuttingDown;
bool mValid;
bool mClosing;
struct CacheIdRefCounter
{

27
dom/cache/PCache.ipdl поставляемый
Просмотреть файл

@ -3,16 +3,13 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PBlob; // FIXME: bug 792908
include protocol PCacheOp;
include protocol PCachePushStream;
include PCacheTypes;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PBlob; // FIXME: bug 792908
include protocol PCacheStreamControl;
using mozilla::dom::cache::RequestId from "mozilla/dom/cache/Types.h";
using mozilla::ErrorResult from "ipc/ErrorIPCUtils.h";
include "mozilla/dom/cache/IPCUtils.h";
include CacheTypes;
namespace mozilla {
namespace dom {
@ -21,27 +18,15 @@ namespace cache {
protocol PCache
{
manager PBackground;
manages PCacheOp;
manages PCachePushStream;
parent:
PCacheOp(CacheOpArgs aOpArgs);
PCachePushStream();
Teardown();
Match(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
MatchAll(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
AddAll(RequestId requestId, PCacheRequest[] requests);
Put(RequestId requestId, CacheRequestResponse aPut);
Delete(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
Keys(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
child:
MatchResponse(RequestId requestId, nsresult aRv, PCacheResponseOrVoid aResponse);
MatchAllResponse(RequestId requestId, nsresult aRv, PCacheResponse[] responses);
AddAllResponse(RequestId requestId, ErrorResult aRv);
PutResponse(RequestId requestId, nsresult aRv);
DeleteResponse(RequestId requestId, nsresult aRv, bool success);
KeysResponse(RequestId requestId, nsresult aRv, PCacheRequest[] requests);
both:
__delete__();
};

29
dom/cache/PCacheOp.ipdl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
/* 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 PCache;
include protocol PCachePushStream;
include protocol PCacheStorage;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include CacheTypes;
using mozilla::ErrorResult from "ipc/ErrorIPCUtils.h";
namespace mozilla {
namespace dom {
namespace cache {
protocol PCacheOp
{
manager PCache or PCacheStorage;
child:
__delete__(ErrorResult aRv, CacheOpResult aResult);
};
} // namespace cache
} // namespace dom
} // namespace mozilla

23
dom/cache/PCacheStorage.ipdl поставляемый
Просмотреть файл

@ -3,14 +3,13 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PBlob; // FIXME: bug 792908
include protocol PCache;
include PCacheTypes;
include protocol PCacheOp;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PBlob; // FIXME: bug 792908
include protocol PCacheStreamControl;
using mozilla::dom::cache::RequestId from "mozilla/dom/cache/IPCUtils.h";
include CacheTypes;
namespace mozilla {
namespace dom {
@ -19,23 +18,13 @@ namespace cache {
protocol PCacheStorage
{
manager PBackground;
manages PCacheOp;
parent:
PCacheOp(CacheOpArgs aOpArgs);
Teardown();
Match(RequestId aRequestId, PCacheRequest aRequest,
PCacheQueryParams aParams);
Has(RequestId aRequestId, nsString aKey);
Open(RequestId aRequestId, nsString aKey);
Delete(RequestId aRequestId, nsString aKey);
Keys(RequestId aRequestId);
child:
MatchResponse(RequestId aRequestId, nsresult aRv,
PCacheResponseOrVoid aResponseOrVoid);
HasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
OpenResponse(RequestId aRequestId, nsresult aRv, nullable PCache aActor);
DeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
KeysResponse(RequestId aRequestId, nsresult aRv, nsString[] aKeys);
__delete__();
};

95
dom/cache/PCacheTypes.ipdlh поставляемый
Просмотреть файл

@ -1,95 +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/. */
include protocol PCachePushStream;
include protocol PCacheStreamControl;
include PHeaders;
include InputStreamParams;
using HeadersGuardEnum from "mozilla/dom/FetchIPCUtils.h";
using RequestCredentials from "mozilla/dom/FetchIPCUtils.h";
using RequestMode from "mozilla/dom/FetchIPCUtils.h";
using RequestCache from "mozilla/dom/FetchIPCUtils.h";
using RequestContext from "mozilla/dom/FetchIPCUtils.h";
using mozilla::dom::ResponseType from "mozilla/dom/FetchIPCUtils.h";
using mozilla::void_t from "ipc/IPCMessageUtils.h";
using struct nsID from "nsID.h";
namespace mozilla {
namespace dom {
namespace cache {
struct PCacheQueryParams
{
bool ignoreSearch;
bool ignoreMethod;
bool ignoreVary;
bool cacheNameSet;
nsString cacheName;
};
struct PCacheReadStream
{
nsID id;
OptionalInputStreamParams params;
OptionalFileDescriptorSet fds;
nullable PCacheStreamControl control;
nullable PCachePushStream pushStream;
};
union PCacheReadStreamOrVoid
{
void_t;
PCacheReadStream;
};
struct PCacheRequest
{
nsCString method;
nsString url;
nsString urlWithoutQuery;
PHeadersEntry[] headers;
HeadersGuardEnum headersGuard;
nsString referrer;
RequestMode mode;
RequestCredentials credentials;
PCacheReadStreamOrVoid body;
uint32_t contentPolicyType;
RequestContext context;
RequestCache requestCache;
};
union PCacheRequestOrVoid
{
void_t;
PCacheRequest;
};
struct PCacheResponse
{
ResponseType type;
nsString url;
uint32_t status;
nsCString statusText;
PHeadersEntry[] headers;
HeadersGuardEnum headersGuard;
PCacheReadStreamOrVoid body;
nsCString securityInfo;
};
union PCacheResponseOrVoid
{
void_t;
PCacheResponse;
};
struct CacheRequestResponse
{
PCacheRequest request;
PCacheResponse response;
};
} // namespace cache
} // namespace dom
} // namespace mozilla

38
dom/cache/PrincipalVerifier.cpp поставляемый
Просмотреть файл

@ -46,25 +46,35 @@ PrincipalVerifier::CreateAndDispatch(Listener* aListener,
}
void
PrincipalVerifier::ClearListener()
PrincipalVerifier::AddListener(Listener* aListener)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mListener);
mListener = nullptr;
MOZ_ASSERT(aListener);
MOZ_ASSERT(!mListenerList.Contains(aListener));
mListenerList.AppendElement(aListener);
}
void
PrincipalVerifier::RemoveListener(Listener* aListener)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aListener);
MOZ_ALWAYS_TRUE(mListenerList.RemoveElement(aListener));
}
PrincipalVerifier::PrincipalVerifier(Listener* aListener,
PBackgroundParent* aActor,
const PrincipalInfo& aPrincipalInfo)
: mListener(aListener)
, mActor(BackgroundParent::GetContentParent(aActor))
: mActor(BackgroundParent::GetContentParent(aActor))
, mPrincipalInfo(aPrincipalInfo)
, mInitiatingThread(NS_GetCurrentThread())
, mResult(NS_OK)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mListener);
MOZ_ASSERT(mInitiatingThread);
MOZ_ASSERT(aListener);
mListenerList.AppendElement(aListener);
}
PrincipalVerifier::~PrincipalVerifier()
@ -73,7 +83,7 @@ PrincipalVerifier::~PrincipalVerifier()
// threads, its a race to see which thread de-refs us last. Therefore
// we cannot guarantee which thread we destruct on.
MOZ_ASSERT(!mListener);
MOZ_ASSERT(mListenerList.IsEmpty());
// We should always be able to explicitly release the actor on the main
// thread.
@ -172,17 +182,13 @@ void
PrincipalVerifier::CompleteOnInitiatingThread()
{
AssertIsOnBackgroundThread();
// This can happen if the listener is destroyed before we finish. For
// example, if the child process OOMs and the actor is destroyed.
if (!mListener) {
return;
ListenerList::ForwardIterator iter(mListenerList);
while (iter.HasMore()) {
iter.GetNext()->OnPrincipalVerified(mResult, mManagerId);
}
mListener->OnPrincipalVerified(mResult, mManagerId);
// The listener must clear their reference in OnPrincipalVerified()
MOZ_ASSERT(!mListener);
// The listener must clear its reference in OnPrincipalVerified()
MOZ_ASSERT(mListenerList.IsEmpty());
}
void

14
dom/cache/PrincipalVerifier.h поставляемый
Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsThreadUtils.h"
#include "nsTObserverArray.h"
namespace mozilla {
@ -26,7 +27,7 @@ class PrincipalVerifier final : public nsRunnable
public:
// An interface to be implemented by code wishing to use the
// PrincipalVerifier. Note, the Listener implementation is responsible
// for calling ClearListener() on the PrincipalVerifier to clear the
// for calling RemoveListener() on the PrincipalVerifier to clear the
// weak reference.
class Listener
{
@ -38,9 +39,11 @@ public:
CreateAndDispatch(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
// The Listener must call ClearListener() when OnPrincipalVerified() is
void AddListener(Listener* aListener);
// The Listener must call RemoveListener() when OnPrincipalVerified() is
// called or when the Listener is destroyed.
void ClearListener();
void RemoveListener(Listener* aListener);
private:
PrincipalVerifier(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor,
@ -52,8 +55,9 @@ private:
void DispatchToInitiatingThread(nsresult aRv);
// Weak reference cleared by ClearListener()
Listener* mListener;
// Weak reference cleared by RemoveListener()
typedef nsTObserverArray<Listener*> ListenerList;
ListenerList mListenerList;
// set in originating thread at construction, but must be accessed and
// released on main thread

49
dom/cache/ReadStream.cpp поставляемый
Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/unused.h"
#include "mozilla/dom/cache/CacheStreamControlChild.h"
#include "mozilla/dom/cache/CacheStreamControlParent.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/SnappyUncompressInputStream.h"
@ -35,10 +35,10 @@ public:
nsIInputStream* aStream);
void
Serialize(PCacheReadStreamOrVoid* aReadStreamOut);
Serialize(CacheReadStreamOrVoid* aReadStreamOut);
void
Serialize(PCacheReadStream* aReadStreamOut);
Serialize(CacheReadStream* aReadStreamOut);
// ReadStream::Controllable methods
virtual void
@ -50,6 +50,9 @@ public:
virtual bool
MatchId(const nsID& aId) const override;
virtual bool
HasEverBeenRead() const override;
// Simulate nsIInputStream methods, but we don't actually inherit from it
NS_METHOD
Close();
@ -103,6 +106,7 @@ private:
NumStates
};
Atomic<State> mState;
Atomic<bool> mHasEverBeenRead;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(cache::ReadStream::Inner, override)
};
@ -193,17 +197,17 @@ ReadStream::Inner::Inner(StreamControl* aControl, const nsID& aId,
}
void
ReadStream::Inner::Serialize(PCacheReadStreamOrVoid* aReadStreamOut)
ReadStream::Inner::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
{
MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
MOZ_ASSERT(aReadStreamOut);
PCacheReadStream stream;
CacheReadStream stream;
Serialize(&stream);
*aReadStreamOut = stream;
}
void
ReadStream::Inner::Serialize(PCacheReadStream* aReadStreamOut)
ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut)
{
MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
MOZ_ASSERT(aReadStreamOut);
@ -249,6 +253,13 @@ ReadStream::Inner::MatchId(const nsID& aId) const
return mId.Equals(aId);
}
bool
ReadStream::Inner::HasEverBeenRead() const
{
MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
return mHasEverBeenRead;
}
NS_IMETHODIMP
ReadStream::Inner::Close()
{
@ -284,6 +295,8 @@ ReadStream::Inner::Read(char* aBuf, uint32_t aCount, uint32_t* aNumReadOut)
Close();
}
mHasEverBeenRead = true;
return rv;
}
@ -294,6 +307,10 @@ ReadStream::Inner::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
// stream ops can happen on any thread
MOZ_ASSERT(aNumReadOut);
if (aCount) {
mHasEverBeenRead = true;
}
nsresult rv = mSnappyStream->ReadSegments(aWriter, aClosure, aCount,
aNumReadOut);
@ -302,6 +319,14 @@ ReadStream::Inner::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
Close();
}
// Verify bytes were actually read before marking as being ever read. For
// example, code can test if the stream supports ReadSegments() by calling
// this method with a dummy callback which doesn't read anything. We don't
// want to trigger on that.
if (*aNumReadOut) {
mHasEverBeenRead = true;
}
return rv;
}
@ -391,18 +416,18 @@ NS_IMPL_ISUPPORTS(cache::ReadStream, nsIInputStream, ReadStream);
// static
already_AddRefed<ReadStream>
ReadStream::Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid)
ReadStream::Create(const CacheReadStreamOrVoid& aReadStreamOrVoid)
{
if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
return nullptr;
}
return Create(aReadStreamOrVoid.get_PCacheReadStream());
return Create(aReadStreamOrVoid.get_CacheReadStream());
}
// static
already_AddRefed<ReadStream>
ReadStream::Create(const PCacheReadStream& aReadStream)
ReadStream::Create(const CacheReadStream& aReadStream)
{
// The parameter may or may not be for a Cache created stream. The way we
// tell is by looking at the stream control actor. If the actor exists,
@ -457,13 +482,13 @@ ReadStream::Create(PCacheStreamControlParent* aControl, const nsID& aId,
}
void
ReadStream::Serialize(PCacheReadStreamOrVoid* aReadStreamOut)
ReadStream::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
{
mInner->Serialize(aReadStreamOut);
}
void
ReadStream::Serialize(PCacheReadStream* aReadStreamOut)
ReadStream::Serialize(CacheReadStream* aReadStreamOut)
{
mInner->Serialize(aReadStreamOut);
}

15
dom/cache/ReadStream.h поставляемый
Просмотреть файл

@ -21,8 +21,8 @@ namespace mozilla {
namespace dom {
namespace cache {
class PCacheReadStream;
class PCacheReadStreamOrVoid;
class CacheReadStream;
class CacheReadStreamOrVoid;
class PCacheStreamControlParent;
// IID for the dom::cache::ReadStream interface
@ -63,6 +63,9 @@ public:
virtual bool
MatchId(const nsID& aId) const = 0;
virtual bool
HasEverBeenRead() const = 0;
NS_IMETHOD_(MozExternalRefCountType)
AddRef(void) = 0;
@ -71,17 +74,17 @@ public:
};
static already_AddRefed<ReadStream>
Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid);
Create(const CacheReadStreamOrVoid& aReadStreamOrVoid);
static already_AddRefed<ReadStream>
Create(const PCacheReadStream& aReadStream);
Create(const CacheReadStream& aReadStream);
static already_AddRefed<ReadStream>
Create(PCacheStreamControlParent* aControl, const nsID& aId,
nsIInputStream* aStream);
void Serialize(PCacheReadStreamOrVoid* aReadStreamOut);
void Serialize(PCacheReadStream* aReadStreamOut);
void Serialize(CacheReadStreamOrVoid* aReadStreamOut);
void Serialize(CacheReadStream* aReadStreamOut);
private:
class Inner;

6
dom/cache/SavedTypes.h поставляемый
Просмотреть файл

@ -10,7 +10,7 @@
// NOTE: This cannot be rolled into Types.h because the IPC dependency.
// breaks webidl unified builds.
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/Types.h"
#include "nsCOMPtr.h"
#include "nsID.h"
@ -23,7 +23,7 @@ namespace cache {
struct SavedRequest
{
SavedRequest() : mHasBodyId(false) { mValue.body() = void_t(); }
PCacheRequest mValue;
CacheRequest mValue;
bool mHasBodyId;
nsID mBodyId;
CacheId mCacheId;
@ -32,7 +32,7 @@ struct SavedRequest
struct SavedResponse
{
SavedResponse() : mHasBodyId(false) { mValue.body() = void_t(); }
PCacheResponse mValue;
CacheResponse mValue;
bool mHasBodyId;
nsID mBodyId;
CacheId mCacheId;

12
dom/cache/StreamControl.cpp поставляемый
Просмотреть файл

@ -84,6 +84,18 @@ StreamControl::CloseAllReadStreamsWithoutReporting()
}
}
bool
StreamControl::HasEverBeenRead() const
{
ReadStreamList::ForwardIterator iter(mReadStreamList);
while (iter.HasMore()) {
if (iter.GetNext()->HasEverBeenRead()) {
return true;
}
}
return false;
}
} // namespace cache
} // namespace dom
} // namespace mozilla

11
dom/cache/StreamControl.h поставляемый
Просмотреть файл

@ -20,7 +20,7 @@ namespace ipc {
namespace dom {
namespace cache {
class PCacheReadStream;
class CacheReadStream;
// Abstract class to help implement the stream control Child and Parent actors.
// This provides an interface to partly help with serialization of IPC types,
@ -30,14 +30,14 @@ class StreamControl
public:
// abstract interface that must be implemented by child class
virtual void
SerializeControl(PCacheReadStream* aReadStreamOut) = 0;
SerializeControl(CacheReadStream* aReadStreamOut) = 0;
virtual void
SerializeFds(PCacheReadStream* aReadStreamOut,
SerializeFds(CacheReadStream* aReadStreamOut,
const nsTArray<mozilla::ipc::FileDescriptor>& aFds) = 0;
virtual void
DeserializeFds(const PCacheReadStream& aReadStream,
DeserializeFds(const CacheReadStream& aReadStream,
nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) = 0;
// inherited implementation of the ReadStream::Controllable list
@ -68,6 +68,9 @@ protected:
void
CloseAllReadStreamsWithoutReporting();
bool
HasEverBeenRead() const;
// protected parts of the abstract interface
virtual void
NoteClosedAfterForget(const nsID& aId) = 0;

151
dom/cache/StreamUtils.cpp поставляемый
Просмотреть файл

@ -1,151 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/cache/StreamUtils.h"
#include "mozilla/unused.h"
#include "mozilla/dom/cache/CacheStreamControlChild.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
namespace mozilla {
namespace dom {
namespace cache {
namespace {
using mozilla::unused;
using mozilla::void_t;
using mozilla::dom::cache::CacheStreamControlChild;
using mozilla::dom::cache::Feature;
using mozilla::dom::cache::PCacheReadStream;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::FileDescriptorSetChild;
using mozilla::ipc::OptionalFileDescriptorSet;
void
StartDestroyStreamChild(const PCacheReadStream& aReadStream)
{
CacheStreamControlChild* cacheControl =
static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
if (cacheControl) {
cacheControl->StartDestroy();
}
if (aReadStream.fds().type() ==
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
nsAutoTArray<FileDescriptor, 4> fds;
FileDescriptorSetChild* fdSetActor =
static_cast<FileDescriptorSetChild*>(aReadStream.fds().get_PFileDescriptorSetChild());
MOZ_ASSERT(fdSetActor);
fdSetActor->ForgetFileDescriptors(fds);
MOZ_ASSERT(!fds.IsEmpty());
unused << fdSetActor->Send__delete__(fdSetActor);
}
}
void
AddFeatureToStreamChild(const PCacheReadStream& aReadStream, Feature* aFeature)
{
CacheStreamControlChild* cacheControl =
static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
if (cacheControl) {
cacheControl->SetFeature(aFeature);
}
}
} // anonymous namespace
void
StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid)
{
if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) {
return;
}
StartDestroyStreamChild(aResponseOrVoid.get_PCacheResponse());
}
void
StartDestroyStreamChild(const PCacheResponse& aResponse)
{
if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
return;
}
StartDestroyStreamChild(aResponse.body().get_PCacheReadStream());
}
void
StartDestroyStreamChild(const nsTArray<PCacheResponse>& aResponses)
{
for (uint32_t i = 0; i < aResponses.Length(); ++i) {
StartDestroyStreamChild(aResponses[i]);
}
}
void
StartDestroyStreamChild(const nsTArray<PCacheRequest>& aRequests)
{
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
continue;
}
StartDestroyStreamChild(aRequests[i].body().get_PCacheReadStream());
}
}
void
AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid,
Feature* aFeature)
{
if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) {
return;
}
AddFeatureToStreamChild(aResponseOrVoid.get_PCacheResponse(), aFeature);
}
void
AddFeatureToStreamChild(const PCacheResponse& aResponse,
Feature* aFeature)
{
if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
return;
}
AddFeatureToStreamChild(aResponse.body().get_PCacheReadStream(), aFeature);
}
void
AddFeatureToStreamChild(const nsTArray<PCacheResponse>& aResponses,
Feature* aFeature)
{
for (uint32_t i = 0; i < aResponses.Length(); ++i) {
AddFeatureToStreamChild(aResponses[i], aFeature);
}
}
void
AddFeatureToStreamChild(const nsTArray<PCacheRequest>& aRequests,
Feature* aFeature)
{
for (uint32_t i = 0; i < aRequests.Length(); ++i) {
if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
continue;
}
AddFeatureToStreamChild(aRequests[i].body().get_PCacheReadStream(),
aFeature);
}
}
} // namespace cache
} // namespace dom
} // namespace mozilla

39
dom/cache/StreamUtils.h поставляемый
Просмотреть файл

@ -1,39 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_cache_StreamUtils_h
#define mozilla_dom_cache_StreamUtils_h
#include "nsTArrayForwardDeclare.h"
namespace mozilla {
namespace dom {
namespace cache {
class Feature;
class PCacheRequest;
class PCacheResponse;
class PCacheResponseOrVoid;
void StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid);
void StartDestroyStreamChild(const PCacheResponse& aResponse);
void StartDestroyStreamChild(const nsTArray<PCacheResponse>& aResponses);
void StartDestroyStreamChild(const nsTArray<PCacheRequest>& aRequests);
void AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid,
Feature* aFeature);
void AddFeatureToStreamChild(const PCacheResponse& aResponse,
Feature* aFeature);
void AddFeatureToStreamChild(const nsTArray<PCacheResponse>& aResponses,
Feature* aFeature);
void AddFeatureToStreamChild(const nsTArray<PCacheRequest>& aRequests,
Feature* aFeature);
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_StreamUtils_h

79
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
#include "mozilla/dom/Request.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/cache/CachePushStreamChild.h"
#include "mozilla/dom/cache/PCacheTypes.h"
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
@ -34,7 +34,9 @@ namespace {
using mozilla::ErrorResult;
using mozilla::unused;
using mozilla::void_t;
using mozilla::dom::cache::PCacheReadStream;
using mozilla::dom::InternalHeaders;
using mozilla::dom::cache::CacheReadStream;
using mozilla::dom::cache::HeadersEntry;
using mozilla::ipc::BackgroundChild;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::PBackgroundChild;
@ -130,7 +132,7 @@ HasVaryStar(mozilla::dom::InternalHeaders* aHeaders)
}
void
SerializeNormalStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut)
SerializeNormalStream(nsIInputStream* aStream, CacheReadStream& aReadStreamOut)
{
nsAutoTArray<FileDescriptor, 4> fds;
SerializeInputStream(aStream, aReadStreamOut.params(), fds);
@ -154,6 +156,20 @@ SerializeNormalStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut)
}
}
void
ToHeadersEntryList(nsTArray<HeadersEntry>& aOut, InternalHeaders* aHeaders)
{
MOZ_ASSERT(aHeaders);
nsAutoTArray<InternalHeaders::Entry, 16> entryList;
aHeaders->GetEntries(entryList);
for (uint32_t i = 0; i < entryList.Length(); ++i) {
InternalHeaders::Entry& entry = entryList[i];
aOut.AppendElement(HeadersEntry(entry.mName, entry.mValue));
}
}
} // anonymous namespace
namespace mozilla {
@ -206,10 +222,10 @@ TypeUtils::ToInternalRequest(const OwningRequestOrUSVString& aIn,
}
void
TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
BodyAction aBodyAction,
ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv)
TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
BodyAction aBodyAction,
ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv)
{
MOZ_ASSERT(aIn);
@ -245,7 +261,7 @@ TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
nsRefPtr<InternalHeaders> headers = aIn->Headers();
MOZ_ASSERT(headers);
headers->GetPHeaders(aOut.headers());
ToHeadersEntryList(aOut.headers(), headers);
aOut.headersGuard() = headers->Guard();
aOut.mode() = aIn->Mode();
aOut.credentials() = aIn->GetCredentialsMode();
@ -269,8 +285,8 @@ TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
}
void
TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut,
InternalResponse& aIn, ErrorResult& aRv)
TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
InternalResponse& aIn, ErrorResult& aRv)
{
aOut.type() = aIn.Type();
@ -295,13 +311,13 @@ TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut,
aRv.ThrowTypeError(MSG_RESPONSE_HAS_VARY_STAR);
return;
}
headers->GetPHeaders(aOut.headers());
ToHeadersEntryList(aOut.headers(), headers);
aOut.headersGuard() = headers->Guard();
aOut.securityInfo() = aIn.GetSecurityInfo();
}
void
TypeUtils::ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv)
TypeUtils::ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv)
{
if (aIn.BodyUsed()) {
aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR);
@ -309,7 +325,7 @@ TypeUtils::ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aR
}
nsRefPtr<InternalResponse> ir = aIn.GetInternalResponse();
ToPCacheResponseWithoutBody(aOut, *ir, aRv);
ToCacheResponseWithoutBody(aOut, *ir, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@ -328,8 +344,8 @@ TypeUtils::ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aR
// static
void
TypeUtils::ToPCacheQueryParams(PCacheQueryParams& aOut,
const CacheQueryOptions& aIn)
TypeUtils::ToCacheQueryParams(CacheQueryParams& aOut,
const CacheQueryOptions& aIn)
{
aOut.ignoreSearch() = aIn.mIgnoreSearch;
aOut.ignoreMethod() = aIn.mIgnoreMethod;
@ -343,7 +359,7 @@ TypeUtils::ToPCacheQueryParams(PCacheQueryParams& aOut,
}
already_AddRefed<Response>
TypeUtils::ToResponse(const PCacheResponse& aIn)
TypeUtils::ToResponse(const CacheResponse& aIn)
{
if (aIn.type() == ResponseType::Error) {
nsRefPtr<InternalResponse> error = InternalResponse::NetworkError();
@ -356,7 +372,7 @@ TypeUtils::ToResponse(const PCacheResponse& aIn)
ir->SetUrl(NS_ConvertUTF16toUTF8(aIn.url()));
nsRefPtr<InternalHeaders> internalHeaders =
new InternalHeaders(aIn.headers(), aIn.headersGuard());
ToInternalHeaders(aIn.headers(), aIn.headersGuard());
ErrorResult result;
ir->Headers()->SetGuard(aIn.headersGuard(), result);
MOZ_ASSERT(!result.Failed());
@ -391,7 +407,7 @@ TypeUtils::ToResponse(const PCacheResponse& aIn)
}
already_AddRefed<InternalRequest>
TypeUtils::ToInternalRequest(const PCacheRequest& aIn)
TypeUtils::ToInternalRequest(const CacheRequest& aIn)
{
nsRefPtr<InternalRequest> internalRequest = new InternalRequest();
@ -408,7 +424,7 @@ TypeUtils::ToInternalRequest(const PCacheRequest& aIn)
internalRequest->SetCacheMode(aIn.requestCache());
nsRefPtr<InternalHeaders> internalHeaders =
new InternalHeaders(aIn.headers(), aIn.headersGuard());
ToInternalHeaders(aIn.headers(), aIn.headersGuard());
ErrorResult result;
internalRequest->Headers()->SetGuard(aIn.headersGuard(), result);
MOZ_ASSERT(!result.Failed());
@ -423,13 +439,30 @@ TypeUtils::ToInternalRequest(const PCacheRequest& aIn)
}
already_AddRefed<Request>
TypeUtils::ToRequest(const PCacheRequest& aIn)
TypeUtils::ToRequest(const CacheRequest& aIn)
{
nsRefPtr<InternalRequest> internalRequest = ToInternalRequest(aIn);
nsRefPtr<Request> request = new Request(GetGlobalObject(), internalRequest);
return request.forget();
}
// static
already_AddRefed<InternalHeaders>
TypeUtils::ToInternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
HeadersGuardEnum aGuard)
{
nsTArray<InternalHeaders::Entry> entryList(aHeadersEntryList.Length());
for (uint32_t i = 0; i < aHeadersEntryList.Length(); ++i) {
const HeadersEntry& headersEntry = aHeadersEntryList[i];
entryList.AppendElement(InternalHeaders::Entry(headersEntry.name(),
headersEntry.value()));
}
nsRefPtr<InternalHeaders> ref = new InternalHeaders(Move(entryList), aGuard);
return ref.forget();
}
void
TypeUtils::CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction,
ErrorResult& aRv)
@ -477,7 +510,7 @@ TypeUtils::ToInternalRequest(const nsAString& aIn, ErrorResult& aRv)
void
TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
PCacheReadStreamOrVoid* aStreamOut,
CacheReadStreamOrVoid* aStreamOut,
ErrorResult& aRv)
{
*aStreamOut = void_t();
@ -492,7 +525,7 @@ TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
return;
}
PCacheReadStream readStream;
CacheReadStream readStream;
readStream.controlChild() = nullptr;
readStream.controlParent() = nullptr;
readStream.pushStreamChild() = nullptr;
@ -516,7 +549,7 @@ TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
void
TypeUtils::SerializePushStream(nsIInputStream* aStream,
PCacheReadStream& aReadStreamOut,
CacheReadStream& aReadStreamOut,
ErrorResult& aRv)
{
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);

41
dom/cache/TypeUtils.h поставляемый
Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/InternalHeaders.h"
#include "nsError.h"
class nsIGlobalObject;
@ -29,11 +30,12 @@ class Response;
namespace cache {
class CachePushStreamChild;
class PCacheQueryParams;
class PCacheReadStream;
class PCacheReadStreamOrVoid;
class PCacheRequest;
class PCacheResponse;
class CacheQueryParams;
class CacheReadStream;
class CacheReadStreamOrVoid;
class CacheRequest;
class CacheResponse;
class HeadersEntry;
class TypeUtils
{
@ -77,28 +79,33 @@ public:
ErrorResult& aRv);
void
ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
BodyAction aBodyAction, ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv);
ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
BodyAction aBodyAction, ReferrerAction aReferrerAction,
SchemeAction aSchemeAction, ErrorResult& aRv);
void
ToPCacheResponseWithoutBody(PCacheResponse& aOut, InternalResponse& aIn,
ErrorResult& aRv);
ToCacheResponseWithoutBody(CacheResponse& aOut, InternalResponse& aIn,
ErrorResult& aRv);
void
ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv);
ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv);
void
ToPCacheQueryParams(PCacheQueryParams& aOut, const CacheQueryOptions& aIn);
ToCacheQueryParams(CacheQueryParams& aOut, const CacheQueryOptions& aIn);
already_AddRefed<Response>
ToResponse(const PCacheResponse& aIn);
ToResponse(const CacheResponse& aIn);
already_AddRefed<InternalRequest>
ToInternalRequest(const PCacheRequest& aIn);
ToInternalRequest(const CacheRequest& aIn);
already_AddRefed<Request>
ToRequest(const PCacheRequest& aIn);
ToRequest(const CacheRequest& aIn);
// static methods
static already_AddRefed<InternalHeaders>
ToInternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
HeadersGuardEnum aGuard = HeadersGuardEnum::None);
private:
void
@ -109,11 +116,11 @@ private:
ToInternalRequest(const nsAString& aIn, ErrorResult& aRv);
void
SerializeCacheStream(nsIInputStream* aStream, PCacheReadStreamOrVoid* aStreamOut,
SerializeCacheStream(nsIInputStream* aStream, CacheReadStreamOrVoid* aStreamOut,
ErrorResult& aRv);
void
SerializePushStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut,
SerializePushStream(nsIInputStream* aStream, CacheReadStream& aReadStreamOut,
ErrorResult& aRv);
};

4
dom/cache/Types.h поставляемый
Просмотреть файл

@ -22,9 +22,7 @@ enum Namespace
CHROME_ONLY_NAMESPACE,
NUMBER_OF_NAMESPACES
};
typedef uintptr_t RequestId;
static const RequestId INVALID_REQUEST_ID = 0;
static const Namespace INVALID_NAMESPACE = NUMBER_OF_NAMESPACES;
typedef int64_t CacheId;
static const CacheId INVALID_CACHE_ID = -1;

10
dom/cache/moz.build поставляемый
Просмотреть файл

@ -11,6 +11,8 @@ EXPORTS.mozilla.dom.cache += [
'AutoUtils.h',
'Cache.h',
'CacheChild.h',
'CacheOpChild.h',
'CacheOpParent.h',
'CacheParent.h',
'CachePushStreamChild.h',
'CachePushStreamParent.h',
@ -35,7 +37,6 @@ EXPORTS.mozilla.dom.cache += [
'SavedTypes.h',
'StreamControl.h',
'StreamList.h',
'StreamUtils.h',
'Types.h',
'TypeUtils.h',
]
@ -46,6 +47,8 @@ UNIFIED_SOURCES += [
'AutoUtils.cpp',
'Cache.cpp',
'CacheChild.cpp',
'CacheOpChild.cpp',
'CacheOpParent.cpp',
'CacheParent.cpp',
'CachePushStreamChild.cpp',
'CachePushStreamParent.cpp',
@ -68,17 +71,16 @@ UNIFIED_SOURCES += [
'ReadStream.cpp',
'StreamControl.cpp',
'StreamList.cpp',
'StreamUtils.cpp',
'TypeUtils.cpp',
]
IPDL_SOURCES += [
'CacheInitData.ipdlh',
'CacheTypes.ipdlh',
'PCache.ipdl',
'PCacheOp.ipdl',
'PCachePushStream.ipdl',
'PCacheStorage.ipdl',
'PCacheStreamControl.ipdl',
'PCacheTypes.ipdlh',
]
include('/ipc/chromium/chromium-config.mozbuild')

Просмотреть файл

@ -558,7 +558,7 @@ public:
}
void
Run(DataStoreDB* aDb, RunStatus aStatus)
Run(DataStoreDB* aDb, RunStatus aStatus) override
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
@ -640,7 +640,7 @@ public:
// nsIDOMEventListener
NS_IMETHOD
HandleEvent(nsIDOMEvent* aEvent)
HandleEvent(nsIDOMEvent* aEvent) override
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());

Просмотреть файл

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s
support-files =
file_utf16_be_bom.css
file_utf16_be_bom.js

Просмотреть файл

@ -1180,7 +1180,9 @@ CrossProcessSafeEvent(const WidgetEvent& aEvent)
case NS_MOUSE_BUTTON_UP:
case NS_MOUSE_MOVE:
case NS_CONTEXTMENU:
case NS_MOUSE_ENTER:
case NS_MOUSE_EXIT:
case NS_MOUSE_ENTER_SYNTH:
return true;
default:
return false;
@ -3787,20 +3789,27 @@ EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
// the same object after event dispatch and handling, so refetch it.
targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
// If we are leaving remote content, dispatch a mouse exit event to the
// remote frame.
if (aMessage == NS_MOUSE_EXIT_SYNTH && IsRemoteTarget(aTargetContent)) {
// For remote content, send a normal widget mouse exit event.
nsAutoPtr<WidgetMouseEvent> remoteEvent;
CreateMouseOrPointerWidgetEvent(aMouseEvent, NS_MOUSE_EXIT,
aRelatedContent, remoteEvent);
// If we are entering/leaving remote content, dispatch a mouse enter/exit
// event to the remote frame.
if (IsRemoteTarget(aTargetContent)) {
if (aMessage == NS_MOUSE_EXIT_SYNTH) {
// For remote content, send a normal widget mouse exit event.
nsAutoPtr<WidgetMouseEvent> remoteEvent;
CreateMouseOrPointerWidgetEvent(aMouseEvent, NS_MOUSE_EXIT,
aRelatedContent, remoteEvent);
// mCurrentTarget is set to the new target, so we must reset it to the
// old target and then dispatch a cross-process event. (mCurrentTarget
// will be set back below.) HandleCrossProcessEvent will query for the
// proper target via GetEventTarget which will return mCurrentTarget.
mCurrentTarget = targetFrame;
HandleCrossProcessEvent(remoteEvent, &status);
// mCurrentTarget is set to the new target, so we must reset it to the
// old target and then dispatch a cross-process event. (mCurrentTarget
// will be set back below.) HandleCrossProcessEvent will query for the
// proper target via GetEventTarget which will return mCurrentTarget.
mCurrentTarget = targetFrame;
HandleCrossProcessEvent(remoteEvent, &status);
} else if (aMessage == NS_MOUSE_ENTER_SYNTH) {
nsAutoPtr<WidgetMouseEvent> remoteEvent;
CreateMouseOrPointerWidgetEvent(aMouseEvent, NS_MOUSE_ENTER,
aRelatedContent, remoteEvent);
HandleCrossProcessEvent(remoteEvent, &status);
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше