mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-01 05:43:46 +00:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
24117e18a9
@ -715,36 +715,22 @@ pref("gecko.handlerService.schemes.ircs.3.uriTemplate", "chrome://browser-region
|
||||
pref("gecko.handlerService.allowRegisterFromDifferentHost", false);
|
||||
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
// Safe browsing does nothing unless this pref is set
|
||||
pref("browser.safebrowsing.enabled", true);
|
||||
|
||||
// Prevent loading of pages identified as malware
|
||||
pref("browser.safebrowsing.malware.enabled", true);
|
||||
|
||||
// Debug logging to error console
|
||||
pref("browser.safebrowsing.debug", false);
|
||||
|
||||
// Non-enhanced mode (local url lists) URL list to check for updates
|
||||
pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.2");
|
||||
pref("browser.safebrowsing.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
|
||||
pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%");
|
||||
pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%");
|
||||
pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%");
|
||||
pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mozilla.com/?hl=%LOCALE%");
|
||||
pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
|
||||
|
||||
pref("browser.safebrowsing.dataProvider", 0);
|
||||
|
||||
// Does the provider name need to be localizable?
|
||||
pref("browser.safebrowsing.provider.0.name", "Google");
|
||||
pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.2");
|
||||
pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
|
||||
pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.2");
|
||||
|
||||
// HTML report pages
|
||||
pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
|
||||
pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
|
||||
pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
|
||||
pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}");
|
||||
pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}");
|
||||
|
||||
// FAQ URLs
|
||||
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
||||
pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/geolocation/");
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||
// pages on phishing/malware hits. (bug 399233)
|
||||
@ -766,12 +752,10 @@ pref("urlclassifier.updatecachemax", 41943040);
|
||||
|
||||
// Maximum size of the sqlite3 cache for lookups, in bytes
|
||||
pref("urlclassifier.lookupcachemax", 1048576);
|
||||
|
||||
// URL for checking the reason for a malware warning.
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
#endif
|
||||
|
||||
pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/geolocation/");
|
||||
|
||||
pref("browser.EULA.version", 3);
|
||||
pref("browser.rights.version", 3);
|
||||
pref("browser.rights.3.shown", false);
|
||||
|
@ -1,4 +1,3 @@
|
||||
#
|
||||
# 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/.
|
||||
@ -13,8 +12,12 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
TEST_DIRS += content/test
|
||||
|
||||
# Normally the "client ID" sent in updates is appinfo.name, but for
|
||||
# official Firefox releases from Mozilla we use a special identifier.
|
||||
ifdef MOZILLA_OFFICIAL
|
||||
DEFINES += -DOFFICIAL_BUILD=1
|
||||
ifdef MOZ_PHOENIX
|
||||
DEFINES += -DUSE_HISTORIC_SAFEBROWSING_ID=1
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
|
@ -34,20 +34,9 @@ var SafeBrowsing = {
|
||||
Services.prefs.addObserver("browser.safebrowsing", this.readPrefs, false);
|
||||
this.readPrefs();
|
||||
|
||||
this.initProviderURLs();
|
||||
|
||||
// Initialize the list manager
|
||||
// Register our two types of tables, and add custom Mozilla entries
|
||||
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||
getService(Ci.nsIUrlListManager);
|
||||
|
||||
listManager.setUpdateUrl(this.updateURL);
|
||||
// setKeyUrl has the side effect of fetching a key from the server.
|
||||
// This shouldn't happen if anti-phishing/anti-malware is disabled.
|
||||
if (this.phishingEnabled || this.malwareEnabled)
|
||||
listManager.setKeyUrl(this.keyURL);
|
||||
listManager.setGethashUrl(this.gethashURL);
|
||||
|
||||
// Register our two types of tables
|
||||
listManager.registerTable(phishingList, false);
|
||||
listManager.registerTable(malwareList, false);
|
||||
this.addMozEntries();
|
||||
@ -63,11 +52,11 @@ var SafeBrowsing = {
|
||||
phishingEnabled: false,
|
||||
malwareEnabled: false,
|
||||
|
||||
provName: null,
|
||||
updateURL: null,
|
||||
keyURL: null,
|
||||
reportURL: null,
|
||||
gethashURL: null,
|
||||
|
||||
reportURL: null,
|
||||
reportGenericURL: null,
|
||||
reportErrorURL: null,
|
||||
reportPhishURL: null,
|
||||
@ -86,6 +75,7 @@ var SafeBrowsing = {
|
||||
debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
|
||||
this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
|
||||
this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
|
||||
this.updateProviderURLs();
|
||||
|
||||
// XXX The listManager backend gets confused if this is called before the
|
||||
// lists are registered. So only call it here when a pref changes, and not
|
||||
@ -95,67 +85,42 @@ var SafeBrowsing = {
|
||||
},
|
||||
|
||||
|
||||
initProviderURLs: function() {
|
||||
log("initializing provider URLs");
|
||||
|
||||
// XXX remove this as obsolete?
|
||||
let provID = Services.prefs.getIntPref("browser.safebrowsing.dataProvider");
|
||||
if (provID != 0) {
|
||||
Cu.reportError("unknown safebrowsing provider ID " + provID);
|
||||
return;
|
||||
}
|
||||
|
||||
let basePref = "browser.safebrowsing.provider.0.";
|
||||
this.provName = Services.prefs.getCharPref(basePref + "name");
|
||||
|
||||
// Urls used to get data from a provider
|
||||
this.updateURL = this.getUrlPref(basePref + "updateURL");
|
||||
this.keyURL = this.getUrlPref(basePref + "keyURL");
|
||||
this.reportURL = this.getUrlPref(basePref + "reportURL");
|
||||
this.gethashURL = this.getUrlPref(basePref + "gethashURL");
|
||||
|
||||
// Urls to HTML report pages
|
||||
this.reportGenericURL = this.getUrlPref(basePref + "reportGenericURL");
|
||||
this.reportErrorURL = this.getUrlPref(basePref + "reportErrorURL");
|
||||
this.reportPhishURL = this.getUrlPref(basePref + "reportPhishURL");
|
||||
this.reportMalwareURL = this.getUrlPref(basePref + "reportMalwareURL")
|
||||
this.reportMalwareErrorURL = this.getUrlPref(basePref + "reportMalwareErrorURL")
|
||||
},
|
||||
|
||||
|
||||
getUrlPref: function(prefName) {
|
||||
let MOZ_OFFICIAL_BUILD = false;
|
||||
#ifdef OFFICIAL_BUILD
|
||||
MOZ_OFFICIAL_BUILD = true;
|
||||
updateProviderURLs: function() {
|
||||
#ifdef USE_HISTORIC_SAFEBROWSING_ID
|
||||
let clientID = "navclient-auto-ffox";
|
||||
#else
|
||||
let clientID = Services.appinfo.name;
|
||||
#endif
|
||||
|
||||
let url = Services.prefs.getCharPref(prefName);
|
||||
log("initializing safe browsing URLs");
|
||||
let basePref = "browser.safebrowsing.";
|
||||
|
||||
let clientName = MOZ_OFFICIAL_BUILD ? "navclient-auto-ffox" : Services.appinfo.name;
|
||||
let clientVersion = Services.appinfo.version;
|
||||
// Urls to HTML report pages
|
||||
this.reportURL = Services.urlFormatter.formatURLPref(basePref + "reportURL");
|
||||
this.reportGenericURL = Services.urlFormatter.formatURLPref(basePref + "reportGenericURL");
|
||||
this.reportErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportErrorURL");
|
||||
this.reportPhishURL = Services.urlFormatter.formatURLPref(basePref + "reportPhishURL");
|
||||
this.reportMalwareURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareURL");
|
||||
this.reportMalwareErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareErrorURL");
|
||||
|
||||
// Parameter substitution
|
||||
// XXX: we should instead use nsIURLFormatter here.
|
||||
url = url.replace(/\{moz:locale\}/g, this.getLocale());
|
||||
url = url.replace(/\{moz:client\}/g, clientName);
|
||||
url = url.replace(/\{moz:buildid\}/g, Services.appinfo.appBuildID);
|
||||
url = url.replace(/\{moz:version\}/g, clientVersion);
|
||||
// Urls used to update DB
|
||||
this.updateURL = Services.urlFormatter.formatURLPref(basePref + "updateURL");
|
||||
this.keyURL = Services.urlFormatter.formatURLPref(basePref + "keyURL");
|
||||
this.gethashURL = Services.urlFormatter.formatURLPref(basePref + "gethashURL");
|
||||
|
||||
log(prefName, "is", url);
|
||||
return url;
|
||||
},
|
||||
this.updateURL = this.updateURL.replace("SAFEBROWSING_ID", clientID);
|
||||
this.keyURL = this.keyURL.replace("SAFEBROWSING_ID", clientID);
|
||||
this.gethashURL = this.gethashURL.replace("SAFEBROWSING_ID", clientID);
|
||||
|
||||
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||
getService(Ci.nsIUrlListManager);
|
||||
|
||||
getLocale: function() {
|
||||
const localePref = "general.useragent.locale";
|
||||
|
||||
let locale = Services.prefs.getCharPref(localePref);
|
||||
try {
|
||||
// Dumb. This API only works if pref is localized or has a user value.
|
||||
locale = Services.prefs.getComplexValue(localePref, Ci.nsIPrefLocalizedString).data;
|
||||
} catch (e) { }
|
||||
|
||||
return locale;
|
||||
listManager.setUpdateUrl(this.updateURL);
|
||||
// XXX Bug 779317 - setKeyUrl has the side effect of fetching a key from the server.
|
||||
// This shouldn't happen if anti-phishing/anti-malware is disabled.
|
||||
if (this.phishingEnabled || this.malwareEnabled)
|
||||
listManager.setKeyUrl(this.keyURL);
|
||||
listManager.setGethashUrl(this.gethashURL);
|
||||
},
|
||||
|
||||
|
||||
@ -179,7 +144,7 @@ var SafeBrowsing = {
|
||||
|
||||
addMozEntries: function() {
|
||||
// Add test entries to the DB.
|
||||
// XXX this should really just be done by DB itself for all moz apps.
|
||||
// XXX bug 779008 - this could be done by DB itself?
|
||||
const phishURL = "mozilla.org/firefox/its-a-trap.html";
|
||||
const malwareURL = "mozilla.org/firefox/its-an-attack.html";
|
||||
|
||||
|
@ -417,9 +417,9 @@ user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
|
||||
// Make url-classifier updates so rare that they won't affect tests
|
||||
user_pref("urlclassifier.updateinterval", 172800);
|
||||
// Point the url-classifier to the local testing server for fast failures
|
||||
user_pref("browser.safebrowsing.provider.0.gethashURL", "http://%(server)s/safebrowsing-dummy/gethash");
|
||||
user_pref("browser.safebrowsing.provider.0.keyURL", "http://%(server)s/safebrowsing-dummy/newkey");
|
||||
user_pref("browser.safebrowsing.provider.0.updateURL", "http://%(server)s/safebrowsing-dummy/update");
|
||||
user_pref("browser.safebrowsing.gethashURL", "http://%(server)s/safebrowsing-dummy/gethash");
|
||||
user_pref("browser.safebrowsing.keyURL", "http://%(server)s/safebrowsing-dummy/newkey");
|
||||
user_pref("browser.safebrowsing.updateURL", "http://%(server)s/safebrowsing-dummy/update");
|
||||
// Point update checks to the local testing server for fast failures
|
||||
user_pref("extensions.update.url", "http://%(server)s/extensions-dummy/updateURL");
|
||||
user_pref("extensions.update.background.url", "http://%(server)s/extensions-dummy/updateBackgroundURL");
|
||||
|
@ -17,15 +17,19 @@ interface nsIFrameMessageListener : nsISupports
|
||||
* receiveMessage is called with one parameter, which has the following
|
||||
* properties:
|
||||
* {
|
||||
* target: %the target of the message. Either an element owning
|
||||
* the message manager, or message manager itself if no
|
||||
* element owns it%
|
||||
* name: %message name%,
|
||||
* sync: %true or false%.
|
||||
* json: %json object or null%,
|
||||
* json: %structured clone of the sent message data%,
|
||||
* json: %same as .data, deprecated%,
|
||||
* objects: %array of handles or null, always null if sync is false%
|
||||
* }
|
||||
* @note objects property isn't implemented yet.
|
||||
*
|
||||
* if the message is synchronous, possible return value is sent back
|
||||
* as JSON.
|
||||
* as JSON (will be changed to use structured clones).
|
||||
*
|
||||
* When the listener is called, 'this' value is the target of the message.
|
||||
*/
|
||||
|
@ -128,6 +128,7 @@ CPPSRCS = \
|
||||
FragmentOrElement.cpp \
|
||||
Link.cpp \
|
||||
nsBlobProtocolHandler.cpp \
|
||||
nsBlobURI.cpp \
|
||||
nsFrameMessageManager.cpp \
|
||||
nsInProcessTabChildGlobal.cpp \
|
||||
ThirdPartyUtil.cpp \
|
||||
|
@ -3,19 +3,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsBlobProtocolHandler.h"
|
||||
#include "nsSimpleURI.h"
|
||||
#include "nsBlobURI.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIURIWithPrincipal.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Hash table
|
||||
@ -89,233 +82,6 @@ GetFileDataInfo(const nsACString& aUri)
|
||||
return res;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Uri
|
||||
|
||||
#define NS_BLOBURI_CID \
|
||||
{ 0xf5475c51, 0x59a7, 0x4757, \
|
||||
{ 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
|
||||
|
||||
static NS_DEFINE_CID(kBLOBURICID, NS_BLOBURI_CID);
|
||||
|
||||
class nsBlobURI : public nsSimpleURI,
|
||||
public nsIURIWithPrincipal
|
||||
{
|
||||
public:
|
||||
nsBlobURI(nsIPrincipal* aPrincipal) :
|
||||
nsSimpleURI(), mPrincipal(aPrincipal)
|
||||
{}
|
||||
virtual ~nsBlobURI() {}
|
||||
|
||||
// For use only from deserialization
|
||||
nsBlobURI() : nsSimpleURI() {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIURIWITHPRINCIPAL
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
// Override CloneInternal() and EqualsInternal()
|
||||
virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone);
|
||||
virtual nsresult EqualsInternal(nsIURI* aOther,
|
||||
RefHandlingEnum aRefHandlingMode,
|
||||
bool* aResult);
|
||||
|
||||
// Override StartClone to hand back a nsBlobURI
|
||||
virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
|
||||
{ return new nsBlobURI(); }
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
||||
static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
|
||||
NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsBlobURI, nsSimpleURI)
|
||||
NS_IMPL_RELEASE_INHERITED(nsBlobURI, nsSimpleURI)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsBlobURI)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
|
||||
if (aIID.Equals(kBLOBURICID))
|
||||
foundInterface = static_cast<nsIURI*>(this);
|
||||
else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
|
||||
// Need to return explicitly here, because if we just set foundInterface
|
||||
// to null the NS_INTERFACE_MAP_END_INHERITING will end up calling into
|
||||
// nsSimplURI::QueryInterface and finding something for this CID.
|
||||
*aInstancePtr = nullptr;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
else
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSimpleURI)
|
||||
|
||||
// nsIURIWithPrincipal methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
NS_IF_ADDREF(*aPrincipal = mPrincipal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetPrincipalUri(nsIURI** aUri)
|
||||
{
|
||||
if (mPrincipal) {
|
||||
mPrincipal->GetURI(aUri);
|
||||
}
|
||||
else {
|
||||
*aUri = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISerializable methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
nsresult rv = nsSimpleURI::Read(aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_ReadOptionalObject(aStream, true, getter_AddRefs(mPrincipal));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
nsresult rv = nsSimpleURI::Write(aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_WriteOptionalCompoundObject(aStream, mPrincipal,
|
||||
NS_GET_IID(nsIPrincipal),
|
||||
true);
|
||||
}
|
||||
|
||||
// nsIURI methods:
|
||||
nsresult
|
||||
nsBlobURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone)
|
||||
{
|
||||
nsCOMPtr<nsIURI> simpleClone;
|
||||
nsresult rv =
|
||||
nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG
|
||||
nsRefPtr<nsBlobURI> uriCheck;
|
||||
rv = simpleClone->QueryInterface(kBLOBURICID, getter_AddRefs(uriCheck));
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
|
||||
"Unexpected!");
|
||||
#endif
|
||||
|
||||
nsBlobURI* blobURI = static_cast<nsBlobURI*>(simpleClone.get());
|
||||
|
||||
blobURI->mPrincipal = mPrincipal;
|
||||
|
||||
simpleClone.forget(aClone);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsBlobURI::EqualsInternal(nsIURI* aOther,
|
||||
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
bool* aResult)
|
||||
{
|
||||
if (!aOther) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsBlobURI> otherBlobUri;
|
||||
aOther->QueryInterface(kBLOBURICID, getter_AddRefs(otherBlobUri));
|
||||
if (!otherBlobUri) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compare the member data that our base class knows about.
|
||||
if (!nsSimpleURI::EqualsInternal(otherBlobUri, aRefHandlingMode)) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compare the piece of additional member data that we add to base class.
|
||||
if (mPrincipal && otherBlobUri->mPrincipal) {
|
||||
// Both of us have mPrincipals. Compare them.
|
||||
return mPrincipal->Equals(otherBlobUri->mPrincipal, aResult);
|
||||
}
|
||||
// else, at least one of us lacks a principal; only equal if *both* lack it.
|
||||
*aResult = (!mPrincipal && !otherBlobUri->mPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIClassInfo methods:
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetInterfaces(PRUint32 *count, nsIID * **array)
|
||||
{
|
||||
*count = 0;
|
||||
*array = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
|
||||
{
|
||||
*_retval = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetContractID(char * *aContractID)
|
||||
{
|
||||
// Make sure to modify any subclasses as needed if this ever
|
||||
// changes.
|
||||
*aContractID = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassDescription(char * *aClassDescription)
|
||||
{
|
||||
*aClassDescription = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassID(nsCID * *aClassID)
|
||||
{
|
||||
// Make sure to modify any subclasses as needed if this ever
|
||||
// changes to not call the virtual GetClassIDNoAlloc.
|
||||
*aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
|
||||
NS_ENSURE_TRUE(*aClassID, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return GetClassIDNoAlloc(*aClassID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
|
||||
{
|
||||
*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
*aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
||||
{
|
||||
*aClassIDNoAlloc = kBLOBURICID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Protocol handler
|
||||
|
||||
|
199
content/base/src/nsBlobURI.cpp
Normal file
199
content/base/src/nsBlobURI.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
/* 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 "nsBlobURI.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
static NS_DEFINE_CID(kBLOBURICID, NS_BLOBURI_CID);
|
||||
|
||||
static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
|
||||
NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsBlobURI, nsSimpleURI)
|
||||
NS_IMPL_RELEASE_INHERITED(nsBlobURI, nsSimpleURI)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsBlobURI)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
|
||||
if (aIID.Equals(kBLOBURICID))
|
||||
foundInterface = static_cast<nsIURI*>(this);
|
||||
else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
|
||||
// Need to return explicitly here, because if we just set foundInterface
|
||||
// to null the NS_INTERFACE_MAP_END_INHERITING will end up calling into
|
||||
// nsSimplURI::QueryInterface and finding something for this CID.
|
||||
*aInstancePtr = nullptr;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
else
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSimpleURI)
|
||||
|
||||
// nsIURIWithPrincipal methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
NS_IF_ADDREF(*aPrincipal = mPrincipal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetPrincipalUri(nsIURI** aUri)
|
||||
{
|
||||
if (mPrincipal) {
|
||||
mPrincipal->GetURI(aUri);
|
||||
}
|
||||
else {
|
||||
*aUri = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISerializable methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
nsresult rv = nsSimpleURI::Read(aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_ReadOptionalObject(aStream, true, getter_AddRefs(mPrincipal));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::Write(nsIObjectOutputStream* aStream)
|
||||
{
|
||||
nsresult rv = nsSimpleURI::Write(aStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_WriteOptionalCompoundObject(aStream, mPrincipal,
|
||||
NS_GET_IID(nsIPrincipal),
|
||||
true);
|
||||
}
|
||||
|
||||
// nsIURI methods:
|
||||
nsresult
|
||||
nsBlobURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone)
|
||||
{
|
||||
nsCOMPtr<nsIURI> simpleClone;
|
||||
nsresult rv =
|
||||
nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG
|
||||
nsRefPtr<nsBlobURI> uriCheck;
|
||||
rv = simpleClone->QueryInterface(kBLOBURICID, getter_AddRefs(uriCheck));
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
|
||||
"Unexpected!");
|
||||
#endif
|
||||
|
||||
nsBlobURI* blobURI = static_cast<nsBlobURI*>(simpleClone.get());
|
||||
|
||||
blobURI->mPrincipal = mPrincipal;
|
||||
|
||||
simpleClone.forget(aClone);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsBlobURI::EqualsInternal(nsIURI* aOther,
|
||||
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
bool* aResult)
|
||||
{
|
||||
if (!aOther) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsBlobURI> otherBlobUri;
|
||||
aOther->QueryInterface(kBLOBURICID, getter_AddRefs(otherBlobUri));
|
||||
if (!otherBlobUri) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compare the member data that our base class knows about.
|
||||
if (!nsSimpleURI::EqualsInternal(otherBlobUri, aRefHandlingMode)) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compare the piece of additional member data that we add to base class.
|
||||
if (mPrincipal && otherBlobUri->mPrincipal) {
|
||||
// Both of us have mPrincipals. Compare them.
|
||||
return mPrincipal->Equals(otherBlobUri->mPrincipal, aResult);
|
||||
}
|
||||
// else, at least one of us lacks a principal; only equal if *both* lack it.
|
||||
*aResult = (!mPrincipal && !otherBlobUri->mPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIClassInfo methods:
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetInterfaces(PRUint32 *count, nsIID * **array)
|
||||
{
|
||||
*count = 0;
|
||||
*array = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
|
||||
{
|
||||
*_retval = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetContractID(char * *aContractID)
|
||||
{
|
||||
// Make sure to modify any subclasses as needed if this ever
|
||||
// changes.
|
||||
*aContractID = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassDescription(char * *aClassDescription)
|
||||
{
|
||||
*aClassDescription = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassID(nsCID * *aClassID)
|
||||
{
|
||||
// Make sure to modify any subclasses as needed if this ever
|
||||
// changes to not call the virtual GetClassIDNoAlloc.
|
||||
*aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
|
||||
NS_ENSURE_TRUE(*aClassID, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return GetClassIDNoAlloc(*aClassID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
|
||||
{
|
||||
*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
*aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlobURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
||||
{
|
||||
*aClassIDNoAlloc = kBLOBURICID;
|
||||
return NS_OK;
|
||||
}
|
50
content/base/src/nsBlobURI.h
Normal file
50
content/base/src/nsBlobURI.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* 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 nsBlobURI_h
|
||||
#define nsBlobURI_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIURIWithPrincipal.h"
|
||||
#include "nsSimpleURI.h"
|
||||
|
||||
class nsBlobURI : public nsSimpleURI,
|
||||
public nsIURIWithPrincipal
|
||||
{
|
||||
public:
|
||||
nsBlobURI(nsIPrincipal* aPrincipal) :
|
||||
nsSimpleURI(), mPrincipal(aPrincipal)
|
||||
{}
|
||||
virtual ~nsBlobURI() {}
|
||||
|
||||
// For use only from deserialization
|
||||
nsBlobURI() : nsSimpleURI() {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIURIWITHPRINCIPAL
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
// Override CloneInternal() and EqualsInternal()
|
||||
virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone);
|
||||
virtual nsresult EqualsInternal(nsIURI* aOther,
|
||||
RefHandlingEnum aRefHandlingMode,
|
||||
bool* aResult);
|
||||
|
||||
// Override StartClone to hand back a nsBlobURI
|
||||
virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
|
||||
{ return new nsBlobURI(); }
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
||||
#define NS_BLOBURI_CID \
|
||||
{ 0xf5475c51, 0x59a7, 0x4757, \
|
||||
{ 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
|
||||
|
||||
#endif /* nsBlobURI_h */
|
@ -22,6 +22,7 @@
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWebProgress.h"
|
||||
@ -83,6 +84,7 @@
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -2156,8 +2158,15 @@ class nsAsyncMessageToChild : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToChild(nsFrameLoader* aFrameLoader,
|
||||
const nsAString& aMessage, const nsAString& aJSON)
|
||||
: mFrameLoader(aFrameLoader), mMessage(aMessage), mJSON(aJSON) {}
|
||||
const nsAString& aMessage,
|
||||
const StructuredCloneData& aData)
|
||||
: mFrameLoader(aFrameLoader), mMessage(aMessage)
|
||||
{
|
||||
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
|
||||
NS_RUNTIMEABORT("OOM");
|
||||
}
|
||||
mClosure = aData.mClosure;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
@ -2165,29 +2174,62 @@ public:
|
||||
static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
|
||||
if (tabChild && tabChild->GetInnerManager()) {
|
||||
nsFrameScriptCx cx(static_cast<nsIDOMEventTarget*>(tabChild), tabChild);
|
||||
|
||||
StructuredCloneData data;
|
||||
data.mData = mData.data();
|
||||
data.mDataLength = mData.nbytes();
|
||||
data.mClosure = mClosure;
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
|
||||
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(tabChild), mMessage,
|
||||
false, mJSON, nullptr, nullptr);
|
||||
false, &data, nullptr, nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
nsString mMessage;
|
||||
nsString mJSON;
|
||||
JSAutoStructuredCloneBuffer mData;
|
||||
StructuredCloneClosure mClosure;
|
||||
};
|
||||
|
||||
bool SendAsyncMessageToChild(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
mozilla::dom::PBrowserParent* tabParent =
|
||||
PBrowserParent* tabParent =
|
||||
static_cast<nsFrameLoader*>(aCallbackData)->GetRemoteBrowser();
|
||||
if (tabParent) {
|
||||
return tabParent->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
|
||||
ClonedMessageData data;
|
||||
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobParent*>& blobParents = data.blobsParent();
|
||||
|
||||
PRUint32 length = blobs.Length();
|
||||
blobParents.SetCapacity(length);
|
||||
|
||||
ContentParent* cp = static_cast<ContentParent*>(tabParent->Manager());
|
||||
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobParent* blobParent = cp->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
blobParents.AppendElement(blobParent);
|
||||
}
|
||||
}
|
||||
|
||||
return tabParent->SendAsyncMessage(nsString(aMessage), data);
|
||||
}
|
||||
|
||||
nsRefPtr<nsIRunnable> ev =
|
||||
new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData),
|
||||
aMessage, aJSON);
|
||||
aMessage, aData);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
return true;
|
||||
}
|
||||
|
@ -3,9 +3,12 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "nsFrameMessageManager.h"
|
||||
|
||||
#include "ContentChild.h"
|
||||
#include "ContentParent.h"
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
@ -20,14 +23,17 @@
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static bool
|
||||
IsChromeProcess()
|
||||
@ -170,15 +176,32 @@ JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameMessageManager::GetParamsForMessage(const jsval& aObject,
|
||||
JSContext* aCx,
|
||||
nsAString& aJSON)
|
||||
static bool
|
||||
GetParamsForMessage(JSContext* aCx,
|
||||
const jsval& aObject,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
StructuredCloneClosure& aClosure)
|
||||
{
|
||||
aJSON.Truncate();
|
||||
if (WriteStructuredClone(aCx, aObject, aBuffer, aClosure)) {
|
||||
return true;
|
||||
}
|
||||
JS_ClearPendingException(aCx);
|
||||
|
||||
// Not clonable, try JSON
|
||||
//XXX This is ugly but currently structured cloning doesn't handle
|
||||
// properly cases when interface is implemented in JS and used
|
||||
// as a dictionary.
|
||||
nsAutoString json;
|
||||
JSAutoRequest ar(aCx);
|
||||
jsval v = aObject;
|
||||
JS_Stringify(aCx, &v, nullptr, JSVAL_NULL, JSONCreator, &aJSON);
|
||||
NS_ENSURE_TRUE(JS_Stringify(aCx, &v, nullptr, JSVAL_NULL, JSONCreator, &json), false);
|
||||
NS_ENSURE_TRUE(!json.IsEmpty(), false);
|
||||
|
||||
jsval val = JSVAL_NULL;
|
||||
NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const jschar*>(PromiseFlatString(json).get()),
|
||||
json.Length(), &val), false);
|
||||
|
||||
return WriteStructuredClone(aCx, val, aBuffer, aClosure);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -194,12 +217,17 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
|
||||
*aRetval = JSVAL_VOID;
|
||||
if (mSyncCallback) {
|
||||
NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED);
|
||||
nsString json;
|
||||
if (aArgc >= 2) {
|
||||
GetParamsForMessage(aObject, aCx, json);
|
||||
StructuredCloneData data;
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
if (aArgc >= 2 &&
|
||||
!GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
data.mData = buffer.data();
|
||||
data.mDataLength = buffer.nbytes();
|
||||
|
||||
InfallibleTArray<nsString> retval;
|
||||
if (mSyncCallback(mCallbackData, aMessageName, json, &retval)) {
|
||||
if (mSyncCallback(mCallbackData, aMessageName, data, &retval)) {
|
||||
JSAutoRequest ar(aCx);
|
||||
PRUint32 len = retval.Length();
|
||||
JSObject* dataArray = JS_NewArrayObject(aCx, len, NULL);
|
||||
@ -226,16 +254,16 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
|
||||
|
||||
nsresult
|
||||
nsFrameMessageManager::SendAsyncMessageInternal(const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
if (mAsyncCallback) {
|
||||
NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED);
|
||||
mAsyncCallback(mCallbackData, aMessage, aJSON);
|
||||
mAsyncCallback(mCallbackData, aMessage, aData);
|
||||
}
|
||||
PRInt32 len = mChildManagers.Count();
|
||||
for (PRInt32 i = 0; i < len; ++i) {
|
||||
static_cast<nsFrameMessageManager*>(mChildManagers[i])->
|
||||
SendAsyncMessageInternal(aMessage, aJSON);
|
||||
SendAsyncMessageInternal(aMessage, aData);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -246,11 +274,18 @@ nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
|
||||
JSContext* aCx,
|
||||
PRUint8 aArgc)
|
||||
{
|
||||
nsString json;
|
||||
if (aArgc >= 2) {
|
||||
GetParamsForMessage(aObject, aCx, json);
|
||||
StructuredCloneData data;
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
|
||||
if (aArgc >= 2 &&
|
||||
!GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
return SendAsyncMessageInternal(aMessageName, json);
|
||||
|
||||
data.mData = buffer.data();
|
||||
data.mDataLength = buffer.nbytes();
|
||||
|
||||
return SendAsyncMessageInternal(aMessageName, data);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -342,7 +377,8 @@ public:
|
||||
nsresult
|
||||
nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
const nsAString& aMessage,
|
||||
bool aSync, const nsAString& aJSON,
|
||||
bool aSync,
|
||||
const StructuredCloneData* aCloneData,
|
||||
JSObject* aObjectsArray,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext)
|
||||
@ -402,11 +438,10 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
jsval json = JSVAL_NULL;
|
||||
if (!aJSON.IsEmpty()) {
|
||||
if (!JS_ParseJSON(ctx, static_cast<const jschar*>(PromiseFlatString(aJSON).get()),
|
||||
aJSON.Length(), &json)) {
|
||||
json = JSVAL_NULL;
|
||||
}
|
||||
if (aCloneData && aCloneData->mDataLength &&
|
||||
!ReadStructuredClone(ctx, *aCloneData, &json)) {
|
||||
JS_ClearPendingException(ctx);
|
||||
return NS_OK;
|
||||
}
|
||||
JSString* jsMessage =
|
||||
JS_NewUCStringCopyN(ctx,
|
||||
@ -418,7 +453,8 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
STRING_TO_JSVAL(jsMessage), NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(ctx, param, "sync",
|
||||
BOOLEAN_TO_JSVAL(aSync), NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(ctx, param, "json", json, NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(ctx, param, "json", json, NULL, NULL, JSPROP_ENUMERATE); // deprecated
|
||||
JS_DefineProperty(ctx, param, "data", json, NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(ctx, param, "objects", objectsv.jsval_value(), NULL, NULL, JSPROP_ENUMERATE);
|
||||
|
||||
jsval thisValue = JSVAL_VOID;
|
||||
@ -479,7 +515,8 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
}
|
||||
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager;
|
||||
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
|
||||
aSync, aJSON, aObjectsArray,
|
||||
aSync, aCloneData,
|
||||
aObjectsArray,
|
||||
aJSONRetVal, mContext) : NS_OK;
|
||||
}
|
||||
|
||||
@ -888,13 +925,31 @@ nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyn
|
||||
|
||||
bool SendAsyncMessageToChildProcess(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
mozilla::dom::ContentParent* cp =
|
||||
static_cast<mozilla::dom::ContentParent*>(aCallbackData);
|
||||
NS_WARN_IF_FALSE(cp, "No child process!");
|
||||
if (cp) {
|
||||
return cp->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
|
||||
ClonedMessageData data;
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobParent*>& blobParents = data.blobsParent();
|
||||
PRUint32 length = blobs.Length();
|
||||
blobParents.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobParent* blobParent = cp->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobParent) {
|
||||
return false;
|
||||
}
|
||||
blobParents.AppendElement(blobParent);
|
||||
}
|
||||
}
|
||||
|
||||
return cp->SendAsyncMessage(nsString(aMessage), data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -902,49 +957,79 @@ bool SendAsyncMessageToChildProcess(void* aCallbackData,
|
||||
class nsAsyncMessageToSameProcessChild : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToSameProcessChild(const nsAString& aMessage, const nsAString& aJSON)
|
||||
: mMessage(aMessage), mJSON(aJSON) {}
|
||||
nsAsyncMessageToSameProcessChild(const nsAString& aMessage,
|
||||
const StructuredCloneData& aData)
|
||||
: mMessage(aMessage)
|
||||
{
|
||||
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
|
||||
NS_RUNTIMEABORT("OOM");
|
||||
}
|
||||
mClosure = aData.mClosure;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (nsFrameMessageManager::sChildProcessManager) {
|
||||
StructuredCloneData data;
|
||||
data.mData = mData.data();
|
||||
data.mDataLength = mData.nbytes();
|
||||
data.mClosure = mClosure;
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage,
|
||||
false, mJSON, nullptr, nullptr);
|
||||
false, &data, nullptr, nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsString mMessage;
|
||||
nsString mJSON;
|
||||
JSAutoStructuredCloneBuffer mData;
|
||||
StructuredCloneClosure mClosure;
|
||||
};
|
||||
|
||||
bool SendAsyncMessageToSameProcessChild(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
nsRefPtr<nsIRunnable> ev =
|
||||
new nsAsyncMessageToSameProcessChild(aMessage, aJSON);
|
||||
new nsAsyncMessageToSameProcessChild(aMessage, aData);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendSyncMessageToParentProcess(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
const StructuredCloneData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
ClonedMessageData data;
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild();
|
||||
PRUint32 length = blobs.Length();
|
||||
blobChildList.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobChild) {
|
||||
return false;
|
||||
}
|
||||
blobChildList.AppendElement(blobChild);
|
||||
}
|
||||
}
|
||||
return
|
||||
cc->SendSyncMessage(nsString(aMessage), nsString(aJSON), aJSONRetVal);
|
||||
cc->SendSyncMessage(nsString(aMessage), data, aJSONRetVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendSyncMessageToSameProcessParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
const StructuredCloneData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
|
||||
@ -959,19 +1044,36 @@ bool SendSyncMessageToSameProcessParent(void* aCallbackData,
|
||||
if (nsFrameMessageManager::sSameProcessParentManager) {
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage,
|
||||
true, aJSON, nullptr, aJSONRetVal);
|
||||
true, &aData, nullptr, aJSONRetVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendAsyncMessageToParentProcess(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
return cc->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
|
||||
ClonedMessageData data;
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild();
|
||||
PRUint32 length = blobs.Length();
|
||||
blobChildList.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobChild) {
|
||||
return false;
|
||||
}
|
||||
blobChildList.AppendElement(blobChild);
|
||||
}
|
||||
}
|
||||
return cc->SendAsyncMessage(nsString(aMessage), data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -979,8 +1081,15 @@ bool SendAsyncMessageToParentProcess(void* aCallbackData,
|
||||
class nsAsyncMessageToSameProcessParent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToSameProcessParent(const nsAString& aMessage, const nsAString& aJSON)
|
||||
: mMessage(aMessage), mJSON(aJSON) {}
|
||||
nsAsyncMessageToSameProcessParent(const nsAString& aMessage,
|
||||
const StructuredCloneData& aData)
|
||||
: mMessage(aMessage)
|
||||
{
|
||||
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
|
||||
NS_RUNTIMEABORT("OOM");
|
||||
}
|
||||
mClosure = aData.mClosure;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
@ -988,25 +1097,32 @@ public:
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages->RemoveElement(this);
|
||||
}
|
||||
if (nsFrameMessageManager::sSameProcessParentManager) {
|
||||
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage, false,
|
||||
mJSON, nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
StructuredCloneData data;
|
||||
data.mData = mData.data();
|
||||
data.mDataLength = mData.nbytes();
|
||||
data.mClosure = mClosure;
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> ppm =
|
||||
nsFrameMessageManager::sSameProcessParentManager;
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
mMessage, false, &data, nullptr, nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsString mMessage;
|
||||
nsString mJSON;
|
||||
JSAutoStructuredCloneBuffer mData;
|
||||
StructuredCloneClosure mClosure;
|
||||
};
|
||||
|
||||
bool SendAsyncMessageToSameProcessParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const nsAString& aMessage,
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsAsyncMessageToSameProcessParent(aMessage, aJSON);
|
||||
new nsAsyncMessageToSameProcessParent(aMessage, aData);
|
||||
nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
return true;
|
||||
@ -1089,4 +1205,4 @@ nsFrameMessageManager::MarkForCC()
|
||||
xpc_TryUnmarkWrappedGrayObject(mListeners[i].mListener);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
struct StructuredCloneData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,15 +42,16 @@ struct nsMessageListenerInfo
|
||||
typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL);
|
||||
typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
const mozilla::dom::StructuredCloneData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal);
|
||||
typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON);
|
||||
const mozilla::dom::StructuredCloneData& aData);
|
||||
|
||||
class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
|
||||
public nsIChromeFrameMessageManager
|
||||
{
|
||||
typedef mozilla::dom::StructuredCloneData StructuredCloneData;
|
||||
public:
|
||||
nsFrameMessageManager(bool aChrome,
|
||||
nsSyncMessageCallback aSyncCallback,
|
||||
@ -63,7 +65,8 @@ public:
|
||||
: mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager),
|
||||
mHandlingMessage(false), mDisconnected(false), mParentManager(aParentManager),
|
||||
mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
|
||||
mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
|
||||
mLoadScriptCallback(aLoadScriptCallback),
|
||||
mCallbackData(aCallbackData),
|
||||
mContext(aContext)
|
||||
{
|
||||
NS_ASSERTION(mContext || (aChrome && !aParentManager) || aProcessManager,
|
||||
@ -112,10 +115,11 @@ public:
|
||||
NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
|
||||
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
|
||||
bool aSync, const nsAString& aJSON,
|
||||
bool aSync, const StructuredCloneData* aCloneData,
|
||||
JSObject* aObjectsArray,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext = nullptr);
|
||||
|
||||
void AddChildManager(nsFrameMessageManager* aManager,
|
||||
bool aLoadScripts = true);
|
||||
void RemoveChildManager(nsFrameMessageManager* aManager)
|
||||
@ -126,11 +130,8 @@ public:
|
||||
void Disconnect(bool aRemoveFromParent = true);
|
||||
void SetCallbackData(void* aData, bool aLoadScripts = true);
|
||||
void* GetCallbackData() { return mCallbackData; }
|
||||
void GetParamsForMessage(const jsval& aObject,
|
||||
JSContext* aCx,
|
||||
nsAString& aJSON);
|
||||
nsresult SendAsyncMessageInternal(const nsAString& aMessage,
|
||||
const nsAString& aJSON);
|
||||
const StructuredCloneData& aData);
|
||||
JSContext* GetJSContext() { return mContext; }
|
||||
void SetJSContext(JSContext* aCx) { mContext = aCx; }
|
||||
void RemoveFromParent();
|
||||
@ -257,4 +258,4 @@ class nsScriptCacheCleaner MOZ_FINAL : public nsIObserver
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
@ -20,10 +20,14 @@
|
||||
#include "xpcpublic.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
|
||||
using mozilla::dom::StructuredCloneData;
|
||||
using mozilla::dom::StructuredCloneClosure;
|
||||
|
||||
bool SendSyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
const StructuredCloneData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsInProcessTabChildGlobal* tabChild =
|
||||
@ -38,7 +42,7 @@ bool SendSyncMessageToParent(void* aCallbackData,
|
||||
}
|
||||
if (tabChild->mChromeMessageManager) {
|
||||
nsRefPtr<nsFrameMessageManager> mm = tabChild->mChromeMessageManager;
|
||||
mm->ReceiveMessage(owner, aMessage, true, aJSON, nullptr, aJSONRetVal);
|
||||
mm->ReceiveMessage(owner, aMessage, true, &aData, nullptr, aJSONRetVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -47,32 +51,45 @@ class nsAsyncMessageToParent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsAsyncMessageToParent(nsInProcessTabChildGlobal* aTabChild,
|
||||
const nsAString& aMessage, const nsAString& aJSON)
|
||||
: mTabChild(aTabChild), mMessage(aMessage), mJSON(aJSON) {}
|
||||
const nsAString& aMessage,
|
||||
const StructuredCloneData& aData)
|
||||
: mTabChild(aTabChild), mMessage(aMessage)
|
||||
{
|
||||
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
|
||||
NS_RUNTIMEABORT("OOM");
|
||||
}
|
||||
mClosure = aData.mClosure;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mTabChild->mASyncMessages.RemoveElement(this);
|
||||
if (mTabChild->mChromeMessageManager) {
|
||||
StructuredCloneData data;
|
||||
data.mData = mData.data();
|
||||
data.mDataLength = mData.nbytes();
|
||||
data.mClosure = mClosure;
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
|
||||
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false,
|
||||
mJSON, nullptr, nullptr);
|
||||
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data,
|
||||
nullptr, nullptr, nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
|
||||
nsString mMessage;
|
||||
nsString mJSON;
|
||||
JSAutoStructuredCloneBuffer mData;
|
||||
StructuredCloneClosure mClosure;
|
||||
};
|
||||
|
||||
bool SendAsyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
nsInProcessTabChildGlobal* tabChild =
|
||||
static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsAsyncMessageToParent(tabChild, aMessage, aJSON);
|
||||
new nsAsyncMessageToParent(tabChild, aMessage, aData);
|
||||
tabChild->mASyncMessages.AppendElement(ev);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
return true;
|
||||
|
@ -552,6 +552,7 @@ MOCHITEST_FILES_B = \
|
||||
file_XHR_anon.sjs \
|
||||
test_XHR_system.html \
|
||||
test_XHR_parameters.html \
|
||||
test_ipc_messagemanager_blob.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
|
111
content/base/test/test_ipc_messagemanager_blob.html
Normal file
111
content/base/test/test_ipc_messagemanager_blob.html
Normal file
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for OOP Blobs in MessageManager</title>
|
||||
<script type="application/javascript"
|
||||
src="/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const childFrameURL =
|
||||
"data:text/html,<!DOCTYPE HTML><html><body></body></html>";
|
||||
|
||||
function childFrameScript() {
|
||||
"use strict";
|
||||
|
||||
addMessageListener("test:ipcClonedMessage", function(message) {
|
||||
if (!(message.json instanceof Components.interfaces.nsIDOMBlob)) {
|
||||
sendAsyncMessage(message.name, message.json);
|
||||
return;
|
||||
}
|
||||
|
||||
let reader =
|
||||
Components.classes["@mozilla.org/files/filereader;1"]
|
||||
.createInstance(Components.interfaces.nsIDOMFileReader);
|
||||
reader.addEventListener("load", function() {
|
||||
let response = reader.result == "this is a great success!" ?
|
||||
message.json :
|
||||
"error";
|
||||
sendAsyncMessage(message.name, response);
|
||||
});
|
||||
reader.readAsText(message.json);
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
ok("Browser prefs set.");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.mozbrowser = true;
|
||||
iframe.id = "iframe";
|
||||
iframe.src = childFrameURL;
|
||||
|
||||
iframe.addEventListener("mozbrowserloadend", function() {
|
||||
ok(true, "Got iframe load event.");
|
||||
|
||||
const messages = [
|
||||
"hi!",
|
||||
"",
|
||||
2,
|
||||
-.04,
|
||||
3432987324987239872948732982,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
0,
|
||||
new Blob(["this ", "is ", "a ", "great ", "success!"],
|
||||
{"type" : "text\/plain"}),
|
||||
];
|
||||
let receivedMessageIndex = 0;
|
||||
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
mm.addMessageListener("test:ipcClonedMessage", function(message) {
|
||||
is(message.json, messages[receivedMessageIndex++],
|
||||
"Got correct round-tripped response");
|
||||
if (receivedMessageIndex == messages.length) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
|
||||
false);
|
||||
|
||||
for each (let message in messages) {
|
||||
mm.sendAsyncMessage("test:ipcClonedMessage", message);
|
||||
}
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
addEventListener("load", function() {
|
||||
info("Got load event.");
|
||||
|
||||
let whitelist;
|
||||
try {
|
||||
whitelist =
|
||||
SpecialPowers.getCharPref("dom.mozBrowserFramesWhitelist") + ", ";
|
||||
} catch (e) {
|
||||
whitelist = "";
|
||||
}
|
||||
|
||||
whitelist += window.location.protocol + "//" + window.location.host;
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.mozBrowserFramesWhitelist", whitelist],
|
||||
["browser.pageThumbs.enabled", false]
|
||||
]
|
||||
}, runTests);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -74,12 +74,13 @@ NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
|
||||
}
|
||||
|
||||
WebGLContextOptions::WebGLContextOptions()
|
||||
: depth(true), stencil(false),
|
||||
: alpha(true), depth(true), stencil(false),
|
||||
premultipliedAlpha(true), antialias(true),
|
||||
preserveDrawingBuffer(false)
|
||||
{
|
||||
// Set default alpha state based on preference.
|
||||
alpha = Preferences::GetBool("webgl.default-no-alpha", false) ? 0 : 1;
|
||||
if (Preferences::GetBool("webgl.default-no-alpha", false))
|
||||
alpha = false;
|
||||
}
|
||||
|
||||
WebGLContext::WebGLContext()
|
||||
|
@ -289,21 +289,21 @@ public:
|
||||
#ifdef MOZ_WAVE
|
||||
static bool IsWaveEnabled();
|
||||
static bool IsWaveType(const nsACString& aType);
|
||||
static const char gWaveTypes[4][16];
|
||||
static const char gWaveTypes[4][15];
|
||||
static char const *const gWaveCodecs[2];
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBM
|
||||
static bool IsWebMEnabled();
|
||||
static bool IsWebMType(const nsACString& aType);
|
||||
static const char gWebMTypes[2][17];
|
||||
static const char gWebMTypes[2][11];
|
||||
static char const *const gWebMCodecs[4];
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GSTREAMER
|
||||
static bool IsH264Enabled();
|
||||
static bool IsH264Type(const nsACString& aType);
|
||||
static const char gH264Types[3][17];
|
||||
static const char gH264Types[3][16];
|
||||
static char const *const gH264Codecs[7];
|
||||
#endif
|
||||
|
||||
|
@ -1959,12 +1959,12 @@ void nsHTMLMediaElement::UnbindFromTree(bool aDeep,
|
||||
}
|
||||
|
||||
#ifdef MOZ_RAW
|
||||
static const char gRawTypes[][16] = {
|
||||
static const char gRawTypes[2][16] = {
|
||||
"video/x-raw",
|
||||
"video/x-raw-yuv"
|
||||
};
|
||||
|
||||
static const char* gRawCodecs[] = {
|
||||
static const char* gRawCodecs[1] = {
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -2048,7 +2048,7 @@ nsHTMLMediaElement::IsOggType(const nsACString& aType)
|
||||
// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
|
||||
// of WAVE media types and codec types. However, the audio/vnd.wave
|
||||
// MIME type described there is not used.
|
||||
const char nsHTMLMediaElement::gWaveTypes[4][16] = {
|
||||
const char nsHTMLMediaElement::gWaveTypes[4][15] = {
|
||||
"audio/x-wav",
|
||||
"audio/wav",
|
||||
"audio/wave",
|
||||
@ -2084,7 +2084,7 @@ nsHTMLMediaElement::IsWaveType(const nsACString& aType)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBM
|
||||
const char nsHTMLMediaElement::gWebMTypes[2][17] = {
|
||||
const char nsHTMLMediaElement::gWebMTypes[2][11] = {
|
||||
"video/webm",
|
||||
"audio/webm"
|
||||
};
|
||||
@ -2120,7 +2120,7 @@ nsHTMLMediaElement::IsWebMType(const nsACString& aType)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GSTREAMER
|
||||
const char nsHTMLMediaElement::gH264Types[3][17] = {
|
||||
const char nsHTMLMediaElement::gH264Types[3][16] = {
|
||||
"video/mp4",
|
||||
"video/3gpp",
|
||||
"video/quicktime",
|
||||
|
@ -35,7 +35,7 @@ function createTestArray() {
|
||||
var tests = [];
|
||||
var tmpVid = document.createElement("video");
|
||||
|
||||
for (var testNum=0; testNum<gSeekTests.length; testNum++) {
|
||||
for (var testNum=0; testNum<gInfoLeakTests.length; testNum++) {
|
||||
var test = gInfoLeakTests[testNum];
|
||||
if (!tmpVid.canPlayType(test.type)) {
|
||||
continue;
|
||||
|
@ -16,9 +16,9 @@ DIRS = \
|
||||
interfaces/base \
|
||||
interfaces/canvas \
|
||||
interfaces/core \
|
||||
interfaces/devicestorage \
|
||||
interfaces/html \
|
||||
interfaces/events \
|
||||
interfaces/devicestorage \
|
||||
interfaces/contacts \
|
||||
interfaces/settings \
|
||||
interfaces/stylesheets \
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "nsMimeTypeArray.h"
|
||||
#include "nsDesktopNotification.h"
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsIHttpProtocolHandler.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsIDocShell.h"
|
||||
@ -192,6 +191,12 @@ Navigator::Invalidate()
|
||||
}
|
||||
#endif
|
||||
|
||||
PRUint32 len = mDeviceStorageStores.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
mDeviceStorageStores[i]->Shutdown();
|
||||
}
|
||||
mDeviceStorageStores.Clear();
|
||||
|
||||
}
|
||||
|
||||
nsPIDOMWindow *
|
||||
@ -873,7 +878,7 @@ Navigator::MozIsLocallyAvailable(const nsAString &aURI,
|
||||
// Navigator::nsIDOMNavigatorDeviceStorage
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMETHODIMP Navigator::GetDeviceStorage(const nsAString &aType, nsIVariant** _retval)
|
||||
NS_IMETHODIMP Navigator::GetDeviceStorage(const nsAString &aType, nsIDOMDeviceStorage** _retval)
|
||||
{
|
||||
if (!Preferences::GetBool("device.storage.enabled", false)) {
|
||||
return NS_OK;
|
||||
@ -885,7 +890,15 @@ NS_IMETHODIMP Navigator::GetDeviceStorage(const nsAString &aType, nsIVariant** _
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(win, aType, _retval);
|
||||
nsRefPtr<nsDOMDeviceStorage> storage;
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(win, aType, getter_AddRefs(storage));
|
||||
|
||||
if (!storage) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ADDREF(*_retval = storage.get());
|
||||
mDeviceStorageStores.AppendElement(storage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsIDOMNavigatorNetwork.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "DeviceStorage.h"
|
||||
|
||||
class nsPluginArray;
|
||||
class nsMimeTypeArray;
|
||||
@ -162,6 +163,7 @@ private:
|
||||
#endif
|
||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
|
||||
nsWeakPtr mWindow;
|
||||
};
|
||||
|
||||
|
@ -140,6 +140,7 @@
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
||||
// CSS related includes
|
||||
#include "nsCSSRules.h"
|
||||
#include "nsIDOMStyleSheet.h"
|
||||
#include "nsIDOMStyleSheetList.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
@ -289,6 +290,7 @@
|
||||
#include "nsIDOMCSSMediaRule.h"
|
||||
#include "nsIDOMCSSFontFaceRule.h"
|
||||
#include "nsIDOMCSSMozDocumentRule.h"
|
||||
#include "nsIDOMCSSSupportsRule.h"
|
||||
#include "nsIDOMMozCSSKeyframeRule.h"
|
||||
#include "nsIDOMMozCSSKeyframesRule.h"
|
||||
#include "nsIDOMCSSPrimitiveValue.h"
|
||||
@ -418,6 +420,7 @@
|
||||
|
||||
// Device Storage
|
||||
#include "nsIDOMDeviceStorage.h"
|
||||
#include "nsIDOMDeviceStorageChangeEvent.h"
|
||||
#include "nsIDOMDeviceStorageCursor.h"
|
||||
|
||||
// Drag and drop
|
||||
@ -1088,6 +1091,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(BeforeUnloadEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
@ -1431,7 +1437,10 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(MessageEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DeviceStorage, nsDOMGenericSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(DeviceStorage, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DeviceStorageChangeEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DeviceStorageCursor, nsDOMGenericSH,
|
||||
@ -3171,6 +3180,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(CSSSupportsRule, nsIDOMCSSSupportsRule)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(BeforeUnloadEvent, nsIDOMBeforeUnloadEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBeforeUnloadEvent)
|
||||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||
@ -4027,6 +4040,12 @@ nsDOMClassInfo::Init()
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DeviceStorage, nsIDOMDeviceStorage)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceStorage)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DeviceStorageChangeEvent, nsIDOMDeviceStorageChangeEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceStorageChangeEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DeviceStorageCursor, nsIDOMDeviceStorageCursor)
|
||||
@ -5815,16 +5834,12 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
|
||||
}
|
||||
case nsXPTType::T_I32:
|
||||
{
|
||||
if (!JS_NewNumberValue(cx, c->GetValue()->val.i32, &v)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
v = JS_NumberValue(c->GetValue()->val.i32);
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_U32:
|
||||
{
|
||||
if (!JS_NewNumberValue(cx, c->GetValue()->val.u32, &v)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
v = JS_NumberValue(c->GetValue()->val.u32);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -6697,6 +6712,13 @@ ConstructorEnabled(const nsGlobalNameStruct *aStruct, nsGlobalWindow *aWin)
|
||||
}
|
||||
}
|
||||
|
||||
// Don't expose CSSSupportsRule unless @supports processing is enabled.
|
||||
if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
|
||||
if (!CSSSupportsRule::PrefEnabled()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -193,6 +193,7 @@ DOMCI_CLASS(TreeColumns)
|
||||
#endif
|
||||
|
||||
DOMCI_CLASS(CSSMozDocumentRule)
|
||||
DOMCI_CLASS(CSSSupportsRule)
|
||||
|
||||
DOMCI_CLASS(BeforeUnloadEvent)
|
||||
|
||||
@ -384,6 +385,7 @@ DOMCI_CLASS(DataContainerEvent)
|
||||
DOMCI_CLASS(MessageEvent)
|
||||
|
||||
DOMCI_CLASS(DeviceStorage)
|
||||
DOMCI_CLASS(DeviceStorageChangeEvent)
|
||||
DOMCI_CLASS(DeviceStorageCursor)
|
||||
|
||||
// Geolocation
|
||||
|
@ -8349,7 +8349,8 @@ nsGlobalWindow::GetIndexedDB(nsIIDBFactory** _retval)
|
||||
}
|
||||
|
||||
// This may be null if being created from a file.
|
||||
rv = indexedDB::IDBFactory::Create(this, getter_AddRefs(mIndexedDB));
|
||||
rv = indexedDB::IDBFactory::Create(this, nullptr,
|
||||
getter_AddRefs(mIndexedDB));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -2412,8 +2412,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv)
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
JSBool ok = ::JS_NewNumberValue(cx, data, aArgv);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
*aArgv = ::JS_NumberValue(data);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -2425,8 +2424,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv)
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
JSBool ok = ::JS_NewNumberValue(cx, data, aArgv);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
*aArgv = ::JS_NumberValue(data);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2056,9 +2056,9 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
"%s.SetNull()" % varName)
|
||||
return handleDefault(
|
||||
conversionCode,
|
||||
("static const PRUnichar data[] = { %s, 0 };\n"
|
||||
("static const PRUnichar data[] = { %s };\n"
|
||||
"%s.SetData(data, ArrayLength(data) - 1)" %
|
||||
(", ".join("'" + char + "'" for char in defaultValue.value),
|
||||
(", ".join(["'" + char + "'" for char in defaultValue.value] + ["0"]),
|
||||
varName)))
|
||||
|
||||
if isMember:
|
||||
@ -2586,7 +2586,7 @@ if (!%(resultStr)s) {
|
||||
IDLType.Tags.double]:
|
||||
# XXXbz will cast to double do the "even significand" thing that webidl
|
||||
# calls for for 64-bit ints? Do we care?
|
||||
return wrapAndSetPtr("JS_NewNumberValue(cx, double(%s), ${jsvalPtr})" % result)
|
||||
return setValue("JS_NumberValue(double(%s))" % result)
|
||||
|
||||
elif tag == IDLType.Tags.uint32:
|
||||
return setValue("UINT_TO_JSVAL(%s)" % result)
|
||||
|
@ -357,6 +357,7 @@ dictionary Dict : ParentDict {
|
||||
long b = 8;
|
||||
long z = 9;
|
||||
DOMString str;
|
||||
DOMString empty = "";
|
||||
TestEnum otherEnum = "b";
|
||||
DOMString otherStr = "def";
|
||||
DOMString? yetAnotherStr = null;
|
||||
|
@ -154,9 +154,9 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
if (sc) {
|
||||
rv =
|
||||
StringArrayToJSArray(sc->GetNativeContext(),
|
||||
sc->GetNativeGlobal(), mUuids, &mJsDeviceAddresses);
|
||||
sc->GetNativeGlobal(), mDeviceAddresses, &mJsDeviceAddresses);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cannot set JS Devices Addresses object!");
|
||||
NS_WARNING("Cannot set JS Device Addresses object!");
|
||||
return;
|
||||
}
|
||||
Root();
|
||||
@ -335,7 +335,7 @@ BluetoothAdapter::GetDevices(JSContext* aCx, jsval* aDevices)
|
||||
aDevices->setObject(*mJsDeviceAddresses);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("UUIDs not yet set!\n");
|
||||
NS_WARNING("Devices not yet set!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -50,12 +50,10 @@ ParseZoomRatioItemAndAdd(JSContext* aCx, JSObject* aArray, PRUint32 aIndex, cons
|
||||
}
|
||||
|
||||
double d = strtod(aStart, aEnd);
|
||||
jsval v;
|
||||
|
||||
d /= 100;
|
||||
if (!JS_NewNumberValue(aCx, d, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
jsval v = JS_NumberValue(d);
|
||||
|
||||
if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
73
dom/devicestorage/DeviceStorage.h
Normal file
73
dom/devicestorage/DeviceStorage.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* 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 DeviceStorage_h
|
||||
#define DeviceStorage_h
|
||||
|
||||
#include "nsIDOMDeviceStorage.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
|
||||
class nsDOMDeviceStorage MOZ_FINAL
|
||||
: public nsIDOMDeviceStorage
|
||||
, public nsIFileUpdateListener
|
||||
, public nsDOMEventTargetHelper
|
||||
, public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMDEVICESTORAGE
|
||||
|
||||
NS_DECL_NSIFILEUPDATELISTENER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
|
||||
NS_DECL_EVENT_HANDLER(change)
|
||||
|
||||
nsDOMDeviceStorage();
|
||||
|
||||
nsresult Init(nsPIDOMWindow* aWindow, const nsAString &aType);
|
||||
|
||||
void SetRootFileForType(const nsAString& aType);
|
||||
|
||||
static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
|
||||
const nsAString &aType,
|
||||
nsDOMDeviceStorage** aStore);
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorage();
|
||||
|
||||
nsresult GetInternal(const JS::Value & aName,
|
||||
JSContext* aCx,
|
||||
nsIDOMDOMRequest** aRetval,
|
||||
bool aEditable);
|
||||
|
||||
nsresult EnumerateInternal(const JS::Value & aName,
|
||||
const JS::Value & aOptions,
|
||||
JSContext* aCx,
|
||||
PRUint8 aArgc,
|
||||
bool aEditable,
|
||||
nsIDOMDeviceStorageCursor** aRetval);
|
||||
|
||||
PRInt32 mStorageType;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
friend class WatchFileEvent;
|
||||
friend class DeviceStorageRequest;
|
||||
|
||||
bool mIsWatchingFile;
|
||||
|
||||
// nsIDOMDeviceStorage.type
|
||||
enum {
|
||||
DEVICE_STORAGE_TYPE_DEFAULT = 0,
|
||||
DEVICE_STORAGE_TYPE_SHARED,
|
||||
DEVICE_STORAGE_TYPE_EXTERNAL,
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -31,7 +31,7 @@ CPPSRCS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsDeviceStorage.h \
|
||||
DeviceStorage.h \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -2,7 +2,15 @@
|
||||
* 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/ContentChild.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestChild.h"
|
||||
|
||||
#include "nsDeviceStorage.h"
|
||||
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIDirectoryEnumerator.h"
|
||||
@ -21,6 +29,10 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "TabChild.h"
|
||||
#include "DeviceStorageRequestChild.h"
|
||||
#include "nsIDOMDeviceStorageChangeEvent.h"
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
// Microsoft's API Name hackery sucks
|
||||
#undef CreateEvent
|
||||
@ -90,8 +102,8 @@ DeviceStorageFile::IsSafePath()
|
||||
|
||||
while ((token = nsCRT::strtok(buffer, "/", &buffer))) {
|
||||
if (PL_strcmp(token, "") == 0 ||
|
||||
PL_strcmp(token, ".") == 0 ||
|
||||
PL_strcmp(token, "..") == 0 ) {
|
||||
PL_strcmp(token, ".") == 0 ||
|
||||
PL_strcmp(token, "..") == 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -153,8 +165,8 @@ DeviceStorageFile::Write(nsIDOMBlob* aBlob)
|
||||
|
||||
nsCOMPtr<nsIOutputStream> bufferedOutputStream;
|
||||
NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
|
||||
outputStream,
|
||||
4096*4);
|
||||
outputStream,
|
||||
4096*4);
|
||||
|
||||
if (!bufferedOutputStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -197,18 +209,21 @@ DeviceStorageFile::Write(InfallibleTArray<PRUint8>& aBits) {
|
||||
|
||||
void
|
||||
DeviceStorageFile::CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
|
||||
PRUint64 aSince)
|
||||
PRUint64 aSince)
|
||||
{
|
||||
nsString rootPath;
|
||||
mFile->GetPath(rootPath);
|
||||
nsresult rv = mFile->GetPath(rootPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return collectFilesInternal(aFiles, aSince, rootPath);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
|
||||
PRUint64 aSince,
|
||||
nsAString& aRootPath)
|
||||
PRUint64 aSince,
|
||||
nsAString& aRootPath)
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> e;
|
||||
mFile->GetDirectoryEntries(getter_AddRefs(e));
|
||||
@ -236,7 +251,10 @@ DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &
|
||||
f->IsFile(&isFile);
|
||||
|
||||
nsString fullpath;
|
||||
f->GetPath(fullpath);
|
||||
nsresult rv = f->GetPath(fullpath);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!StringBeginsWith(fullpath, aRootPath)) {
|
||||
NS_ERROR("collectFiles returned a path that does not belong!");
|
||||
@ -261,14 +279,9 @@ DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS0(DeviceStorageFile)
|
||||
|
||||
|
||||
// TODO - eventually, we will want to factor this method
|
||||
// out into different system specific subclasses (or
|
||||
// something)
|
||||
PRInt32
|
||||
nsDOMDeviceStorage::SetRootFileForType(const nsAString& aType, const PRInt32 aIndex)
|
||||
void
|
||||
nsDOMDeviceStorage::SetRootFileForType(const nsAString& aType)
|
||||
{
|
||||
PRInt32 typeResult = DEVICE_STORAGE_TYPE_DEFAULT;
|
||||
|
||||
nsCOMPtr<nsIFile> f;
|
||||
nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
NS_ASSERTION(dirService, "Must have directory service");
|
||||
@ -278,72 +291,54 @@ nsDOMDeviceStorage::SetRootFileForType(const nsAString& aType, const PRInt32 aIn
|
||||
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
if (!vs) {
|
||||
return typeResult;
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIVolume> v;
|
||||
vs->GetVolumeByPath(NS_LITERAL_STRING("/sdcard"), getter_AddRefs(v));
|
||||
|
||||
if (!v) {
|
||||
return typeResult;
|
||||
return;
|
||||
}
|
||||
|
||||
PRInt32 state;
|
||||
v->GetState(&state);
|
||||
|
||||
if (state != nsIVolume::STATE_MOUNTED) {
|
||||
return typeResult;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Picture directory
|
||||
if (aType.Equals(NS_LITERAL_STRING("pictures"))) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (aIndex == 0) {
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/DCIM"), false, getter_AddRefs(f));
|
||||
}
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/DCIM"), false, getter_AddRefs(f));
|
||||
#elif defined (MOZ_WIDGET_COCOA)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#elif defined (XP_UNIX)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Video directory
|
||||
if (aType.Equals(NS_LITERAL_STRING("videos"))) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (aIndex == 0) {
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/Movies"), false, getter_AddRefs(f));
|
||||
}
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/Movies"), false, getter_AddRefs(f));
|
||||
#elif defined (MOZ_WIDGET_COCOA)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#elif defined (XP_UNIX)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Music directory
|
||||
if (aType.Equals(NS_LITERAL_STRING("music"))) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (aIndex == 0) {
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/Music"), false, getter_AddRefs(f));
|
||||
}
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/sdcard/Music"), false, getter_AddRefs(f));
|
||||
#elif defined (MOZ_WIDGET_COCOA)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#elif defined (XP_UNIX)
|
||||
if (aIndex == 0) {
|
||||
dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
}
|
||||
dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -351,17 +346,17 @@ nsDOMDeviceStorage::SetRootFileForType(const nsAString& aType, const PRInt32 aIn
|
||||
if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
|
||||
|
||||
// testing directory
|
||||
if (aType.Equals(NS_LITERAL_STRING("testing")) && aIndex == 0) {
|
||||
if (aType.Equals(NS_LITERAL_STRING("testing"))) {
|
||||
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
if (f) {
|
||||
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
|
||||
f->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
f->Normalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mFile = f;
|
||||
return typeResult;
|
||||
}
|
||||
|
||||
static jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile)
|
||||
@ -443,6 +438,92 @@ jsval StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
|
||||
return result;
|
||||
}
|
||||
|
||||
class nsDOMDeviceStorageChangeEvent : public nsDOMEvent, public nsIDOMDeviceStorageChangeEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
|
||||
NS_DECL_NSIDOMDEVICESTORAGECHANGEEVENT
|
||||
|
||||
nsDOMDeviceStorageChangeEvent();
|
||||
|
||||
virtual nsresult InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx,
|
||||
jsval* aVal);
|
||||
|
||||
NS_IMETHOD Init(const nsAString & aEventTypeArg,
|
||||
bool aCanBubbleArg,
|
||||
bool aCancelableArg,
|
||||
nsAString& aPath,
|
||||
nsAString& aReason);
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorageChangeEvent();
|
||||
|
||||
protected:
|
||||
nsString mPath;
|
||||
nsString mReason;
|
||||
};
|
||||
|
||||
DOMCI_DATA(DeviceStorageChangeEvent, nsDOMDeviceStorageChangeEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorageChangeEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorageChangeEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorageChangeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorageChangeEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorageChangeEvent, nsDOMEvent)
|
||||
|
||||
nsDOMDeviceStorageChangeEvent::nsDOMDeviceStorageChangeEvent()
|
||||
: nsDOMEvent(nullptr, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMDeviceStorageChangeEvent::~nsDOMDeviceStorageChangeEvent()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageChangeEvent::Init(const nsAString & aEventTypeArg,
|
||||
bool aCanBubbleArg,
|
||||
bool aCancelableArg,
|
||||
nsAString& aPath,
|
||||
nsAString& aReason)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aEventTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mPath = aPath;
|
||||
mReason = aReason;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorageChangeEvent::InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx,
|
||||
jsval* aVal)
|
||||
{
|
||||
mozilla::dom::DeviceStorageChangeEventInit d;
|
||||
nsresult rv = d.Init(aCx, aVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return Init(aType, d.bubbles, d.cancelable, d.path, d.reason);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageChangeEvent::GetPath(nsAString & aPath)
|
||||
{
|
||||
aPath = mPath;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageChangeEvent::GetReason(nsAString & aReason)
|
||||
{
|
||||
aReason = mReason;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class DeviceStorageCursorRequest MOZ_FINAL
|
||||
: public nsIContentPermissionRequest
|
||||
, public PCOMContentPermissionRequestChild
|
||||
@ -488,11 +569,11 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(DeviceStorageCursorRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(DeviceStorageCursorRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DeviceStorageCursorRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCursor)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCursor)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DeviceStorageCursorRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCursor, nsIDOMDeviceStorageCursor)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCursor, nsIDOMDeviceStorageCursor)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
||||
@ -707,7 +788,12 @@ nsDOMDeviceStorageCursor::Allow()
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
|
||||
nsString fullpath;
|
||||
mFile->mFile->GetPath(fullpath);
|
||||
nsresult rv = mFile->mFile->GetPath(fullpath);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// just do nothing
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(this, mFile);
|
||||
DeviceStorageEnumerationParams params(fullpath, mSince);
|
||||
@ -827,14 +913,14 @@ public:
|
||||
mFile->mFile->Remove(false);
|
||||
|
||||
nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mRequest,
|
||||
POST_ERROR_EVENT_UNKNOWN,
|
||||
mFile);
|
||||
POST_ERROR_EVENT_UNKNOWN,
|
||||
mFile);
|
||||
NS_DispatchToMainThread(event);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<PostResultEvent> event = new PostResultEvent(mRequest,
|
||||
mFile->mPath);
|
||||
mFile->mPath);
|
||||
NS_DispatchToMainThread(event);
|
||||
|
||||
return NS_OK;
|
||||
@ -927,23 +1013,40 @@ class DeviceStorageRequest MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
enum DeviceStorageRequestType {
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH
|
||||
};
|
||||
DeviceStorageRequest(const PRInt32 aRequestType,
|
||||
|
||||
DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
|
||||
nsPIDOMWindow *aWindow,
|
||||
nsIURI *aURI,
|
||||
DeviceStorageFile *aFile,
|
||||
DOMRequest* aRequest,
|
||||
nsDOMDeviceStorage *aDeviceStorage,
|
||||
nsIDOMEventListener *aListener)
|
||||
: mRequestType(aRequestType)
|
||||
, mWindow(aWindow)
|
||||
, mURI(aURI)
|
||||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mDeviceStorage(aDeviceStorage)
|
||||
, mListener(aListener) {}
|
||||
|
||||
DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
|
||||
nsPIDOMWindow *aWindow,
|
||||
nsIURI *aURI,
|
||||
DeviceStorageFile *aFile,
|
||||
DOMRequest* aRequest,
|
||||
nsIDOMBlob *aBlob = nullptr)
|
||||
: mRequestType(aRequestType)
|
||||
, mWindow(aWindow)
|
||||
, mURI(aURI)
|
||||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mBlob(aBlob) {}
|
||||
: mRequestType(aRequestType)
|
||||
, mWindow(aWindow)
|
||||
, mURI(aURI)
|
||||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mBlob(aBlob) {}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest, nsIContentPermissionRequest)
|
||||
@ -960,8 +1063,9 @@ public:
|
||||
// because owner implements nsITabChild, we can assume that it is
|
||||
// the one and only TabChild.
|
||||
TabChild* child = GetTabChildFrom(mWindow->GetDocShell());
|
||||
if (!child)
|
||||
if (!child) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Retain a reference so the object isn't deleted without IPDL's knowledge.
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
@ -1023,7 +1127,12 @@ public:
|
||||
}
|
||||
|
||||
nsString fullpath;
|
||||
mFile->mFile->GetPath(fullpath);
|
||||
nsresult rv = mFile->mFile->GetPath(fullpath);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// just do nothing
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
switch(mRequestType) {
|
||||
case DEVICE_STORAGE_REQUEST_WRITE:
|
||||
@ -1032,52 +1141,74 @@ public:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
mBlob->GetInternalStream(getter_AddRefs(stream));
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
mBlob->GetInternalStream(getter_AddRefs(stream));
|
||||
|
||||
InfallibleTArray<PRUint8> bits;
|
||||
PRUint32 bufSize, numRead;
|
||||
InfallibleTArray<PRUint8> bits;
|
||||
PRUint32 bufSize, numRead;
|
||||
|
||||
stream->Available(&bufSize);
|
||||
bits.SetCapacity(bufSize);
|
||||
stream->Available(&bufSize);
|
||||
bits.SetCapacity(bufSize);
|
||||
|
||||
void* buffer = (void*) bits.Elements();
|
||||
void* buffer = (void*) bits.Elements();
|
||||
|
||||
stream->Read((char*)buffer, bufSize, &numRead);
|
||||
stream->Read((char*)buffer, bufSize, &numRead);
|
||||
|
||||
DeviceStorageAddParams params(fullpath, bits);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
r = new WriteFileEvent(mBlob, mFile, mRequest);
|
||||
DeviceStorageAddParams params(fullpath, bits);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
r = new WriteFileEvent(mBlob, mFile, mRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
case DEVICE_STORAGE_REQUEST_READ:
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
DeviceStorageGetParams params(fullpath);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
DeviceStorageGetParams params(fullpath);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
r = new ReadFileEvent(mFile, mRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
case DEVICE_STORAGE_REQUEST_DELETE:
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
DeviceStorageDeleteParams params(fullpath);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
|
||||
DeviceStorageDeleteParams params(fullpath);
|
||||
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
|
||||
return NS_OK;
|
||||
}
|
||||
r = new DeleteFileEvent(mFile, mRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
case DEVICE_STORAGE_REQUEST_WATCH:
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
nsString fullpath;
|
||||
mFile->mFile->GetPath(fullpath);
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->AddObserver(mDeviceStorage, "file-watcher-update", false);
|
||||
ContentChild::GetSingleton()->SendAddFileWatch(fullpath);
|
||||
} else {
|
||||
if (!mDeviceStorage->mIsWatchingFile) {
|
||||
|
||||
//TODO
|
||||
|
||||
mFile->mFile->Watch(mDeviceStorage);
|
||||
mDeviceStorage->mIsWatchingFile = true;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
@ -1112,6 +1243,8 @@ private:
|
||||
|
||||
nsRefPtr<DOMRequest> mRequest;
|
||||
nsCOMPtr<nsIDOMBlob> mBlob;
|
||||
nsRefPtr<nsDOMDeviceStorage> mDeviceStorage;
|
||||
nsCOMPtr<nsIDOMEventListener> mListener;
|
||||
};
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeviceStorageRequest)
|
||||
@ -1128,44 +1261,55 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DeviceStorageRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mBlob)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDeviceStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DeviceStorageRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRequest, nsIDOMDOMRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow, nsPIDOMWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mBlob, nsIDOMBlob)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mDeviceStorage, nsIDOMDeviceStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mListener, nsIDOMEventListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDeviceStorage)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(change)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(change)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
DOMCI_DATA(DeviceStorage, nsDOMDeviceStorage)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorage)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDeviceStorage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorage)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDeviceStorage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIFileUpdateListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorage)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMDeviceStorage)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMDeviceStorage)
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
|
||||
|
||||
nsDOMDeviceStorage::nsDOMDeviceStorage()
|
||||
: mStorageType(DEVICE_STORAGE_TYPE_DEFAULT)
|
||||
{
|
||||
}
|
||||
: mIsWatchingFile(false)
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType, const PRInt32 aIndex)
|
||||
nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType)
|
||||
{
|
||||
NS_ASSERTION(aWindow, "Must have a content dom");
|
||||
|
||||
mStorageType = SetRootFileForType(aType, aIndex);
|
||||
SetRootFileForType(aType);
|
||||
if (!mFile) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
mOwner = do_GetWeakReference(aWindow);
|
||||
if (!mOwner) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
BindToOwner(aWindow);
|
||||
|
||||
// Grab the uri of the document
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
@ -1183,50 +1327,34 @@ nsDOMDeviceStorage::~nsDOMDeviceStorage()
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
|
||||
const nsAString &aType,
|
||||
nsIVariant** _retval)
|
||||
nsDOMDeviceStorage::Shutdown()
|
||||
{
|
||||
nsTArray<nsRefPtr<nsIDOMDeviceStorage> > stores;
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
PRInt32 index = 0;
|
||||
while (1) {
|
||||
nsresult rv;
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage();
|
||||
rv = storage->Init(aWin, aType, index++);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
stores.AppendElement(storage);
|
||||
if (mIsWatchingFile) {
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(this, "file-watcher-update");
|
||||
|
||||
nsString fullpath;
|
||||
mFile->GetPath(fullpath);
|
||||
ContentChild::GetSingleton()->SendRemoveFileWatch(fullpath);
|
||||
}
|
||||
else {
|
||||
mFile->Unwatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> result = do_CreateInstance("@mozilla.org/variant;1");
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
result->SetAsArray(nsIDataType::VTYPE_INTERFACE,
|
||||
&NS_GET_IID(nsIDOMDeviceStorage),
|
||||
stores.Length(),
|
||||
const_cast<void*>(static_cast<const void*>(stores.Elements())));
|
||||
NS_ADDREF(*_retval = result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::GetType(nsAString & aType)
|
||||
void
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
|
||||
const nsAString &aType,
|
||||
nsDOMDeviceStorage** aStore)
|
||||
{
|
||||
switch(mStorageType) {
|
||||
case DEVICE_STORAGE_TYPE_EXTERNAL:
|
||||
aType.AssignLiteral("external");
|
||||
break;
|
||||
case DEVICE_STORAGE_TYPE_SHARED:
|
||||
aType.AssignLiteral("shared");
|
||||
break;
|
||||
case DEVICE_STORAGE_TYPE_DEFAULT:
|
||||
default:
|
||||
aType.AssignLiteral("default");
|
||||
break;
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage();
|
||||
if (NS_SUCCEEDED(storage->Init(aWin, aType))) {
|
||||
NS_ADDREF(*aStore = storage);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1251,7 +1379,7 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
|
||||
if (aBlob == nullptr)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mOwner);
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -1296,7 +1424,7 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath,
|
||||
nsIDOMDOMRequest * *_retval,
|
||||
bool aEditable)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mOwner);
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -1335,7 +1463,7 @@ nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMReq
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> r;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mOwner);
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -1411,7 +1539,7 @@ nsDOMDeviceStorage::EnumerateInternal(const JS::Value & aName,
|
||||
bool aEditable,
|
||||
nsIDOMDeviceStorageCursor** aRetval)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mOwner);
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
@ -1478,3 +1606,206 @@ nsDOMDeviceStorage::EnumerateInternal(const JS::Value & aName,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
// data strings will have the format of
|
||||
// reason:path
|
||||
nsDependentString data(aData);
|
||||
|
||||
nsAString::const_iterator start, end;
|
||||
nsAString::const_iterator colon;
|
||||
|
||||
data.BeginReading(start);
|
||||
data.EndReading(end);
|
||||
colon = end;
|
||||
|
||||
nsString reason;
|
||||
nsString filepath;
|
||||
if (!FindInReadable(NS_LITERAL_STRING(":"), start, colon)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
filepath = Substring(colon, end);
|
||||
data.BeginReading(start);
|
||||
reason = Substring(start, --colon);
|
||||
|
||||
nsCOMPtr<nsIFile> f;
|
||||
NS_NewLocalFile(filepath, false, getter_AddRefs(f));
|
||||
|
||||
nsCString creason;
|
||||
creason.AssignWithConversion(reason);
|
||||
CopyUTF16toUTF8(reason, creason);
|
||||
|
||||
Update(creason.get(), f);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::Update(const char* aReason, nsIFile* aFile)
|
||||
{
|
||||
nsString rootpath;
|
||||
nsresult rv = mFile->GetPath(rootpath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString fullpath;
|
||||
rv = aFile->GetPath(fullpath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(fullpath.Length() >= rootpath.Length(), "Root path longer than full path!");
|
||||
|
||||
if (!StringBeginsWith(fullpath, rootpath)) {
|
||||
NS_WARNING("Observing a path outside of our root!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAString::size_type len = rootpath.Length() + 1; // +1 for the trailing /
|
||||
nsDependentSubstring newPath (fullpath, len, fullpath.Length() - len);
|
||||
|
||||
nsRefPtr<nsDOMDeviceStorageChangeEvent> event = new nsDOMDeviceStorageChangeEvent();
|
||||
nsString reason;
|
||||
reason.AssignWithConversion(aReason);
|
||||
rv = event->Init(NS_LITERAL_STRING("change"), true, false, newPath, reason);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMDeviceStorageChangeEvent> e = event.get();
|
||||
|
||||
bool ignore;
|
||||
DispatchEvent(e, &ignore);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
|
||||
nsIDOMEventListener *aListener,
|
||||
bool aUseCapture,
|
||||
bool aWantsUntrusted,
|
||||
PRUint8 aArgc)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
||||
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile);
|
||||
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WATCH,
|
||||
win, mURI, dsf, request, this, aListener);
|
||||
NS_DispatchToMainThread(r);
|
||||
return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::AddSystemEventListener(const nsAString & aType,
|
||||
nsIDOMEventListener *aListener,
|
||||
bool aUseCapture,
|
||||
bool aWantsUntrusted,
|
||||
PRUint8 aArgc)
|
||||
{
|
||||
return nsDOMDeviceStorage::AddEventListener(aType,aListener,aUseCapture,aWantsUntrusted, aArgc);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::RemoveEventListener(const nsAString & aType,
|
||||
nsIDOMEventListener *aListener,
|
||||
bool aUseCapture)
|
||||
{
|
||||
nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, false);
|
||||
|
||||
if (mIsWatchingFile && !HasListenersFor(NS_LITERAL_STRING("change"))) {
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(this, "file-watcher-update");
|
||||
|
||||
nsString fullpath;
|
||||
mFile->GetPath(fullpath);
|
||||
ContentChild::GetSingleton()->SendRemoveFileWatch(fullpath);
|
||||
} else {
|
||||
mFile->Unwatch(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::RemoveSystemEventListener(const nsAString & aType,
|
||||
nsIDOMEventListener *aListener,
|
||||
bool aUseCapture)
|
||||
{
|
||||
return nsDOMDeviceStorage::RemoveEventListener(aType, aListener, aUseCapture);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::DispatchEvent(nsIDOMEvent *aEvt,
|
||||
bool *aRetval)
|
||||
{
|
||||
return nsDOMEventTargetHelper::DispatchEvent(aEvt, aRetval);
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMDeviceStorage::GetTargetForDOMEvent()
|
||||
{
|
||||
return nsDOMEventTargetHelper::GetTargetForDOMEvent();
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMDeviceStorage::GetTargetForEventTargetChain()
|
||||
{
|
||||
return nsDOMEventTargetHelper::GetTargetForEventTargetChain();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::PreHandleEvent(nsEventChainPreVisitor & aVisitor)
|
||||
{
|
||||
return nsDOMEventTargetHelper::PreHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::WillHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
return nsDOMEventTargetHelper::WillHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::PostHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
return nsDOMEventTargetHelper::PostHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::DispatchDOMEvent(nsEvent *aEvent,
|
||||
nsIDOMEvent *aDOMEvent,
|
||||
nsPresContext *aPresContext,
|
||||
nsEventStatus *aEventStatus)
|
||||
{
|
||||
return nsDOMEventTargetHelper::DispatchDOMEvent(aEvent,
|
||||
aDOMEvent,
|
||||
aPresContext,
|
||||
aEventStatus);
|
||||
}
|
||||
|
||||
nsEventListenerManager *
|
||||
nsDOMDeviceStorage::GetListenerManager(bool aMayCreate)
|
||||
{
|
||||
return nsDOMEventTargetHelper::GetListenerManager(aMayCreate);
|
||||
}
|
||||
|
||||
nsIScriptContext *
|
||||
nsDOMDeviceStorage::GetContextForEventHandlers(nsresult *aRv)
|
||||
{
|
||||
return nsDOMEventTargetHelper::GetContextForEventHandlers(aRv);
|
||||
}
|
||||
|
||||
JSContext *
|
||||
nsDOMDeviceStorage::GetJSContextForEventHandlers()
|
||||
{
|
||||
return nsDOMEventTargetHelper::GetJSContextForEventHandlers();
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(nsDOMDeviceStorage, change)
|
||||
|
@ -6,28 +6,25 @@
|
||||
#define nsDeviceStorage_h
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
|
||||
|
||||
#include "PCOMContentPermissionRequestChild.h"
|
||||
|
||||
#include "DOMRequest.h"
|
||||
#include "PCOMContentPermissionRequestChild.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestChild.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsIDOMDeviceStorage.h"
|
||||
#include "nsIDOMDeviceStorageCursor.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "DeviceStorage.h"
|
||||
|
||||
|
||||
#define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST "File location doesn't exists"
|
||||
@ -66,41 +63,6 @@ private:
|
||||
void AppendRelativePath();
|
||||
};
|
||||
|
||||
class nsDOMDeviceStorage MOZ_FINAL : public nsIDOMDeviceStorage
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMDEVICESTORAGE
|
||||
|
||||
nsDOMDeviceStorage();
|
||||
|
||||
nsresult Init(nsPIDOMWindow* aWindow, const nsAString &aType, const PRInt32 aIndex);
|
||||
|
||||
PRInt32 SetRootFileForType(const nsAString& aType, const PRInt32 aIndex);
|
||||
|
||||
static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin, const nsAString &aType, nsIVariant** _retval);
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorage();
|
||||
|
||||
nsresult GetInternal(const JS::Value & aName, JSContext* aCx, nsIDOMDOMRequest * *_retval, bool aEditable);
|
||||
|
||||
nsresult EnumerateInternal(const JS::Value & aName, const JS::Value & aOptions, JSContext* aCx, PRUint8 aArgc, bool aEditable, nsIDOMDeviceStorageCursor** aRetval);
|
||||
|
||||
PRInt32 mStorageType;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
|
||||
nsWeakPtr mOwner;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
// nsIDOMDeviceStorage.type
|
||||
enum {
|
||||
DEVICE_STORAGE_TYPE_DEFAULT = 0,
|
||||
DEVICE_STORAGE_TYPE_SHARED,
|
||||
DEVICE_STORAGE_TYPE_EXTERNAL,
|
||||
};
|
||||
};
|
||||
|
||||
class ContinueCursorEvent MOZ_FINAL: public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -59,13 +59,13 @@ function createRandomBlob() {
|
||||
}
|
||||
|
||||
function randomFilename(l) {
|
||||
var set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
|
||||
var result = "";
|
||||
for (var i=0; i<l; i++) {
|
||||
var r = Math.floor(set.length * Math.random());
|
||||
result += set.substring(r, r + 1);
|
||||
}
|
||||
return result;
|
||||
var set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
|
||||
var result = "";
|
||||
for (var i=0; i<l; i++) {
|
||||
var r = Math.floor(set.length * Math.random());
|
||||
result += set.substring(r, r + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function reportErrorAndQuit(e) {
|
||||
|
@ -54,7 +54,7 @@ function deleteSuccess(e) {
|
||||
dump(e.target.result + "\n")
|
||||
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
request = storage[0].get(e.target.result);
|
||||
request = storage.get(e.target.result);
|
||||
request.onsuccess = getAfterDeleteSuccess;
|
||||
request.onerror = getAfterDeleteError;
|
||||
|
||||
@ -77,7 +77,7 @@ function getSuccess(e) {
|
||||
gFileReader.onload = function(e) {
|
||||
readerCallback(e);
|
||||
|
||||
request = storage[0].delete(name)
|
||||
request = storage.delete(name)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
@ -102,7 +102,7 @@ function addSuccess(e) {
|
||||
ok(e.target.result == gFileName, "File name should match");
|
||||
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
request = storage[0].get(gFileName);
|
||||
request = storage.get(gFileName);
|
||||
request.onsuccess = getSuccess;
|
||||
request.onerror = getError;
|
||||
|
||||
@ -119,7 +119,7 @@ ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
ok(storage, "Should have gotten a storage");
|
||||
|
||||
request = storage[0].addNamed(gDataBlob, "devicestorage/hi");
|
||||
request = storage.addNamed(gDataBlob, "devicestorage/hi");
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
|
@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
devicestorage_setup();
|
||||
|
||||
function testingStorage() {
|
||||
return navigator.getDeviceStorage("testing")[0];
|
||||
return navigator.getDeviceStorage("testing");
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
@ -41,7 +41,7 @@ function enumerateSuccess(e) {
|
||||
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);
|
||||
|
||||
// clean up
|
||||
var cleanup = storage[0].delete(prefix + "/" + filename);
|
||||
var cleanup = storage.delete(prefix + "/" + filename);
|
||||
cleanup.onsuccess = function(e) {} // todo - can i remove this?
|
||||
|
||||
e.target.continue();
|
||||
@ -56,7 +56,7 @@ function addSuccess(e) {
|
||||
addedSoFar = addedSoFar + 1;
|
||||
if (addedSoFar == files.length) {
|
||||
|
||||
var cursor = storage[0].enumerate(prefix);
|
||||
var cursor = storage.enumerate(prefix);
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = handleError;
|
||||
}
|
||||
@ -77,7 +77,7 @@ var addedSoFar = 0;
|
||||
|
||||
for (var i=0; i<files.length; i++) {
|
||||
|
||||
request = storage[0].addNamed(createRandomBlob(), prefix + '/' + files[i]);
|
||||
request = storage.addNamed(createRandomBlob(), prefix + '/' + files[i]);
|
||||
|
||||
ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
|
@ -30,7 +30,7 @@ function enumerateSuccess(e) {
|
||||
function enumerateFailure(e) {
|
||||
}
|
||||
|
||||
var cursor = navigator.getDeviceStorage("testing")[0].enumerate();
|
||||
var cursor = navigator.getDeviceStorage("testing").enumerate();
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = enumerateFailure;
|
||||
|
||||
|
@ -45,7 +45,7 @@ function enumerateSuccess(e) {
|
||||
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);
|
||||
|
||||
// clean up
|
||||
var cleanup = storage[0].delete(prefix + "/" + filename);
|
||||
var cleanup = storage.delete(prefix + "/" + filename);
|
||||
cleanup.onsuccess = function(e) {} // todo - can i remove this?
|
||||
|
||||
e.target.continue();
|
||||
@ -60,7 +60,7 @@ function addSuccess(e) {
|
||||
addedSoFar = addedSoFar + 1;
|
||||
if (addedSoFar == files.length) {
|
||||
|
||||
var cursor = storage[0].enumerate();
|
||||
var cursor = storage.enumerate();
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = handleError;
|
||||
}
|
||||
@ -81,7 +81,7 @@ var addedSoFar = 0;
|
||||
|
||||
for (var i=0; i<files.length; i++) {
|
||||
|
||||
request = storage[0].addNamed(createRandomBlob(), prefix + '/' + files[i]);
|
||||
request = storage.addNamed(createRandomBlob(), prefix + '/' + files[i]);
|
||||
|
||||
ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
|
@ -30,43 +30,43 @@ storage = navigator.getDeviceStorage("testing");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate();
|
||||
var cursor = storage.enumerate();
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate no parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate("string");
|
||||
var cursor = storage.enumerate("string");
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate one string parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate("string", "string2");
|
||||
var cursor = storage.enumerate("string", "string2");
|
||||
} catch(e) {throws = true}
|
||||
ok(throws, "enumerate two string parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate("string", {"since": 1});
|
||||
var cursor = storage.enumerate("string", {"since": 1});
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate a string and object parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate({"path": "a"});
|
||||
var cursor = storage.enumerate({"path": "a"});
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate object parameter with path");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate({}, "string");
|
||||
var cursor = storage.enumerate({}, "string");
|
||||
} catch(e) {throws = true}
|
||||
ok(throws, "enumerate object then a string");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage[0].enumerate({"path": "a", "since": 0});
|
||||
var cursor = storage.enumerate({"path": "a", "since": 0});
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate object parameter with path");
|
||||
|
||||
|
@ -45,7 +45,7 @@ function verifyAndDelete(prefix, files, e) {
|
||||
|
||||
// clean up
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
var cleanup = storage[0].delete(prefix + "/" + filename);
|
||||
var cleanup = storage.delete(prefix + "/" + filename);
|
||||
cleanup.onsuccess = function(e) {}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ function enumerateNew() {
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
// 836031600 is a long time ago
|
||||
var cursor = storage[0].enumerate(prefix, {"since": new Date(836031600)});
|
||||
var cursor = storage.enumerate(prefix, {"since": new Date(836031600)});
|
||||
cursor.onsuccess = function(e) {
|
||||
verifyAndDelete(prefix, newFiles, e);
|
||||
if (e.target.result) {
|
||||
|
@ -46,7 +46,7 @@ function addOverwritingError(e) {
|
||||
ok(true, "Adding to the same location should fail");
|
||||
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
request = storage[0].delete(filename)
|
||||
request = storage.delete(filename)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
@ -57,7 +57,7 @@ function addSuccess(e) {
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
request = storage[0].addNamed(createRandomBlob(), filename);
|
||||
request = storage.addNamed(createRandomBlob(), filename);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addOverwritingSuccess;
|
||||
@ -67,7 +67,7 @@ function addSuccess(e) {
|
||||
function addError(e) {
|
||||
// test file is already exists. clean it up and try again..
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
request = storage[0].delete(filename)
|
||||
request = storage.delete(filename)
|
||||
request.onsuccess = runtest;
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ function runtest() {
|
||||
var storage = navigator.getDeviceStorage("testing");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
request = storage[0].addNamed(createRandomBlob(), filename);
|
||||
request = storage.addNamed(createRandomBlob(), filename);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
|
@ -41,7 +41,7 @@ ok(!storage, "kilimanjaro - Should not have this type of storage");
|
||||
storage = navigator.getDeviceStorage("testing");
|
||||
ok(storage, "testing - Should have getDeviceStorage");
|
||||
|
||||
var cursor = storage[0].enumerate();
|
||||
var cursor = storage.enumerate();
|
||||
ok(cursor, "Should have a non-null cursor");
|
||||
|
||||
devicestorage_cleanup();
|
||||
|
@ -516,10 +516,9 @@ LockedFile::GetLocation(JSContext* aCx,
|
||||
if (mLocation == LL_MAXUINT) {
|
||||
*aLocation = JSVAL_NULL;
|
||||
}
|
||||
else if (!JS_NewNumberValue(aCx, double(mLocation), aLocation)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
else {
|
||||
*aLocation = JS_NumberValue(double(mLocation));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -32,17 +32,7 @@ MetadataHelper::GetSuccessResult(JSContext* aCx,
|
||||
NS_ENSURE_TRUE(obj, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (mParams->SizeRequested()) {
|
||||
jsval val;
|
||||
|
||||
if (mParams->Size() <= JSVAL_INT_MAX) {
|
||||
val = INT_TO_JSVAL(mParams->Size());
|
||||
}
|
||||
else {
|
||||
double size = mParams->Size();
|
||||
if (!JS_NewNumberValue(aCx, size, &val)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
jsval val = JS_NumberValue(mParams->Size());
|
||||
|
||||
if (!JS_DefineProperty(aCx, obj, "size", val, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE)) {
|
||||
|
@ -12,6 +12,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
dummy_worker.js \
|
||||
helpers.js \
|
||||
test_append_read_data.html \
|
||||
test_getFileId.html \
|
||||
@ -27,6 +28,7 @@ MOCHITEST_FILES = \
|
||||
test_success_events_after_abort.html \
|
||||
test_truncate.html \
|
||||
test_write_read_data.html \
|
||||
test_workers.html \
|
||||
test_archivereader.html \
|
||||
$(NULL)
|
||||
|
||||
|
8
dom/file/test/dummy_worker.js
Normal file
8
dom/file/test/dummy_worker.js
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
onmessage = function(event) {
|
||||
throw("Shouldn't be called!");
|
||||
}
|
61
dom/file/test/test_workers.html
Normal file
61
dom/file/test/test_workers.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>File Handle Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
var testBuffer = getRandomBuffer(100000);
|
||||
|
||||
for each (let fileStorage in fileStorages) {
|
||||
let request = getFileHandle(fileStorage.key, "test.txt");
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let fileHandle = event.target.result;
|
||||
fileHandle.onerror = errorHandler;
|
||||
|
||||
let lockedFile = fileHandle.open("readwrite");
|
||||
|
||||
request = lockedFile.write(testBuffer);
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
request = fileHandle.getFile();
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let file = event.target.result;
|
||||
|
||||
var worker = new Worker("dummy_worker.js");
|
||||
try {
|
||||
worker.postMessage(file);
|
||||
ok(false, "Should have thrown!");
|
||||
}
|
||||
catch (e) {
|
||||
ok(e instanceof DOMException, "Got exception.");
|
||||
is(e.name, "DataCloneError", "Good error.");
|
||||
is(e.code, DOMException.DATA_CLONE_ERR, "Good error code.")
|
||||
}
|
||||
worker.terminate();
|
||||
}
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
@ -749,7 +749,7 @@ IDBCursor::Advance(PRInt64 aCount)
|
||||
}
|
||||
|
||||
Key key;
|
||||
return ContinueInternal(key, aCount);
|
||||
return ContinueInternal(key, PRInt32(aCount));
|
||||
}
|
||||
|
||||
void
|
||||
@ -876,9 +876,26 @@ ContinueHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
if (!mCloneReadInfo.mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
InfallibleTArray<PBlobParent*> blobsParent;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
IDBDatabase* database = mTransaction->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobsParent);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
}
|
||||
}
|
||||
|
||||
ResponseValue response;
|
||||
@ -890,6 +907,7 @@ ContinueHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
continueResponse.key() = mKey;
|
||||
continueResponse.objectKey() = mObjectKey;
|
||||
continueResponse.cloneInfo() = mCloneReadInfo;
|
||||
continueResponse.blobsParent().SwapElements(blobsParent);
|
||||
response = continueResponse;
|
||||
}
|
||||
|
||||
@ -925,6 +943,8 @@ ContinueHelper::UnpackResponseFromParentProcess(
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
IDBObjectStore::ConvertActorsToBlobs(response.blobsChild(),
|
||||
mCloneReadInfo.mFiles);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMLists.h"
|
||||
#include "nsJSUtils.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "ipc/IndexedDBChild.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::ContentParent;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -170,7 +172,8 @@ already_AddRefed<IDBDatabase>
|
||||
IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
|
||||
already_AddRefed<DatabaseInfo> aDatabaseInfo,
|
||||
const nsACString& aASCIIOrigin,
|
||||
FileManager* aFileManager)
|
||||
FileManager* aFileManager,
|
||||
mozilla::dom::ContentParent* aContentParent)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
|
||||
@ -191,6 +194,7 @@ IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
|
||||
databaseInfo.swap(db->mDatabaseInfo);
|
||||
db->mASCIIOrigin = aASCIIOrigin;
|
||||
db->mFileManager = aFileManager;
|
||||
db->mContentParent = aContentParent;
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
@ -207,6 +211,7 @@ IDBDatabase::IDBDatabase()
|
||||
: mDatabaseId(0),
|
||||
mActorChild(nullptr),
|
||||
mActorParent(nullptr),
|
||||
mContentParent(nullptr),
|
||||
mInvalidated(0),
|
||||
mRegistered(false),
|
||||
mClosed(false),
|
||||
|
@ -19,6 +19,12 @@
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
@ -50,7 +56,8 @@ public:
|
||||
Create(IDBWrapperCache* aOwnerCache,
|
||||
already_AddRefed<DatabaseInfo> aDatabaseInfo,
|
||||
const nsACString& aASCIIOrigin,
|
||||
FileManager* aFileManager);
|
||||
FileManager* aFileManager,
|
||||
mozilla::dom::ContentParent* aContentParent);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
@ -135,6 +142,12 @@ public:
|
||||
return mActorChild;
|
||||
}
|
||||
|
||||
mozilla::dom::ContentParent*
|
||||
GetContentParent() const
|
||||
{
|
||||
return mContentParent;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CreateObjectStoreInternal(IDBTransaction* aTransaction,
|
||||
const ObjectStoreInfoGuts& aInfo,
|
||||
@ -165,6 +178,8 @@ private:
|
||||
IndexedDBDatabaseChild* mActorChild;
|
||||
IndexedDBDatabaseParent* mActorParent;
|
||||
|
||||
mozilla::dom::ContentParent* mContentParent;
|
||||
|
||||
PRInt32 mInvalidated;
|
||||
bool mRegistered;
|
||||
bool mClosed;
|
||||
|
@ -119,8 +119,8 @@ IDBVersionChangeEvent::GetNewVersion(JSContext* aCx,
|
||||
if (!mNewVersion) {
|
||||
*aNewVersion = JSVAL_NULL;
|
||||
}
|
||||
else if (!JS_NewNumberValue(aCx, double(mNewVersion), aNewVersion)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
else {
|
||||
*aNewVersion = JS_NumberValue(double(mNewVersion));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "IDBFactory.h"
|
||||
|
||||
#include "nsIFile.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIPrincipal.h"
|
||||
@ -16,6 +15,7 @@
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#include "jsdbgapi.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
@ -46,6 +46,7 @@
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
using mozilla::dom::ContentChild;
|
||||
using mozilla::dom::ContentParent;
|
||||
using mozilla::dom::TabChild;
|
||||
|
||||
namespace {
|
||||
@ -63,7 +64,7 @@ struct ObjectStoreInfoMap
|
||||
|
||||
IDBFactory::IDBFactory()
|
||||
: mOwningObject(nullptr), mActorChild(nullptr), mActorParent(nullptr),
|
||||
mRootedOwningObject(false)
|
||||
mContentParent(nullptr), mRootedOwningObject(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -84,6 +85,7 @@ IDBFactory::~IDBFactory()
|
||||
nsresult
|
||||
IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aASCIIOrigin,
|
||||
ContentParent* aContentParent,
|
||||
IDBFactory** aFactory)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -118,6 +120,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||
factory->mASCIIOrigin = origin;
|
||||
factory->mWindow = aWindow;
|
||||
factory->mContentParent = aContentParent;
|
||||
|
||||
if (!IndexedDatabaseManager::IsMainProcess()) {
|
||||
TabChild* tabChild = GetTabChildFrom(aWindow);
|
||||
@ -145,6 +148,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||
nsresult
|
||||
IDBFactory::Create(JSContext* aCx,
|
||||
JSObject* aOwningObject,
|
||||
ContentParent* aContentParent,
|
||||
IDBFactory** aFactory)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -162,6 +166,7 @@ IDBFactory::Create(JSContext* aCx,
|
||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||
factory->mASCIIOrigin = origin;
|
||||
factory->mOwningObject = aOwningObject;
|
||||
factory->mContentParent = aContentParent;
|
||||
|
||||
if (!IndexedDatabaseManager::IsMainProcess()) {
|
||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
||||
@ -180,11 +185,13 @@ IDBFactory::Create(JSContext* aCx,
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::Create(IDBFactory** aFactory)
|
||||
IDBFactory::Create(ContentParent* aContentParent,
|
||||
IDBFactory** aFactory)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
|
||||
NS_ASSERTION(aContentParent, "Null ContentParent!");
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
@ -243,7 +250,7 @@ IDBFactory::Create(IDBFactory** aFactory)
|
||||
}
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
rv = Create(cx, global, getter_AddRefs(factory));
|
||||
rv = Create(cx, global, aContentParent, getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_HOLD_JS_OBJECTS(factory, IDBFactory);
|
||||
@ -529,10 +536,10 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (IndexedDatabaseManager::IsMainProcess()) {
|
||||
if (IndexedDatabaseManager::IsMainProcess()) {
|
||||
nsRefPtr<OpenDatabaseHelper> openHelper =
|
||||
new OpenDatabaseHelper(request, aName, mASCIIOrigin, aVersion, aDeleting,
|
||||
privilege);
|
||||
mContentParent, privilege);
|
||||
|
||||
rv = openHelper->Init();
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
@ -628,4 +635,4 @@ IDBFactory::Cmp(const jsval& aFirst,
|
||||
|
||||
*_retval = Key::CompareKeys(first, second);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
@ -17,6 +17,12 @@
|
||||
class nsIAtom;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
struct DatabaseInfo;
|
||||
@ -29,6 +35,7 @@ struct ObjectStoreInfo;
|
||||
|
||||
class IDBFactory MOZ_FINAL : public nsIIDBFactory
|
||||
{
|
||||
typedef mozilla::dom::ContentParent ContentParent;
|
||||
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||
|
||||
public:
|
||||
@ -39,14 +46,17 @@ public:
|
||||
// Called when using IndexedDB from a window in a different process.
|
||||
static nsresult Create(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aASCIIOrigin,
|
||||
ContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
// Called when using IndexedDB from a window in the current process.
|
||||
static nsresult Create(nsPIDOMWindow* aWindow,
|
||||
ContentParent* aContentParent,
|
||||
nsIIDBFactory** aFactory)
|
||||
{
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv = Create(aWindow, EmptyCString(), getter_AddRefs(factory));
|
||||
nsresult rv =
|
||||
Create(aWindow, EmptyCString(), aContentParent, getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
factory.forget(aFactory);
|
||||
@ -57,11 +67,13 @@ public:
|
||||
// process.
|
||||
static nsresult Create(JSContext* aCx,
|
||||
JSObject* aOwningObject,
|
||||
ContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
// Called when using IndexedDB from a JS component or a JSM in a different
|
||||
// process.
|
||||
static nsresult Create(IDBFactory** aFactory);
|
||||
static nsresult Create(ContentParent* aContentParent,
|
||||
IDBFactory** aFactory);
|
||||
|
||||
static already_AddRefed<mozIStorageConnection>
|
||||
GetConnection(const nsAString& aDatabaseFilePath);
|
||||
@ -118,6 +130,8 @@ private:
|
||||
IndexedDBChild* mActorChild;
|
||||
IndexedDBParent* mActorParent;
|
||||
|
||||
mozilla::dom::ContentParent* mContentParent;
|
||||
|
||||
bool mRootedOwningObject;
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "nsIIDBKeyRange.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
@ -32,6 +35,7 @@
|
||||
#include "IndexedDatabaseInlines.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::indexedDB::ipc;
|
||||
|
||||
namespace {
|
||||
@ -634,6 +638,7 @@ IDBIndex::OpenCursorFromChildProcess(
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -651,6 +656,8 @@ IDBIndex::OpenCursorFromChildProcess(
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
cloneInfo.mFiles.SwapElements(aBlobs);
|
||||
|
||||
nsRefPtr<IDBCursor> cursor =
|
||||
IDBCursor::Create(aRequest, mObjectStore->Transaction(), this, direction,
|
||||
Key(), EmptyCString(), EmptyCString(), aKey, aObjectKey,
|
||||
@ -1236,9 +1243,26 @@ GetHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
if (!mCloneReadInfo.mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
InfallibleTArray<PBlobParent*> blobsParent;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobsParent);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobActors failed!");
|
||||
}
|
||||
}
|
||||
|
||||
ResponseValue response;
|
||||
@ -1246,9 +1270,9 @@ GetHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
response = aResultCode;
|
||||
}
|
||||
else {
|
||||
SerializedStructuredCloneReadInfo readInfo;
|
||||
readInfo = mCloneReadInfo;
|
||||
GetResponse getResponse = readInfo;
|
||||
GetResponse getResponse;
|
||||
getResponse.cloneInfo() = mCloneReadInfo;
|
||||
getResponse.blobsParent().SwapElements(blobsParent);
|
||||
response = getResponse;
|
||||
}
|
||||
|
||||
@ -1265,8 +1289,8 @@ GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
|
||||
NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetResponse,
|
||||
"Bad response type!");
|
||||
|
||||
const SerializedStructuredCloneReadInfo& cloneInfo =
|
||||
aResponseValue.get_GetResponse().cloneInfo();
|
||||
const GetResponse& getResponse = aResponseValue.get_GetResponse();
|
||||
const SerializedStructuredCloneReadInfo& cloneInfo = getResponse.cloneInfo();
|
||||
|
||||
NS_ASSERTION((!cloneInfo.dataLength && !cloneInfo.data) ||
|
||||
(cloneInfo.dataLength && cloneInfo.data),
|
||||
@ -1277,6 +1301,8 @@ GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
IDBObjectStore::ConvertActorsToBlobs(getResponse.blobsChild(),
|
||||
mCloneReadInfo.mFiles);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1567,10 +1593,50 @@ GetAllHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
|
||||
if (!mCloneReadInfos[index].mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
GetAllResponse getAllResponse;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
|
||||
IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
PRUint32 length = mCloneReadInfos.Length();
|
||||
|
||||
InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
|
||||
getAllResponse.cloneInfos();
|
||||
infos.SetCapacity(length);
|
||||
|
||||
InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
|
||||
blobArrays.SetCapacity(length);
|
||||
|
||||
for (PRUint32 index = 0;
|
||||
NS_SUCCEEDED(aResultCode) && index < length;
|
||||
index++) {
|
||||
const StructuredCloneReadInfo& clone = mCloneReadInfos[index];
|
||||
|
||||
// Append the structured clone data.
|
||||
SerializedStructuredCloneReadInfo* info = infos.AppendElement();
|
||||
*info = clone;
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = clone.mFiles;
|
||||
|
||||
// Now take care of the files.
|
||||
BlobArray* blobArray = blobArrays.AppendElement();
|
||||
|
||||
InfallibleTArray<PBlobParent*>& blobs = blobArray->blobsParent();
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobs);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1579,18 +1645,6 @@ GetAllHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
response = aResultCode;
|
||||
}
|
||||
else {
|
||||
GetAllResponse getAllResponse;
|
||||
|
||||
InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
|
||||
getAllResponse.cloneInfos();
|
||||
|
||||
infos.SetCapacity(mCloneReadInfos.Length());
|
||||
|
||||
for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
|
||||
SerializedStructuredCloneReadInfo* info = infos.AppendElement();
|
||||
*info = mCloneReadInfos[index];
|
||||
}
|
||||
|
||||
response = getAllResponse;
|
||||
}
|
||||
|
||||
@ -1608,19 +1662,24 @@ GetAllHelper::UnpackResponseFromParentProcess(
|
||||
NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetAllResponse,
|
||||
"Bad response type!");
|
||||
|
||||
const GetAllResponse& getAllResponse = aResponseValue.get_GetAllResponse();
|
||||
const InfallibleTArray<SerializedStructuredCloneReadInfo>& cloneInfos =
|
||||
aResponseValue.get_GetAllResponse().cloneInfos();
|
||||
getAllResponse.cloneInfos();
|
||||
const InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
|
||||
|
||||
mCloneReadInfos.SetCapacity(cloneInfos.Length());
|
||||
|
||||
for (PRUint32 index = 0; index < cloneInfos.Length(); index++) {
|
||||
const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index];
|
||||
const InfallibleTArray<PBlobChild*> blobs = blobArrays[index].blobsChild();
|
||||
|
||||
StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement();
|
||||
if (!destInfo->SetFromSerialized(srcInfo)) {
|
||||
NS_WARNING("Failed to copy clone buffer!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
IDBObjectStore::ConvertActorsToBlobs(blobs, destInfo->mFiles);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2199,13 +2258,30 @@ OpenCursorHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
if (!mCloneReadInfo.mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
|
||||
|
||||
InfallibleTArray<PBlobParent*> blobsParent;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobsParent);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
nsresult rv = EnsureCursor();
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -2241,6 +2317,7 @@ OpenCursorHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
params.key() = mKey;
|
||||
params.objectKey() = mObjectKey;
|
||||
params.optionalCloneInfo() = mSerializedCloneReadInfo;
|
||||
params.blobsParent().SwapElements(blobsParent);
|
||||
|
||||
IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(mCursor);
|
||||
|
||||
@ -2324,11 +2401,7 @@ nsresult
|
||||
CountHelper::GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal)
|
||||
{
|
||||
if (!JS_NewNumberValue(aCx, static_cast<double>(mCount), aVal)) {
|
||||
NS_WARNING("Failed to make number value!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
*aVal = JS_NumberValue(static_cast<double>(mCount));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,7 @@ public:
|
||||
const Key& aKey,
|
||||
const Key& aObjectKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval);
|
||||
|
||||
private:
|
||||
|
@ -12,7 +12,10 @@
|
||||
#include "nsIOutputStream.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
@ -45,6 +48,7 @@
|
||||
#define FILE_COPY_BUFFER_SIZE 32768
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::indexedDB::ipc;
|
||||
|
||||
namespace {
|
||||
@ -881,7 +885,8 @@ IDBObjectStore::GetStructuredCloneReadInfoFromStatement(
|
||||
nsRefPtr<FileInfo> fileInfo = fileManager->GetFileInfo(id);
|
||||
NS_ASSERTION(fileInfo, "Null file info!");
|
||||
|
||||
aInfo.mFileInfos.AppendElement(fileInfo);
|
||||
StructuredCloneFile* file = aInfo.mFiles.AppendElement();
|
||||
file->mFileInfo.swap(fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -954,9 +959,9 @@ static inline PRUint32
|
||||
SwapBytes(PRUint32 u)
|
||||
{
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
return ((u & 0x000000ffU) << 24) |
|
||||
((u & 0x0000ff00U) << 8) |
|
||||
((u & 0x00ff0000U) >> 8) |
|
||||
return ((u & 0x000000ffU) << 24) |
|
||||
((u & 0x0000ff00U) << 8) |
|
||||
((u & 0x00ff0000U) >> 8) |
|
||||
((u & 0xff000000U) >> 24);
|
||||
#else
|
||||
return u;
|
||||
@ -1005,6 +1010,7 @@ StructuredCloneReadString(JSStructuredCloneReader* aReader,
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
JSObject*
|
||||
IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
@ -1017,12 +1023,15 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
StructuredCloneReadInfo* cloneReadInfo =
|
||||
reinterpret_cast<StructuredCloneReadInfo*>(aClosure);
|
||||
|
||||
if (aData >= cloneReadInfo->mFileInfos.Length()) {
|
||||
if (aData >= cloneReadInfo->mFiles.Length()) {
|
||||
NS_ERROR("Bad blob index!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<FileInfo> fileInfo = cloneReadInfo->mFileInfos[aData];
|
||||
nsresult rv;
|
||||
|
||||
StructuredCloneFile& file = cloneReadInfo->mFiles[aData];
|
||||
nsRefPtr<FileInfo>& fileInfo = file.mFileInfo;
|
||||
IDBDatabase* database = cloneReadInfo->mDatabase;
|
||||
|
||||
if (aTag == SCTAG_DOM_FILEHANDLE) {
|
||||
@ -1042,7 +1051,7 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
convName, convType, fileInfo.forget());
|
||||
|
||||
jsval wrappedFileHandle;
|
||||
nsresult rv =
|
||||
rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx),
|
||||
static_cast<nsIDOMFileHandle*>(fileHandle),
|
||||
&NS_GET_IID(nsIDOMFileHandle),
|
||||
@ -1055,21 +1064,6 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
return JSVAL_TO_OBJECT(wrappedFileHandle);
|
||||
}
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
if (!directory) {
|
||||
NS_WARNING("Failed to get directory!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> nativeFile =
|
||||
fileManager->GetFileForId(directory, fileInfo->Id());
|
||||
if (!nativeFile) {
|
||||
NS_WARNING("Failed to get file!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PRUint64 size;
|
||||
if (!JS_ReadBytes(aReader, &size, sizeof(PRUint64))) {
|
||||
NS_WARNING("Failed to read size!");
|
||||
@ -1083,13 +1077,36 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 convType(type);
|
||||
|
||||
nsCOMPtr<nsIFile> nativeFile;
|
||||
if (!file.mFile) {
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
if (!directory) {
|
||||
NS_WARNING("Failed to get directory!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nativeFile = fileManager->GetFileForId(directory, fileInfo->Id());
|
||||
if (!nativeFile) {
|
||||
NS_WARNING("Failed to get file!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_BLOB) {
|
||||
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(convType, size,
|
||||
nativeFile, fileInfo);
|
||||
nsCOMPtr<nsIDOMBlob> domBlob;
|
||||
if (file.mFile) {
|
||||
domBlob = file.mFile;
|
||||
}
|
||||
else {
|
||||
domBlob = new nsDOMFileFile(convType, size, nativeFile, fileInfo);
|
||||
}
|
||||
|
||||
jsval wrappedBlob;
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), blob,
|
||||
rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), domBlob,
|
||||
&NS_GET_IID(nsIDOMBlob), &wrappedBlob);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to wrap native!");
|
||||
@ -1099,18 +1116,27 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
return JSVAL_TO_OBJECT(wrappedBlob);
|
||||
}
|
||||
|
||||
NS_ASSERTION(aTag == SCTAG_DOM_FILE, "Huh?!");
|
||||
|
||||
nsCString name;
|
||||
if (!StructuredCloneReadString(aReader, name)) {
|
||||
return nullptr;
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 convName(name);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = new nsDOMFileFile(convName, convType, size,
|
||||
nativeFile, fileInfo);
|
||||
nsCOMPtr<nsIDOMFile> domFile;
|
||||
if (file.mFile) {
|
||||
domFile = do_QueryInterface(file.mFile);
|
||||
NS_ASSERTION(domFile, "This should never fail!");
|
||||
}
|
||||
else {
|
||||
domFile = new nsDOMFileFile(convName, convType, size, nativeFile,
|
||||
fileInfo);
|
||||
}
|
||||
|
||||
jsval wrappedFile;
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), file,
|
||||
rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), domFile,
|
||||
&NS_GET_IID(nsIDOMFile), &wrappedFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to wrap native!");
|
||||
@ -1130,6 +1156,7 @@ IDBObjectStore::StructuredCloneReadCallback(JSContext* aCx,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
@ -1160,29 +1187,28 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
|
||||
if (blob) {
|
||||
// Check if it is a blob created from this db or the blob was already
|
||||
// stored in this db
|
||||
|
||||
nsRefPtr<FileInfo> fileInfo = transaction->GetFileInfo(blob);
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
|
||||
if (!fileInfo) {
|
||||
// Check if it is a blob created from this db or the blob was already
|
||||
// stored in this db
|
||||
nsRefPtr<FileInfo> fileInfo = transaction->GetFileInfo(blob);
|
||||
if (!fileInfo && fileManager) {
|
||||
fileInfo = blob->GetFileInfo(fileManager);
|
||||
}
|
||||
|
||||
if (!fileInfo) {
|
||||
fileInfo = fileManager->GetNewFileInfo();
|
||||
if (!fileInfo) {
|
||||
NS_WARNING("Failed to get new file info!");
|
||||
return false;
|
||||
}
|
||||
fileInfo = fileManager->GetNewFileInfo();
|
||||
if (!fileInfo) {
|
||||
NS_WARNING("Failed to get new file info!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_FAILED(blob->GetInternalStream(getter_AddRefs(inputStream)))) {
|
||||
NS_WARNING("Failed to get internal steam!");
|
||||
return false;
|
||||
}
|
||||
if (NS_FAILED(blob->GetInternalStream(getter_AddRefs(inputStream)))) {
|
||||
NS_WARNING("Failed to get internal steam!");
|
||||
return false;
|
||||
}
|
||||
|
||||
transaction->AddFileInfo(blob, fileInfo);
|
||||
transaction->AddFileInfo(blob, fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint64 size;
|
||||
@ -1204,8 +1230,8 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
||||
|
||||
if (!JS_WriteUint32Pair(aWriter, file ? SCTAG_DOM_FILE : SCTAG_DOM_BLOB,
|
||||
cloneWriteInfo->mFiles.Length()) ||
|
||||
!JS_WriteBytes(aWriter, &size, sizeof(PRUint64)) ||
|
||||
!JS_WriteBytes(aWriter, &convTypeLength, sizeof(PRUint32)) ||
|
||||
!JS_WriteBytes(aWriter, &size, sizeof(size)) ||
|
||||
!JS_WriteBytes(aWriter, &convTypeLength, sizeof(convTypeLength)) ||
|
||||
!JS_WriteBytes(aWriter, convType.get(), convType.Length())) {
|
||||
return false;
|
||||
}
|
||||
@ -1219,7 +1245,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
||||
NS_ConvertUTF16toUTF8 convName(name);
|
||||
PRUint32 convNameLength = SwapBytes(convName.Length());
|
||||
|
||||
if (!JS_WriteBytes(aWriter, &convNameLength, sizeof(PRUint32)) ||
|
||||
if (!JS_WriteBytes(aWriter, &convNameLength, sizeof(convNameLength)) ||
|
||||
!JS_WriteBytes(aWriter, convName.get(), convName.Length())) {
|
||||
return false;
|
||||
}
|
||||
@ -1285,6 +1311,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBObjectStore::ConvertFileIdsToArray(const nsAString& aFileIds,
|
||||
nsTArray<PRInt64>& aResult)
|
||||
@ -1307,6 +1334,79 @@ IDBObjectStore::ConvertFileIdsToArray(const nsAString& aFileIds,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
IDBObjectStore::ConvertActorsToBlobs(
|
||||
const InfallibleTArray<PBlobChild*>& aActors,
|
||||
nsTArray<StructuredCloneFile>& aFiles)
|
||||
{
|
||||
NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aFiles.IsEmpty(), "Should be empty!");
|
||||
|
||||
if (!aActors.IsEmpty()) {
|
||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
||||
NS_ASSERTION(contentChild, "This should never be null!");
|
||||
|
||||
PRUint32 length = aActors.Length();
|
||||
aFiles.SetCapacity(length);
|
||||
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
BlobChild* actor = static_cast<BlobChild*>(aActors[index]);
|
||||
|
||||
StructuredCloneFile* file = aFiles.AppendElement();
|
||||
file->mFile = actor->GetBlob();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBObjectStore::ConvertBlobsToActors(
|
||||
ContentParent* aContentParent,
|
||||
FileManager* aFileManager,
|
||||
const nsTArray<StructuredCloneFile>& aFiles,
|
||||
InfallibleTArray<PBlobParent*>& aActors)
|
||||
{
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aContentParent, "Null contentParent!");
|
||||
NS_ASSERTION(aFileManager, "Null file manager!");
|
||||
|
||||
if (!aFiles.IsEmpty()) {
|
||||
nsCOMPtr<nsIFile> directory = aFileManager->GetDirectory();
|
||||
if (!directory) {
|
||||
NS_WARNING("Failed to get directory!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
PRUint32 fileCount = aFiles.Length();
|
||||
aActors.SetCapacity(fileCount);
|
||||
|
||||
for (PRUint32 index = 0; index < fileCount; index++) {
|
||||
const StructuredCloneFile& file = aFiles[index];
|
||||
NS_ASSERTION(file.mFileInfo, "This should never be null!");
|
||||
|
||||
nsCOMPtr<nsIFile> nativeFile =
|
||||
aFileManager->GetFileForId(directory, file.mFileInfo->Id());
|
||||
if (!nativeFile) {
|
||||
NS_WARNING("Failed to get file!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(nativeFile);
|
||||
|
||||
BlobParent* actor =
|
||||
aContentParent->GetOrCreateActorForBlob(blob);
|
||||
NS_ASSERTION(actor, "This should never fail without aborting!");
|
||||
|
||||
aActors.AppendElement(actor);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
IDBObjectStore::IDBObjectStore()
|
||||
: mId(LL_MININT),
|
||||
mKeyPath(0),
|
||||
@ -1448,6 +1548,7 @@ IDBObjectStore::AddOrPutInternal(
|
||||
const SerializedStructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
const Key& aKey,
|
||||
const InfallibleTArray<IndexUpdateInfo>& aUpdateInfoArray,
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
|
||||
bool aOverwrite,
|
||||
IDBRequest** _retval)
|
||||
{
|
||||
@ -1471,6 +1572,48 @@ IDBObjectStore::AddOrPutInternal(
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
if (!aBlobs.IsEmpty()) {
|
||||
FileManager* fileManager = Transaction()->Database()->Manager();
|
||||
NS_ASSERTION(fileManager, "Null file manager?!");
|
||||
|
||||
PRUint32 length = aBlobs.Length();
|
||||
cloneWriteInfo.mFiles.SetCapacity(length);
|
||||
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
const nsCOMPtr<nsIDOMBlob>& blob = aBlobs[index];
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
|
||||
nsRefPtr<FileInfo> fileInfo = Transaction()->GetFileInfo(blob);
|
||||
if (!fileInfo) {
|
||||
fileInfo = blob->GetFileInfo(fileManager);
|
||||
|
||||
if (!fileInfo) {
|
||||
fileInfo = fileManager->GetNewFileInfo();
|
||||
if (!fileInfo) {
|
||||
NS_WARNING("Failed to get new file info!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
if (NS_FAILED(blob->GetInternalStream(getter_AddRefs(inputStream)))) {
|
||||
NS_WARNING("Failed to get internal steam!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
// XXXbent This is where we should send a message back to the child to
|
||||
// update the file id.
|
||||
|
||||
Transaction()->AddFileInfo(blob, fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
StructuredCloneFile* file = cloneWriteInfo.mFiles.AppendElement();
|
||||
file->mFile = blob;
|
||||
file->mFileInfo.swap(fileInfo);
|
||||
file->mInputStream.swap(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
Key key(aKey);
|
||||
|
||||
nsTArray<IndexUpdateInfo> updateInfo(aUpdateInfoArray);
|
||||
@ -1648,6 +1791,7 @@ IDBObjectStore::OpenCursorFromChildProcess(
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -1665,6 +1809,8 @@ IDBObjectStore::OpenCursorFromChildProcess(
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
cloneInfo.mFiles.SwapElements(aBlobs);
|
||||
|
||||
nsRefPtr<IDBCursor> cursor =
|
||||
IDBCursor::Create(aRequest, mTransaction, this, direction, Key(),
|
||||
EmptyCString(), EmptyCString(), aKey, cloneInfo);
|
||||
@ -2546,6 +2692,31 @@ AddHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
|
||||
commonParams.key() = mKey;
|
||||
commonParams.indexUpdateInfos().AppendElements(mIndexUpdateInfo);
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneWriteInfo.mFiles;
|
||||
|
||||
if (!files.IsEmpty()) {
|
||||
PRUint32 fileCount = files.Length();
|
||||
|
||||
InfallibleTArray<PBlobChild*>& blobsChild = commonParams.blobsChild();
|
||||
blobsChild.SetCapacity(fileCount);
|
||||
|
||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
||||
NS_ASSERTION(contentChild, "This should never be null!");
|
||||
|
||||
for (PRUint32 index = 0; index < fileCount; index++) {
|
||||
const StructuredCloneFile& file = files[index];
|
||||
|
||||
NS_ASSERTION(file.mFile, "This should never be null!");
|
||||
NS_ASSERTION(!file.mFileInfo, "This is not yet supported!");
|
||||
|
||||
BlobChild* actor =
|
||||
contentChild->GetOrCreateActorForBlob(file.mFile);
|
||||
NS_ASSERTION(actor, "This should never fail without aborting!");
|
||||
|
||||
blobsChild.AppendElement(actor);
|
||||
}
|
||||
}
|
||||
|
||||
if (mOverwrite) {
|
||||
PutParams putParams;
|
||||
putParams.commonParams() = commonParams;
|
||||
@ -2690,9 +2861,26 @@ GetHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
if (!mCloneReadInfo.mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
InfallibleTArray<PBlobParent*> blobsParent;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
IDBDatabase* database = mObjectStore->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobsParent);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
}
|
||||
}
|
||||
|
||||
ResponseValue response;
|
||||
@ -2700,9 +2888,9 @@ GetHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
response = aResultCode;
|
||||
}
|
||||
else {
|
||||
SerializedStructuredCloneReadInfo readInfo;
|
||||
readInfo = mCloneReadInfo;
|
||||
GetResponse getResponse = readInfo;
|
||||
GetResponse getResponse;
|
||||
getResponse.cloneInfo() = mCloneReadInfo;
|
||||
getResponse.blobsParent().SwapElements(blobsParent);
|
||||
response = getResponse;
|
||||
}
|
||||
|
||||
@ -2719,8 +2907,8 @@ GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
|
||||
NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetResponse,
|
||||
"Bad response type!");
|
||||
|
||||
const SerializedStructuredCloneReadInfo& cloneInfo =
|
||||
aResponseValue.get_GetResponse().cloneInfo();
|
||||
const GetResponse& getResponse = aResponseValue.get_GetResponse();
|
||||
const SerializedStructuredCloneReadInfo& cloneInfo = getResponse.cloneInfo();
|
||||
|
||||
NS_ASSERTION((!cloneInfo.dataLength && !cloneInfo.data) ||
|
||||
(cloneInfo.dataLength && cloneInfo.data),
|
||||
@ -2731,6 +2919,8 @@ GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
IDBObjectStore::ConvertActorsToBlobs(getResponse.blobsChild(),
|
||||
mCloneReadInfo.mFiles);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3099,13 +3289,30 @@ OpenCursorHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
if (!mCloneReadInfo.mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
|
||||
|
||||
InfallibleTArray<PBlobParent*> blobsParent;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
IDBDatabase* database = mObjectStore->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobsParent);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode)) {
|
||||
nsresult rv = EnsureCursor();
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -3141,6 +3348,7 @@ OpenCursorHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
params.direction() = mDirection;
|
||||
params.key() = mKey;
|
||||
params.cloneInfo() = mSerializedCloneReadInfo;
|
||||
params.blobsParent().SwapElements(blobsParent);
|
||||
|
||||
IndexedDBCursorParent* cursorActor = new IndexedDBCursorParent(mCursor);
|
||||
|
||||
@ -3525,10 +3733,47 @@ GetAllHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
return Success_NotSent;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
|
||||
if (!mCloneReadInfos[index].mFileInfos.IsEmpty()) {
|
||||
NS_WARNING("No support for transferring blobs across processes yet!");
|
||||
return Error;
|
||||
GetAllResponse getAllResponse;
|
||||
|
||||
if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
|
||||
IDBDatabase* database = mObjectStore->Transaction()->Database();
|
||||
NS_ASSERTION(database, "This should never be null!");
|
||||
|
||||
ContentParent* contentParent = database->GetContentParent();
|
||||
NS_ASSERTION(contentParent, "This should never be null!");
|
||||
|
||||
FileManager* fileManager = database->Manager();
|
||||
NS_ASSERTION(fileManager, "This should never be null!");
|
||||
|
||||
PRUint32 length = mCloneReadInfos.Length();
|
||||
|
||||
InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
|
||||
getAllResponse.cloneInfos();
|
||||
infos.SetCapacity(length);
|
||||
|
||||
InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
|
||||
blobArrays.SetCapacity(length);
|
||||
|
||||
for (PRUint32 index = 0;
|
||||
NS_SUCCEEDED(aResultCode) && index < length;
|
||||
index++) {
|
||||
// Append the structured clone data.
|
||||
const StructuredCloneReadInfo& clone = mCloneReadInfos[index];
|
||||
SerializedStructuredCloneReadInfo* info = infos.AppendElement();
|
||||
*info = clone;
|
||||
|
||||
// Now take care of the files.
|
||||
const nsTArray<StructuredCloneFile>& files = clone.mFiles;
|
||||
BlobArray* blobArray = blobArrays.AppendElement();
|
||||
InfallibleTArray<PBlobParent*>& blobs = blobArray->blobsParent();
|
||||
|
||||
aResultCode =
|
||||
IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
|
||||
blobs);
|
||||
if (NS_FAILED(aResultCode)) {
|
||||
NS_WARNING("ConvertBlobsToActors failed!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3537,19 +3782,6 @@ GetAllHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
|
||||
response = aResultCode;
|
||||
}
|
||||
else {
|
||||
GetAllResponse getAllResponse;
|
||||
|
||||
InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
|
||||
getAllResponse.cloneInfos();
|
||||
|
||||
infos.SetCapacity(mCloneReadInfos.Length());
|
||||
|
||||
for (PRUint32 index = 0; index < mCloneReadInfos.Length(); index++) {
|
||||
SerializedStructuredCloneReadInfo* info = infos.AppendElement();
|
||||
*info = mCloneReadInfos[index];
|
||||
}
|
||||
|
||||
getAllResponse = infos;
|
||||
response = getAllResponse;
|
||||
}
|
||||
|
||||
@ -3567,19 +3799,24 @@ GetAllHelper::UnpackResponseFromParentProcess(
|
||||
NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetAllResponse,
|
||||
"Bad response type!");
|
||||
|
||||
const GetAllResponse& getAllResponse = aResponseValue.get_GetAllResponse();
|
||||
const InfallibleTArray<SerializedStructuredCloneReadInfo>& cloneInfos =
|
||||
aResponseValue.get_GetAllResponse().cloneInfos();
|
||||
getAllResponse.cloneInfos();
|
||||
const InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
|
||||
|
||||
mCloneReadInfos.SetCapacity(cloneInfos.Length());
|
||||
|
||||
for (PRUint32 index = 0; index < cloneInfos.Length(); index++) {
|
||||
const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index];
|
||||
const InfallibleTArray<PBlobChild*> blobs = blobArrays[index].blobsChild();
|
||||
|
||||
StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement();
|
||||
if (!destInfo->SetFromSerialized(srcInfo)) {
|
||||
NS_WARNING("Failed to copy clone buffer!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
IDBObjectStore::ConvertActorsToBlobs(blobs, destInfo->mFiles);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -3653,11 +3890,7 @@ nsresult
|
||||
CountHelper::GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal)
|
||||
{
|
||||
if (!JS_NewNumberValue(aCx, static_cast<double>(mCount), aVal)) {
|
||||
NS_WARNING("Failed to make number value!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
*aVal = JS_NumberValue(static_cast<double>(mCount));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,22 @@
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "mozilla/dom/indexedDB/KeyPath.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
class PBlobChild;
|
||||
class PBlobParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class FileManager;
|
||||
class IDBCursor;
|
||||
class IDBKeyRange;
|
||||
class IDBRequest;
|
||||
@ -33,8 +43,6 @@ class Key;
|
||||
struct IndexInfo;
|
||||
struct IndexUpdateInfo;
|
||||
struct ObjectStoreInfo;
|
||||
struct StructuredCloneReadInfo;
|
||||
struct StructuredCloneWriteInfo;
|
||||
|
||||
class IDBObjectStore MOZ_FINAL : public nsIIDBObjectStore
|
||||
{
|
||||
@ -103,6 +111,18 @@ public:
|
||||
ConvertFileIdsToArray(const nsAString& aFileIds,
|
||||
nsTArray<PRInt64>& aResult);
|
||||
|
||||
// Called only in the main process.
|
||||
static nsresult
|
||||
ConvertBlobsToActors(ContentParent* aContentParent,
|
||||
FileManager* aFileManager,
|
||||
const nsTArray<StructuredCloneFile>& aFiles,
|
||||
InfallibleTArray<PBlobParent*>& aActors);
|
||||
|
||||
// Called only in the child process.
|
||||
static void
|
||||
ConvertActorsToBlobs(const InfallibleTArray<PBlobChild*>& aActors,
|
||||
nsTArray<StructuredCloneFile>& aFiles);
|
||||
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
@ -183,6 +203,7 @@ public:
|
||||
const SerializedStructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
const Key& aKey,
|
||||
const InfallibleTArray<IndexUpdateInfo>& aUpdateInfoArray,
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
|
||||
bool aOverwrite,
|
||||
IDBRequest** _retval);
|
||||
|
||||
@ -216,6 +237,7 @@ public:
|
||||
size_t aDirection,
|
||||
const Key& aKey,
|
||||
const SerializedStructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<StructuredCloneFile>& aBlobs,
|
||||
IDBCursor** _retval);
|
||||
|
||||
void
|
||||
|
@ -49,6 +49,20 @@ void SwapData(T& aData1, T& aData2)
|
||||
aData1 = temp;
|
||||
}
|
||||
|
||||
struct StructuredCloneFile
|
||||
{
|
||||
bool operator==(const StructuredCloneFile& aOther) const
|
||||
{
|
||||
return this->mFile == aOther.mFile &&
|
||||
this->mFileInfo == aOther.mFileInfo &&
|
||||
this->mInputStream == aOther.mInputStream;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> mFile;
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneReadInfo;
|
||||
|
||||
struct StructuredCloneReadInfo
|
||||
@ -59,7 +73,7 @@ struct StructuredCloneReadInfo
|
||||
void Swap(StructuredCloneReadInfo& aCloneReadInfo)
|
||||
{
|
||||
mCloneBuffer.swap(aCloneReadInfo.mCloneBuffer);
|
||||
mFileInfos.SwapElements(aCloneReadInfo.mFileInfos);
|
||||
mFiles.SwapElements(aCloneReadInfo.mFiles);
|
||||
SwapData(mDatabase, aCloneReadInfo.mDatabase);
|
||||
}
|
||||
|
||||
@ -68,7 +82,7 @@ struct StructuredCloneReadInfo
|
||||
SetFromSerialized(const SerializedStructuredCloneReadInfo& aOther);
|
||||
|
||||
JSAutoStructuredCloneBuffer mCloneBuffer;
|
||||
nsTArray<nsRefPtr<FileInfo> > mFileInfos;
|
||||
nsTArray<StructuredCloneFile> mFiles;
|
||||
IDBDatabase* mDatabase;
|
||||
};
|
||||
|
||||
@ -98,20 +112,6 @@ struct SerializedStructuredCloneReadInfo
|
||||
size_t dataLength;
|
||||
};
|
||||
|
||||
struct StructuredCloneFile
|
||||
{
|
||||
bool operator==(const StructuredCloneFile& aOther) const
|
||||
{
|
||||
return this->mFile == aOther.mFile &&
|
||||
this->mFileInfo == aOther.mFileInfo &&
|
||||
this->mInputStream == aOther.mInputStream;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> mFile;
|
||||
nsRefPtr<FileInfo> mFileInfo;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
};
|
||||
|
||||
struct SerializedStructuredCloneWriteInfo;
|
||||
|
||||
struct StructuredCloneWriteInfo
|
||||
|
@ -50,7 +50,7 @@ StructuredCloneReadInfo::SetFromSerialized(
|
||||
return false;
|
||||
}
|
||||
|
||||
mFileInfos.Clear();
|
||||
mFiles.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -217,9 +217,11 @@ IndexedDatabaseManager::GetOrCreate()
|
||||
|
||||
if (sIsMainProcess) {
|
||||
nsCOMPtr<nsIFile> dbBaseDirectory;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_INDEXEDDB_PARENT_DIR, getter_AddRefs(dbBaseDirectory));
|
||||
rv = NS_GetSpecialDirectory(NS_APP_INDEXEDDB_PARENT_DIR,
|
||||
getter_AddRefs(dbBaseDirectory));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(dbBaseDirectory));
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(dbBaseDirectory));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
@ -231,9 +233,10 @@ IndexedDatabaseManager::GetOrCreate()
|
||||
|
||||
// Make a lazy thread for any IO we need (like clearing or enumerating the
|
||||
// contents of indexedDB database directories).
|
||||
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
||||
NS_LITERAL_CSTRING("IndexedDB I/O"),
|
||||
LazyIdleThread::ManualShutdown);
|
||||
instance->mIOThread =
|
||||
new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
||||
NS_LITERAL_CSTRING("IndexedDB I/O"),
|
||||
LazyIdleThread::ManualShutdown);
|
||||
|
||||
// We need one quota callback object to hand to SQLite.
|
||||
instance->mQuotaCallbackSingleton = new QuotaCallback();
|
||||
@ -1910,7 +1913,8 @@ IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
|
||||
JSObject* global = JS_GetGlobalForObject(aCx, obj);
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv = IDBFactory::Create(aCx, global, getter_AddRefs(factory));
|
||||
nsresult rv =
|
||||
IDBFactory::Create(aCx, global, nullptr, getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
NS_ASSERTION(factory, "This should never fail for chrome!");
|
||||
|
@ -2106,10 +2106,8 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||
dbInfo->nextIndexId = mLastIndexId + 1;
|
||||
|
||||
nsRefPtr<IDBDatabase> database =
|
||||
IDBDatabase::Create(mOpenDBRequest,
|
||||
dbInfo.forget(),
|
||||
mASCIIOrigin,
|
||||
mFileManager);
|
||||
IDBDatabase::Create(mOpenDBRequest, dbInfo.forget(), mASCIIOrigin,
|
||||
mFileManager, mContentParent);
|
||||
if (!database) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
class mozIStorageConnection;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class OpenDatabaseHelper : public HelperBase
|
||||
@ -24,12 +30,14 @@ public:
|
||||
const nsACString& aASCIIOrigin,
|
||||
PRUint64 aRequestedVersion,
|
||||
bool aForDeletion,
|
||||
mozilla::dom::ContentParent* aContentParent,
|
||||
FactoryPrivilege aPrivilege)
|
||||
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
|
||||
mASCIIOrigin(aASCIIOrigin), mRequestedVersion(aRequestedVersion),
|
||||
mForDeletion(aForDeletion), mPrivilege(aPrivilege), mDatabaseId(nullptr),
|
||||
mCurrentVersion(0), mLastObjectStoreId(0), mLastIndexId(0),
|
||||
mState(eCreated), mResultCode(NS_OK), mLoadDBMetadata(false)
|
||||
mContentParent(aContentParent), mCurrentVersion(0), mLastObjectStoreId(0),
|
||||
mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
|
||||
mLoadDBMetadata(false)
|
||||
{
|
||||
NS_ASSERTION(!aForDeletion || !aRequestedVersion,
|
||||
"Can't be for deletion and request a version!");
|
||||
@ -103,6 +111,7 @@ protected:
|
||||
bool mForDeletion;
|
||||
FactoryPrivilege mPrivilege;
|
||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||
mozilla::dom::ContentParent* mContentParent;
|
||||
|
||||
// Out-params.
|
||||
nsTArray<nsRefPtr<ObjectStoreInfo> > mObjectStores;
|
||||
@ -133,4 +142,4 @@ protected:
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_opendatabasehelper_h__
|
||||
#endif // mozilla_dom_indexeddb_opendatabasehelper_h__
|
@ -6,10 +6,11 @@
|
||||
|
||||
#include "IndexedDBChild.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include "nsIAtom.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
#include "DatabaseInfo.h"
|
||||
#include "IDBEvents.h"
|
||||
@ -21,6 +22,8 @@
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
class IPCOpenDatabaseHelper : public AsyncConnectionHelper
|
||||
@ -289,7 +292,8 @@ IndexedDBDatabaseChild::EnsureDatabase(
|
||||
|
||||
if (!mDatabase) {
|
||||
nsRefPtr<IDBDatabase> database =
|
||||
IDBDatabase::Create(aRequest, dbInfo.forget(), aDBInfo.origin, NULL);
|
||||
IDBDatabase::Create(aRequest, dbInfo.forget(), aDBInfo.origin, NULL,
|
||||
NULL);
|
||||
if (!database) {
|
||||
NS_WARNING("Failed to create database!");
|
||||
return false;
|
||||
@ -646,13 +650,18 @@ IndexedDBObjectStoreChild::RecvPIndexedDBCursorConstructor(
|
||||
|
||||
size_t direction = static_cast<size_t>(aParams.direction());
|
||||
|
||||
nsTArray<StructuredCloneFile> blobs;
|
||||
IDBObjectStore::ConvertActorsToBlobs(aParams.blobsChild(), blobs);
|
||||
|
||||
nsRefPtr<IDBCursor> cursor;
|
||||
nsresult rv =
|
||||
mObjectStore->OpenCursorFromChildProcess(request, direction, aParams.key(),
|
||||
aParams.cloneInfo(),
|
||||
aParams.cloneInfo(), blobs,
|
||||
getter_AddRefs(cursor));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
MOZ_ASSERT(blobs.IsEmpty(), "Should have swapped blob elements!");
|
||||
|
||||
actor->SetCursor(cursor);
|
||||
return true;
|
||||
}
|
||||
@ -754,16 +763,22 @@ IndexedDBIndexChild::RecvPIndexedDBCursorConstructor(
|
||||
|
||||
switch (aParams.optionalCloneInfo().type()) {
|
||||
case CursorUnionType::TSerializedStructuredCloneReadInfo: {
|
||||
nsTArray<StructuredCloneFile> blobs;
|
||||
IDBObjectStore::ConvertActorsToBlobs(aParams.blobsChild(), blobs);
|
||||
|
||||
const SerializedStructuredCloneReadInfo& cloneInfo =
|
||||
aParams.optionalCloneInfo().get_SerializedStructuredCloneReadInfo();
|
||||
|
||||
rv = mIndex->OpenCursorFromChildProcess(request, direction, aParams.key(),
|
||||
aParams.objectKey(), cloneInfo,
|
||||
blobs,
|
||||
getter_AddRefs(cursor));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
} break;
|
||||
|
||||
case CursorUnionType::Tvoid_t:
|
||||
MOZ_ASSERT(aParams.blobsChild().IsEmpty());
|
||||
|
||||
rv = mIndex->OpenCursorFromChildProcess(request, direction, aParams.key(),
|
||||
aParams.objectKey(),
|
||||
getter_AddRefs(cursor));
|
||||
|
@ -6,12 +6,15 @@
|
||||
|
||||
#include "IndexedDBParent.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIIDBVersionChangeEvent.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
@ -26,6 +29,8 @@
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
/*******************************************************************************
|
||||
* AutoSetCurrentTransaction
|
||||
******************************************************************************/
|
||||
@ -1183,6 +1188,29 @@ IndexedDBObjectStoreRequestParent::~IndexedDBObjectStoreRequestParent()
|
||||
MOZ_COUNT_DTOR(IndexedDBObjectStoreRequestParent);
|
||||
}
|
||||
|
||||
void
|
||||
IndexedDBObjectStoreRequestParent::ConvertBlobActors(
|
||||
const InfallibleTArray<PBlobParent*>& aActors,
|
||||
nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs)
|
||||
{
|
||||
MOZ_ASSERT(aBlobs.IsEmpty());
|
||||
|
||||
if (!aActors.IsEmpty()) {
|
||||
// Walk the chain to get to ContentParent.
|
||||
ContentParent* contentParent =
|
||||
mObjectStore->Transaction()->Database()->GetContentParent();
|
||||
MOZ_ASSERT(contentParent);
|
||||
|
||||
uint32_t length = aActors.Length();
|
||||
aBlobs.SetCapacity(length);
|
||||
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
BlobParent* actor = static_cast<BlobParent*>(aActors[index]);
|
||||
aBlobs.AppendElement(actor->GetBlob());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDBObjectStoreRequestParent::Get(const GetParams& aParams)
|
||||
{
|
||||
@ -1254,6 +1282,9 @@ IndexedDBObjectStoreRequestParent::Add(const AddParams& aParams)
|
||||
|
||||
ipc::AddPutParams params = aParams.commonParams();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMBlob> > blobs;
|
||||
ConvertBlobActors(params.blobsParent(), blobs);
|
||||
|
||||
nsRefPtr<IDBRequest> request;
|
||||
|
||||
{
|
||||
@ -1261,7 +1292,7 @@ IndexedDBObjectStoreRequestParent::Add(const AddParams& aParams)
|
||||
|
||||
nsresult rv =
|
||||
mObjectStore->AddOrPutInternal(params.cloneInfo(), params.key(),
|
||||
params.indexUpdateInfos(), false,
|
||||
params.indexUpdateInfos(), blobs, false,
|
||||
getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
@ -1278,6 +1309,9 @@ IndexedDBObjectStoreRequestParent::Put(const PutParams& aParams)
|
||||
|
||||
ipc::AddPutParams params = aParams.commonParams();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMBlob> > blobs;
|
||||
ConvertBlobActors(params.blobsParent(), blobs);
|
||||
|
||||
nsRefPtr<IDBRequest> request;
|
||||
|
||||
{
|
||||
@ -1285,7 +1319,7 @@ IndexedDBObjectStoreRequestParent::Put(const PutParams& aParams)
|
||||
|
||||
nsresult rv =
|
||||
mObjectStore->AddOrPutInternal(params.cloneInfo(), params.key(),
|
||||
params.indexUpdateInfos(), true,
|
||||
params.indexUpdateInfos(), blobs, true,
|
||||
getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
@ -23,10 +23,12 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
class PBlobParent;
|
||||
class TabParent;
|
||||
}
|
||||
}
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIDOMEvent;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
@ -531,6 +533,11 @@ public:
|
||||
|
||||
bool
|
||||
OpenCursor(const OpenCursorParams& aParams);
|
||||
|
||||
protected:
|
||||
void
|
||||
ConvertBlobActors(const InfallibleTArray<PBlobParent*>& aActors,
|
||||
nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs);
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -48,4 +48,4 @@ copy-xpcshell-tests:
|
||||
$(call install_cmd,$(wildcard $(topsrcdir)/dom/indexedDB/test/unit/test_*.js) \
|
||||
$(testxpcobjdir)/$(relativesrcdir)/$(XPCSHELL_TESTS))
|
||||
|
||||
libs-xpcshell-tests: copy-xpcshell-tests
|
||||
libs-xpcshell-tests: copy-xpcshell-tests
|
@ -2,6 +2,7 @@
|
||||
* 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 PBlob;
|
||||
include protocol PIndexedDBCursor;
|
||||
include protocol PIndexedDBObjectStore;
|
||||
include protocol PIndexedDBRequest;
|
||||
@ -102,6 +103,7 @@ struct IndexCursorConstructorParams
|
||||
Key key;
|
||||
Key objectKey;
|
||||
OptionalStructuredCloneReadInfo optionalCloneInfo;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
@ -2,6 +2,7 @@
|
||||
* 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 PBlob;
|
||||
include protocol PIndexedDBCursor;
|
||||
include protocol PIndexedDBIndex;
|
||||
include protocol PIndexedDBRequest;
|
||||
@ -70,6 +71,7 @@ struct AddPutParams
|
||||
SerializedStructuredCloneWriteInfo cloneInfo;
|
||||
Key key;
|
||||
IndexUpdateInfo[] indexUpdateInfos;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
struct AddParams
|
||||
@ -126,6 +128,7 @@ struct ObjectStoreCursorConstructorParams
|
||||
Direction direction;
|
||||
Key key;
|
||||
SerializedStructuredCloneReadInfo cloneInfo;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
@ -2,6 +2,7 @@
|
||||
* 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 PBlob;
|
||||
include protocol PIndexedDBCursor;
|
||||
include protocol PIndexedDBIndex;
|
||||
include protocol PIndexedDBObjectStore;
|
||||
@ -22,6 +23,7 @@ namespace ipc {
|
||||
struct GetResponse
|
||||
{
|
||||
SerializedStructuredCloneReadInfo cloneInfo;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
struct GetKeyResponse
|
||||
@ -29,9 +31,15 @@ struct GetKeyResponse
|
||||
Key key;
|
||||
};
|
||||
|
||||
struct BlobArray
|
||||
{
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
struct GetAllResponse
|
||||
{
|
||||
SerializedStructuredCloneReadInfo[] cloneInfos;
|
||||
BlobArray[] blobs;
|
||||
};
|
||||
|
||||
struct GetAllKeysResponse
|
||||
@ -75,6 +83,7 @@ struct ContinueResponse
|
||||
Key key;
|
||||
Key objectKey;
|
||||
SerializedStructuredCloneReadInfo cloneInfo;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
union ResponseValue
|
||||
|
@ -29,6 +29,7 @@ MOCHITEST_FILES = \
|
||||
test_autoIncrement_indexes.html \
|
||||
test_autoIncrement.html \
|
||||
test_bfcache.html \
|
||||
test_blob_simple.html \
|
||||
test_clear.html \
|
||||
test_complex_keyPaths.html \
|
||||
test_count.html \
|
||||
|
192
dom/indexedDB/test/test_blob_simple.html
Normal file
192
dom/indexedDB/test/test_blob_simple.html
Normal file
@ -0,0 +1,192 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
const BLOB_DATA = ["fun ", "times ", "all ", "around!"];
|
||||
const INDEX_KEY = 5;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
||||
let index = objectStore.createIndex("foo", "index");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let blob = new Blob(BLOB_DATA, { type: "text/plain" });
|
||||
let data = { blob: blob, index: INDEX_KEY };
|
||||
|
||||
objectStore = db.transaction("foo", "readwrite").objectStore("foo");
|
||||
objectStore.add(data).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let key = event.target.result;
|
||||
|
||||
objectStore.add(data).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
objectStore = db.transaction("foo").objectStore("foo");
|
||||
objectStore.get(key).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(event.target.result.blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
objectStore = db.transaction("foo").objectStore("foo");
|
||||
objectStore.mozGetAll().onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result.length, 2, "Got right number of items");
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(event.target.result[0].blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
let cursorResults = [];
|
||||
|
||||
objectStore = db.transaction("foo").objectStore("foo");
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
cursorResults.push(cursor.value);
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
continueToNextStep();
|
||||
}
|
||||
};
|
||||
yield;
|
||||
|
||||
is(cursorResults.length, 2, "Got right number of items");
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(cursorResults[0].blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
let index = db.transaction("foo").objectStore("foo").index("foo");
|
||||
index.get(INDEX_KEY).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(event.target.result.blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
index = db.transaction("foo").objectStore("foo").index("foo");
|
||||
index.mozGetAll().onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result.length, 2, "Got right number of items");
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(event.target.result[0].blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
cursorResults = [];
|
||||
|
||||
index = db.transaction("foo").objectStore("foo").index("foo");
|
||||
index.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
cursorResults.push(cursor.value);
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
continueToNextStep();
|
||||
}
|
||||
};
|
||||
yield;
|
||||
|
||||
is(cursorResults.length, 2, "Got right number of items");
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(cursorResults[0].blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(cursorResults[1].blob);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA.join(""), "Correct text");
|
||||
|
||||
let slice = cursorResults[1].blob.slice(0, BLOB_DATA[0].length);
|
||||
|
||||
fileReader = new FileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(slice);
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, BLOB_DATA[0], "Correct text");
|
||||
|
||||
function workerScript() {
|
||||
onmessage = function(event) {
|
||||
var reader = new FileReaderSync();
|
||||
postMessage(reader.readAsText(event.data));
|
||||
|
||||
var slice = event.data.slice(1, 2);
|
||||
postMessage(reader.readAsText(slice));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let url =
|
||||
URL.createObjectURL(new Blob(["(", workerScript.toSource(), ")()"]));
|
||||
|
||||
let worker = new Worker(url);
|
||||
worker.postMessage(slice);
|
||||
worker.onmessage = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.data, BLOB_DATA[0], "Correct text");
|
||||
event = yield;
|
||||
|
||||
is(event.data, BLOB_DATA[0][1], "Correct text");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="file.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
@ -32,6 +32,7 @@ XPIDLSRCS = \
|
||||
nsIDOMCSSImportRule.idl \
|
||||
nsIDOMCSSMediaRule.idl \
|
||||
nsIDOMCSSMozDocumentRule.idl \
|
||||
nsIDOMCSSSupportsRule.idl \
|
||||
nsIDOMMozCSSKeyframeRule.idl \
|
||||
nsIDOMMozCSSKeyframesRule.idl \
|
||||
nsIDOMCSSPageRule.idl \
|
||||
|
@ -27,6 +27,7 @@ interface nsIDOMCSSRule : nsISupports
|
||||
const unsigned short MOZ_KEYFRAMES_RULE = 7;
|
||||
const unsigned short MOZ_KEYFRAME_RULE = 8;
|
||||
const unsigned short NAMESPACE_RULE = 10;
|
||||
const unsigned short SUPPORTS_RULE = 12;
|
||||
|
||||
readonly attribute unsigned short type;
|
||||
attribute DOMString cssText;
|
||||
|
21
dom/interfaces/css/nsIDOMCSSSupportsRule.idl
Normal file
21
dom/interfaces/css/nsIDOMCSSSupportsRule.idl
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMCSSRule.idl"
|
||||
|
||||
/**
|
||||
* Interface for @supports rules in the CSS OM.
|
||||
*/
|
||||
[scriptable, uuid(5f409a4d-92f9-4a62-8e8a-cc1c02c32918)]
|
||||
interface nsIDOMCSSSupportsRule : nsIDOMCSSRule
|
||||
{
|
||||
readonly attribute nsIDOMCSSRuleList cssRules;
|
||||
|
||||
unsigned long insertRule(in DOMString rule,
|
||||
in unsigned long index)
|
||||
raises(DOMException);
|
||||
void deleteRule(in unsigned long index)
|
||||
raises(DOMException);
|
||||
};
|
@ -20,7 +20,8 @@ include $(topsrcdir)/dom/dom-config.mk
|
||||
XPIDLSRCS = \
|
||||
nsIDOMDeviceStorage.idl \
|
||||
nsIDOMDeviceStorageCursor.idl \
|
||||
nsIDOMNavigatorDeviceStorage.idl
|
||||
nsIDOMNavigatorDeviceStorage.idl \
|
||||
nsIDOMDeviceStorageChangeEvent.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -3,24 +3,22 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMDeviceStorageCursor;
|
||||
interface nsIDOMDeviceStorageChangeEvent;
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
dictionary DeviceStorageEnumerationParameters
|
||||
{
|
||||
jsval since;
|
||||
};
|
||||
|
||||
[scriptable, uuid(05C0D0C8-D698-4CCD-899C-7198A33BD7EC)]
|
||||
interface nsIDOMDeviceStorage : nsISupports
|
||||
[scriptable, uuid(3dbe0137-ca73-44c5-bcde-25c297bf7c65), builtinclass]
|
||||
interface nsIDOMDeviceStorage : nsIDOMEventTarget
|
||||
{
|
||||
/*
|
||||
* Hint as to what kind of storage this object is.
|
||||
* May be "external", "shared", or "default".
|
||||
*/
|
||||
readonly attribute DOMString type;
|
||||
|
||||
attribute nsIDOMEventListener onchange;
|
||||
nsIDOMDOMRequest add(in nsIDOMBlob aBlob);
|
||||
nsIDOMDOMRequest addNamed(in nsIDOMBlob aBlob, in DOMString aName);
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
/* 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 "domstubs.idl"
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, uuid(468304d6-aab6-4e1e-8ab2-569d9e703431), builtinclass]
|
||||
interface nsIDOMDeviceStorageChangeEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString path;
|
||||
readonly attribute DOMString reason;
|
||||
};
|
||||
|
||||
dictionary DeviceStorageChangeEventInit : EventInit
|
||||
{
|
||||
DOMString path;
|
||||
DOMString reason;
|
||||
};
|
@ -3,15 +3,13 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
interface nsIVariant;
|
||||
interface nsIDOMDeviceStorage;
|
||||
|
||||
/**
|
||||
* Property that extends the navigator object.
|
||||
*/
|
||||
[scriptable, uuid(A4B2831D-6065-472F-8A6D-2C9085C74C15)]
|
||||
[scriptable, uuid(da1fbf6e-259c-40bc-ba8c-4ae81748dca3)]
|
||||
interface nsIDOMNavigatorDeviceStorage : nsISupports
|
||||
{
|
||||
// returns an array of nsIDOMDeviceStorage
|
||||
nsIVariant getDeviceStorage(in DOMString type);
|
||||
nsIDOMDeviceStorage getDeviceStorage(in DOMString type);
|
||||
};
|
||||
|
||||
|
797
dom/ipc/Blob.cpp
Normal file
797
dom/ipc/Blob.cpp
Normal file
@ -0,0 +1,797 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "Blob.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIRemoteBlob.h"
|
||||
#include "nsISeekableStream.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/net/NeckoMessageUtils.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "ContentChild.h"
|
||||
#include "ContentParent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::ipc;
|
||||
|
||||
namespace {
|
||||
|
||||
class RemoteInputStream : public nsIInputStream,
|
||||
public nsISeekableStream
|
||||
{
|
||||
mozilla::Monitor mMonitor;
|
||||
nsCOMPtr<nsIDOMBlob> mSourceBlob;
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
nsCOMPtr<nsISeekableStream> mSeekableStream;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
RemoteInputStream(nsIDOMBlob* aSourceBlob)
|
||||
: mMonitor("RemoteInputStream.mMonitor"), mSourceBlob(aSourceBlob)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aSourceBlob);
|
||||
}
|
||||
|
||||
void
|
||||
SetStream(nsIInputStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aStream);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream = aStream;
|
||||
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
|
||||
|
||||
{
|
||||
mozilla::MonitorAutoLock lock(mMonitor);
|
||||
|
||||
MOZ_ASSERT(!mStream);
|
||||
MOZ_ASSERT(!mSeekableStream);
|
||||
|
||||
mStream.swap(stream);
|
||||
mSeekableStream.swap(seekableStream);
|
||||
|
||||
mMonitor.Notify();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Close() MOZ_OVERRIDE
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> sourceBlob;
|
||||
mSourceBlob.swap(sourceBlob);
|
||||
|
||||
rv = mStream->Close();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Available(PRUint32* aAvailable) MOZ_OVERRIDE
|
||||
{
|
||||
// See large comment in FileInputStreamWrapper::Available.
|
||||
if (NS_IsMainThread()) {
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mStream->Available(aAvailable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Read(char* aBuffer, PRUint32 aCount, PRUint32* aResult) MOZ_OVERRIDE
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mStream->Read(aBuffer, aCount, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, PRUint32 aCount,
|
||||
PRUint32* aResult) MOZ_OVERRIDE
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
IsNonBlocking(bool* aNonBlocking) MOZ_OVERRIDE
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNonBlocking);
|
||||
|
||||
*aNonBlocking = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Seek(PRInt32 aWhence, PRInt64 aOffset) MOZ_OVERRIDE
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mSeekableStream) {
|
||||
NS_WARNING("Underlying blob stream is not seekable!");
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
rv = mSeekableStream->Seek(aWhence, aOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Tell(PRInt64* aResult)
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mSeekableStream) {
|
||||
NS_WARNING("Underlying blob stream is not seekable!");
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
rv = mSeekableStream->Tell(aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
SetEOF()
|
||||
{
|
||||
nsresult rv = BlockAndWaitForStream();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mSeekableStream) {
|
||||
NS_WARNING("Underlying blob stream is not seekable!");
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
rv = mSeekableStream->SetEOF();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~RemoteInputStream()
|
||||
{ }
|
||||
|
||||
void
|
||||
ReallyBlockAndWaitForStream()
|
||||
{
|
||||
mozilla::MonitorAutoLock lock(mMonitor);
|
||||
while (!mStream) {
|
||||
mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
BlockAndWaitForStream()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
NS_WARNING("Blocking the main thread is not supported!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ReallyBlockAndWaitForStream();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
IsSeekableStream()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mStream) {
|
||||
NS_WARNING("Don't know if this stream is seekable yet!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReallyBlockAndWaitForStream();
|
||||
}
|
||||
|
||||
return !!mSeekableStream;
|
||||
}
|
||||
};
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
class InputStreamActor : public BlobTraits<ActorFlavor>::StreamType
|
||||
{
|
||||
typedef typename BlobTraits<ActorFlavor>::StreamType::InputStream InputStream;
|
||||
nsRefPtr<RemoteInputStream> mRemoteStream;
|
||||
|
||||
public:
|
||||
InputStreamActor(RemoteInputStream* aRemoteStream)
|
||||
: mRemoteStream(aRemoteStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRemoteStream);
|
||||
}
|
||||
|
||||
InputStreamActor()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
private:
|
||||
// This method is only called by the IPDL message machinery.
|
||||
virtual bool
|
||||
Recv__delete__(const InputStream& aStream) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mRemoteStream);
|
||||
|
||||
mRemoteStream->SetStream(aStream);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
inline
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
GetBlobFromParams(const SlicedBlobConstructorParams& aParams)
|
||||
{
|
||||
MOZ_STATIC_ASSERT(ActorFlavor == mozilla::dom::ipc::Parent,
|
||||
"No other flavor is supported here!");
|
||||
|
||||
BlobParent* actor =
|
||||
const_cast<BlobParent*>(
|
||||
static_cast<const BlobParent*>(aParams.sourceParent()));
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
return actor->GetBlob();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
GetBlobFromParams<Child>(const SlicedBlobConstructorParams& aParams)
|
||||
{
|
||||
BlobChild* actor =
|
||||
const_cast<BlobChild*>(
|
||||
static_cast<const BlobChild*>(aParams.sourceChild()));
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
return actor->GetBlob();
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
SetBlobOnParams(BlobChild* aActor, SlicedBlobConstructorParams& aParams)
|
||||
{
|
||||
aParams.sourceChild() = aActor;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
SetBlobOnParams(BlobParent* aActor, SlicedBlobConstructorParams& aParams)
|
||||
{
|
||||
aParams.sourceParent() = aActor;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
class RemoteBlob : public nsDOMFile,
|
||||
public nsIRemoteBlob
|
||||
{
|
||||
public:
|
||||
typedef RemoteBlob<ActorFlavor> SelfType;
|
||||
typedef Blob<ActorFlavor> ActorType;
|
||||
typedef InputStreamActor<ActorFlavor> StreamActorType;
|
||||
|
||||
private:
|
||||
ActorType* mActor;
|
||||
|
||||
class StreamHelper : public nsRunnable
|
||||
{
|
||||
typedef Blob<ActorFlavor> ActorType;
|
||||
typedef InputStreamActor<ActorFlavor> StreamActorType;
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
ActorType* mActor;
|
||||
nsCOMPtr<nsIDOMBlob> mSourceBlob;
|
||||
nsRefPtr<RemoteInputStream> mInputStream;
|
||||
bool mDone;
|
||||
|
||||
public:
|
||||
StreamHelper(ActorType* aActor, nsIDOMBlob* aSourceBlob)
|
||||
: mMonitor("RemoteBlob::StreamHelper::mMonitor"), mActor(aActor),
|
||||
mSourceBlob(aSourceBlob), mDone(false)
|
||||
{
|
||||
// This may be created on any thread.
|
||||
MOZ_ASSERT(aActor);
|
||||
MOZ_ASSERT(aSourceBlob);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetStream(nsIInputStream** aInputStream)
|
||||
{
|
||||
// This may be called on any thread.
|
||||
MOZ_ASSERT(aInputStream);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mInputStream);
|
||||
MOZ_ASSERT(!mDone);
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
RunInternal(false);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (!mDone) {
|
||||
lock.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mActor);
|
||||
MOZ_ASSERT(mDone);
|
||||
|
||||
if (!mInputStream) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mInputStream.forget(aInputStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RunInternal(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
RunInternal(bool aNotify)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mInputStream);
|
||||
MOZ_ASSERT(!mDone);
|
||||
|
||||
nsRefPtr<RemoteInputStream> stream = new RemoteInputStream(mSourceBlob);
|
||||
|
||||
StreamActorType* streamActor = new StreamActorType(stream);
|
||||
if (mActor->SendPBlobStreamConstructor(streamActor)) {
|
||||
stream.swap(mInputStream);
|
||||
}
|
||||
|
||||
mActor = nullptr;
|
||||
|
||||
if (aNotify) {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mDone = true;
|
||||
lock.Notify();
|
||||
}
|
||||
else {
|
||||
mDone = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SliceHelper : public nsRunnable
|
||||
{
|
||||
typedef Blob<ActorFlavor> ActorType;
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
ActorType* mActor;
|
||||
nsCOMPtr<nsIDOMBlob> mSlice;
|
||||
PRUint64 mStart;
|
||||
PRUint64 mLength;
|
||||
nsString mContentType;
|
||||
bool mDone;
|
||||
|
||||
public:
|
||||
SliceHelper(ActorType* aActor)
|
||||
: mMonitor("RemoteBlob::SliceHelper::mMonitor"), mActor(aActor), mStart(0),
|
||||
mLength(0), mDone(false)
|
||||
{
|
||||
// This may be created on any thread.
|
||||
MOZ_ASSERT(aActor);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetSlice(PRUint64 aStart, PRUint64 aLength, const nsAString& aContentType,
|
||||
nsIDOMBlob** aSlice)
|
||||
{
|
||||
// This may be called on any thread.
|
||||
MOZ_ASSERT(aSlice);
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mSlice);
|
||||
MOZ_ASSERT(!mDone);
|
||||
|
||||
mStart = aStart;
|
||||
mLength = aLength;
|
||||
mContentType = aContentType;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
RunInternal(false);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
NS_ENSURE_TRUE(mainThread, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = mainThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (!mDone) {
|
||||
lock.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mActor);
|
||||
MOZ_ASSERT(mDone);
|
||||
|
||||
if (!mSlice) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mSlice.forget(aSlice);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RunInternal(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
RunInternal(bool aNotify)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mSlice);
|
||||
MOZ_ASSERT(!mDone);
|
||||
|
||||
NormalBlobConstructorParams normalParams;
|
||||
normalParams.contentType() = mContentType;
|
||||
normalParams.length() = mLength;
|
||||
|
||||
ActorType* newActor = ActorType::Create(normalParams);
|
||||
MOZ_ASSERT(newActor);
|
||||
|
||||
SlicedBlobConstructorParams slicedParams;
|
||||
slicedParams.contentType() = mContentType;
|
||||
slicedParams.begin() = mStart;
|
||||
slicedParams.end() = mStart + mLength;
|
||||
SetBlobOnParams(mActor, slicedParams);
|
||||
|
||||
if (mActor->Manager()->SendPBlobConstructor(newActor, slicedParams)) {
|
||||
mSlice = newActor->GetBlob();
|
||||
}
|
||||
|
||||
mActor = nullptr;
|
||||
|
||||
if (aNotify) {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mDone = true;
|
||||
lock.Notify();
|
||||
}
|
||||
else {
|
||||
mDone = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
RemoteBlob(const nsAString& aName, const nsAString& aContentType,
|
||||
PRUint64 aLength)
|
||||
: nsDOMFile(aName, aContentType, aLength), mActor(nullptr)
|
||||
{ }
|
||||
|
||||
RemoteBlob(const nsAString& aContentType, PRUint64 aLength)
|
||||
: nsDOMFile(aContentType, aLength), mActor(nullptr)
|
||||
{ }
|
||||
|
||||
virtual ~RemoteBlob()
|
||||
{
|
||||
if (mActor) {
|
||||
mActor->NoteDyingRemoteBlob();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetActor(ActorType* aActor)
|
||||
{
|
||||
MOZ_ASSERT(!aActor || !mActor);
|
||||
mActor = aActor;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<nsIDOMBlob>
|
||||
CreateSlice(PRUint64 aStart, PRUint64 aLength, const nsAString& aContentType)
|
||||
MOZ_OVERRIDE
|
||||
{
|
||||
if (!mActor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> slice;
|
||||
nsresult rv =
|
||||
helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return slice.forget();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE
|
||||
{
|
||||
if (!mActor) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
|
||||
return helper->GetStream(aStream);
|
||||
}
|
||||
|
||||
virtual void*
|
||||
GetPBlob() MOZ_OVERRIDE
|
||||
{
|
||||
return static_cast<typename ActorType::BaseType*>(mActor);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
Blob<ActorFlavor>::Blob(nsIDOMBlob* aBlob)
|
||||
: mBlob(aBlob), mRemoteBlob(nullptr), mOwnsBlob(true)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
aBlob->AddRef();
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
Blob<ActorFlavor>::Blob(const BlobConstructorParams& aParams)
|
||||
: mBlob(nullptr), mRemoteBlob(nullptr), mOwnsBlob(true)
|
||||
{
|
||||
nsRefPtr<RemoteBlobType> remoteBlob;
|
||||
|
||||
switch (aParams.type()) {
|
||||
case BlobConstructorParams::TNormalBlobConstructorParams: {
|
||||
const NormalBlobConstructorParams& params =
|
||||
aParams.get_NormalBlobConstructorParams();
|
||||
remoteBlob = new RemoteBlobType(params.contentType(), params.length());
|
||||
break;
|
||||
}
|
||||
|
||||
case BlobConstructorParams::TFileBlobConstructorParams: {
|
||||
const FileBlobConstructorParams& params =
|
||||
aParams.get_FileBlobConstructorParams();
|
||||
remoteBlob =
|
||||
new RemoteBlobType(params.name(), params.contentType(),
|
||||
params.length());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown params!");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(remoteBlob);
|
||||
|
||||
if (NS_FAILED(remoteBlob->SetMutable(false))) {
|
||||
MOZ_NOT_REACHED("Failed to make remote blob immutable!");
|
||||
}
|
||||
|
||||
remoteBlob->SetActor(this);
|
||||
remoteBlob.forget(&mRemoteBlob);
|
||||
|
||||
mBlob = mRemoteBlob;
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
Blob<ActorFlavor>*
|
||||
Blob<ActorFlavor>::Create(const BlobConstructorParams& aParams)
|
||||
{
|
||||
switch (aParams.type()) {
|
||||
case BlobConstructorParams::TNormalBlobConstructorParams:
|
||||
case BlobConstructorParams::TFileBlobConstructorParams:
|
||||
return new Blob<ActorFlavor>(aParams);
|
||||
|
||||
case BlobConstructorParams::TSlicedBlobConstructorParams: {
|
||||
const SlicedBlobConstructorParams& params =
|
||||
aParams.get_SlicedBlobConstructorParams();
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> source = GetBlobFromParams<ActorFlavor>(params);
|
||||
MOZ_ASSERT(source);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> slice;
|
||||
nsresult rv =
|
||||
source->Slice(params.begin(), params.end(), params.contentType(), 3,
|
||||
getter_AddRefs(slice));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return new Blob<ActorFlavor>(slice);
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown params!");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
Blob<ActorFlavor>::GetBlob()
|
||||
{
|
||||
MOZ_ASSERT(mBlob);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob;
|
||||
|
||||
// Remote blobs are held alive until the first call to GetBlob. Thereafter we
|
||||
// only hold a weak reference. Normal blobs are held alive until the actor is
|
||||
// destroyed.
|
||||
if (mRemoteBlob && mOwnsBlob) {
|
||||
blob = dont_AddRef(mBlob);
|
||||
mOwnsBlob = false;
|
||||
}
|
||||
else {
|
||||
blob = mBlob;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(blob);
|
||||
|
||||
return blob.forget();
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
void
|
||||
Blob<ActorFlavor>::NoteDyingRemoteBlob()
|
||||
{
|
||||
MOZ_ASSERT(mBlob);
|
||||
MOZ_ASSERT(mRemoteBlob);
|
||||
MOZ_ASSERT(!mOwnsBlob);
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewNonOwningRunnableMethod(this,
|
||||
&Blob<ActorFlavor>::NoteDyingRemoteBlob);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||
MOZ_NOT_REACHED("Should never fail!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Must do this before calling Send__delete__ or we'll crash there trying to
|
||||
// access a dangling pointer.
|
||||
mRemoteBlob = nullptr;
|
||||
|
||||
BaseType::Send__delete__(this);
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
void
|
||||
Blob<ActorFlavor>::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_ASSERT(mBlob);
|
||||
|
||||
if (mRemoteBlob) {
|
||||
mRemoteBlob->SetActor(nullptr);
|
||||
}
|
||||
|
||||
if (mOwnsBlob) {
|
||||
mBlob->Release();
|
||||
}
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
bool
|
||||
Blob<ActorFlavor>::RecvPBlobStreamConstructor(StreamType* aActor)
|
||||
{
|
||||
MOZ_ASSERT(mBlob);
|
||||
MOZ_ASSERT(!mRemoteBlob);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return aActor->Send__delete__(aActor, stream.get());
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
typename Blob<ActorFlavor>::StreamType*
|
||||
Blob<ActorFlavor>::AllocPBlobStream()
|
||||
{
|
||||
return new InputStreamActor<ActorFlavor>();
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
bool
|
||||
Blob<ActorFlavor>::DeallocPBlobStream(StreamType* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
NS_IMPL_ADDREF_INHERITED(RemoteBlob<ActorFlavor>, nsDOMFile)
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
NS_IMPL_RELEASE_INHERITED(RemoteBlob<ActorFlavor>, nsDOMFile)
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteBlob<ActorFlavor>, nsDOMFile,
|
||||
nsIRemoteBlob)
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
|
||||
NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
// Explicit instantiation of both classes.
|
||||
template class Blob<Parent>;
|
||||
template class Blob<Child>;
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
120
dom/ipc/Blob.h
Normal file
120
dom/ipc/Blob.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et 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_ipc_Blob_h
|
||||
#define mozilla_dom_ipc_Blob_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/PBlobChild.h"
|
||||
#include "mozilla/dom/PBlobParent.h"
|
||||
#include "mozilla/dom/PBlobStreamChild.h"
|
||||
#include "mozilla/dom/PBlobStreamParent.h"
|
||||
#include "mozilla/dom/PContentChild.h"
|
||||
#include "mozilla/dom/PContentParent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIDOMBlob;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
enum ActorFlavorEnum
|
||||
{
|
||||
Parent = 0,
|
||||
Child
|
||||
};
|
||||
|
||||
template <ActorFlavorEnum>
|
||||
struct BlobTraits
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct BlobTraits<Parent>
|
||||
{
|
||||
typedef mozilla::dom::PBlobParent BaseType;
|
||||
typedef mozilla::dom::PBlobStreamParent StreamType;
|
||||
typedef mozilla::dom::PContentParent ManagerType;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BlobTraits<Child>
|
||||
{
|
||||
typedef mozilla::dom::PBlobChild BaseType;
|
||||
typedef mozilla::dom::PBlobStreamChild StreamType;
|
||||
typedef mozilla::dom::PContentChild ManagerType;
|
||||
};
|
||||
|
||||
template <ActorFlavorEnum>
|
||||
class RemoteBlob;
|
||||
|
||||
template <ActorFlavorEnum ActorFlavor>
|
||||
class Blob : public BlobTraits<ActorFlavor>::BaseType
|
||||
{
|
||||
public:
|
||||
typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
|
||||
typedef typename BlobTraits<ActorFlavor>::StreamType StreamType;
|
||||
typedef typename BlobTraits<ActorFlavor>::ManagerType ManagerType;
|
||||
typedef RemoteBlob<ActorFlavor> RemoteBlobType;
|
||||
typedef mozilla::ipc::IProtocolManager<
|
||||
mozilla::ipc::RPCChannel::RPCListener>::ActorDestroyReason
|
||||
ActorDestroyReason;
|
||||
typedef mozilla::dom::BlobConstructorParams BlobConstructorParams;
|
||||
|
||||
protected:
|
||||
nsIDOMBlob* mBlob;
|
||||
RemoteBlobType* mRemoteBlob;
|
||||
bool mOwnsBlob;
|
||||
|
||||
public:
|
||||
// This create function is called on the sending side.
|
||||
static Blob*
|
||||
Create(nsIDOMBlob* aBlob)
|
||||
{
|
||||
return new Blob(aBlob);
|
||||
}
|
||||
|
||||
// This create function is called on the receiving side.
|
||||
static Blob*
|
||||
Create(const BlobConstructorParams& aParams);
|
||||
|
||||
already_AddRefed<nsIDOMBlob>
|
||||
GetBlob();
|
||||
|
||||
void
|
||||
NoteDyingRemoteBlob();
|
||||
|
||||
private:
|
||||
// This constructor is called on the sending side.
|
||||
Blob(nsIDOMBlob* aBlob);
|
||||
|
||||
// This constructor is called on the receiving side.
|
||||
Blob(const BlobConstructorParams& aParams);
|
||||
|
||||
// These methods are only called by the IPDL message machinery.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPBlobStreamConstructor(StreamType* aActor) MOZ_OVERRIDE;
|
||||
|
||||
virtual StreamType*
|
||||
AllocPBlobStream() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBlobStream(StreamType* aActor) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
typedef mozilla::dom::ipc::Blob<mozilla::dom::ipc::Child> BlobChild;
|
||||
typedef mozilla::dom::ipc::Blob<mozilla::dom::ipc::Parent> BlobParent;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ipc_Blob_h
|
@ -81,9 +81,13 @@
|
||||
#include "nsIAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/indexedDB/PIndexedDBChild.h"
|
||||
#include "mozilla/dom/sms/SmsChild.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
|
||||
#include "mozilla/dom/indexedDB/PIndexedDBChild.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIRemoteBlob.h"
|
||||
#include "StructuredCloneUtils.h"
|
||||
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
@ -390,7 +394,7 @@ ContentChild::DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor)
|
||||
}
|
||||
|
||||
PCompositorChild*
|
||||
ContentChild::AllocPCompositor(ipc::Transport* aTransport,
|
||||
ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return CompositorChild::Create(aTransport, aOtherProcess);
|
||||
@ -413,6 +417,71 @@ ContentChild::DeallocPBrowser(PBrowserChild* iframe)
|
||||
return true;
|
||||
}
|
||||
|
||||
PBlobChild*
|
||||
ContentChild::AllocPBlob(const BlobConstructorParams& aParams)
|
||||
{
|
||||
return BlobChild::Create(aParams);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPBlob(PBlobChild* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
BlobChild*
|
||||
ContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
|
||||
{
|
||||
NS_ASSERTION(aBlob, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob);
|
||||
if (remoteBlob) {
|
||||
BlobChild* actor =
|
||||
static_cast<BlobChild*>(static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
|
||||
NS_ASSERTION(actor, "Null actor?!");
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
BlobConstructorParams params;
|
||||
|
||||
nsString contentType;
|
||||
nsresult rv = aBlob->GetType(contentType);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
PRUint64 length;
|
||||
rv = aBlob->GetSize(&length);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
|
||||
if (file) {
|
||||
FileBlobConstructorParams fileParams;
|
||||
|
||||
rv = file->GetName(fileParams.name());
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
fileParams.contentType() = contentType;
|
||||
fileParams.length() = length;
|
||||
|
||||
params = fileParams;
|
||||
} else {
|
||||
NormalBlobConstructorParams blobParams;
|
||||
blobParams.contentType() = contentType;
|
||||
blobParams.length() = length;
|
||||
params = blobParams;
|
||||
}
|
||||
|
||||
BlobChild* actor = BlobChild::Create(aBlob);
|
||||
NS_ENSURE_TRUE(actor, nullptr);
|
||||
|
||||
if (!SendPBlobConstructor(actor, params)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
PCrashReporterChild*
|
||||
ContentChild::AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
|
||||
const PRUint32& processType)
|
||||
@ -704,14 +773,30 @@ ContentChild::RecvNotifyVisited(const IPC::URI& aURI)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ContentChild::RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON)
|
||||
ContentChild::RecvAsyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData)
|
||||
{
|
||||
nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
|
||||
if (cpm) {
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobChild*>& blobChildList = aData.blobsChild();
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
if (!blobChildList.IsEmpty()) {
|
||||
PRUint32 length = blobChildList.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = static_cast<BlobChild*>(blobChildList[i]);
|
||||
MOZ_ASSERT(blobChild);
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobChild->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
|
||||
aMsg, false, aJSON, nullptr, nullptr);
|
||||
aMsg, false, &cloneData, nullptr, nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -826,5 +911,20 @@ ContentChild::RecvLastPrivateDocShellDestroyed()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvFilePathUpdate(const nsString& path, const nsCString& aReason)
|
||||
{
|
||||
// data strings will have the format of
|
||||
// reason:path
|
||||
nsString data;
|
||||
CopyASCIItoUTF16(aReason, data);
|
||||
data.Append(NS_LITERAL_STRING(":"));
|
||||
data.Append(path);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nullptr, "file-watcher-update", data.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/PContentChild.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsIConsoleListener.h"
|
||||
|
||||
struct ChromePackage;
|
||||
class nsIDOMBlob;
|
||||
class nsIObserver;
|
||||
struct ResourceMapping;
|
||||
struct OverrideMapping;
|
||||
@ -30,10 +32,12 @@ class AlertObserver;
|
||||
class PrefObserver;
|
||||
class ConsoleListener;
|
||||
class PStorageChild;
|
||||
class ClonedMessageData;
|
||||
|
||||
class ContentChild : public PContentChild
|
||||
{
|
||||
typedef layers::PCompositorChild PCompositorChild;
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
ContentChild();
|
||||
@ -59,7 +63,7 @@ public:
|
||||
return mAppInfo;
|
||||
}
|
||||
|
||||
PCompositorChild* AllocPCompositor(ipc::Transport* aTransport,
|
||||
PCompositorChild* AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags,
|
||||
@ -70,6 +74,9 @@ public:
|
||||
virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestChild*);
|
||||
|
||||
virtual PBlobChild* AllocPBlob(const BlobConstructorParams& aParams);
|
||||
virtual bool DeallocPBlob(PBlobChild*);
|
||||
|
||||
virtual PCrashReporterChild*
|
||||
AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
|
||||
const PRUint32& processType);
|
||||
@ -134,7 +141,8 @@ public:
|
||||
|
||||
virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
|
||||
|
||||
virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
|
||||
virtual bool RecvAsyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData);
|
||||
|
||||
virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
|
||||
|
||||
@ -154,6 +162,8 @@ public:
|
||||
|
||||
virtual bool RecvLastPrivateDocShellDestroyed();
|
||||
|
||||
virtual bool RecvFilePathUpdate(const nsString& path, const nsCString& reason);
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
@ -164,6 +174,8 @@ public:
|
||||
|
||||
PRUint64 GetID() { return mID; }
|
||||
|
||||
BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
|
||||
|
||||
private:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -6,12 +6,13 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "ContentParent.h"
|
||||
|
||||
#if defined(ANDROID) || defined(LINUX)
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "ContentParent.h"
|
||||
#include "CrashReporterParent.h"
|
||||
#include "History.h"
|
||||
#include "IDBFactory.h"
|
||||
@ -47,12 +48,14 @@
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIRemoteBlob.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
@ -63,6 +66,7 @@
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "SandboxHal.h"
|
||||
#include "StructuredCloneUtils.h"
|
||||
#include "TabParent.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
@ -524,6 +528,8 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL)
|
||||
//Sending all information to content process
|
||||
unused << SendAppInfo(version, buildID);
|
||||
}
|
||||
|
||||
mFileWatchers.Init();
|
||||
}
|
||||
|
||||
ContentParent::~ContentParent()
|
||||
@ -760,6 +766,9 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
|
||||
|
||||
mFileWatchers.Clear();
|
||||
|
||||
Close();
|
||||
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
|
||||
}
|
||||
@ -827,7 +836,7 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
}
|
||||
|
||||
PCompositorParent*
|
||||
ContentParent::AllocPCompositor(ipc::Transport* aTransport,
|
||||
ContentParent::AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return CompositorParent::Create(aTransport, aOtherProcess);
|
||||
@ -866,6 +875,72 @@ ContentParent::DeallocPDeviceStorageRequest(PDeviceStorageRequestParent* doomed)
|
||||
return true;
|
||||
}
|
||||
|
||||
PBlobParent*
|
||||
ContentParent::AllocPBlob(const BlobConstructorParams& aParams)
|
||||
{
|
||||
return BlobParent::Create(aParams);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPBlob(PBlobParent* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
BlobParent*
|
||||
ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
|
||||
{
|
||||
NS_ASSERTION(aBlob, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob);
|
||||
if (remoteBlob) {
|
||||
BlobParent* actor =
|
||||
static_cast<BlobParent*>(
|
||||
static_cast<PBlobParent*>(remoteBlob->GetPBlob()));
|
||||
NS_ASSERTION(actor, "Null actor?!");
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
BlobConstructorParams params;
|
||||
|
||||
nsString contentType;
|
||||
nsresult rv = aBlob->GetType(contentType);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
PRUint64 length;
|
||||
rv = aBlob->GetSize(&length);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
|
||||
if (file) {
|
||||
FileBlobConstructorParams fileParams;
|
||||
|
||||
rv = file->GetName(fileParams.name());
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
fileParams.contentType() = contentType;
|
||||
fileParams.length() = length;
|
||||
|
||||
params = fileParams;
|
||||
} else {
|
||||
NormalBlobConstructorParams blobParams;
|
||||
blobParams.contentType() = contentType;
|
||||
blobParams.length() = length;
|
||||
params = blobParams;
|
||||
}
|
||||
|
||||
BlobParent* actor = BlobParent::Create(aBlob);
|
||||
NS_ENSURE_TRUE(actor, nullptr);
|
||||
|
||||
if (!SendPBlobConstructor(actor, params)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
PCrashReporterParent*
|
||||
ContentParent::AllocPCrashReporter(const NativeThreadId& tid,
|
||||
const PRUint32& processType)
|
||||
@ -930,7 +1005,7 @@ ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor)
|
||||
}
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv = IDBFactory::Create(getter_AddRefs(factory));
|
||||
nsresult rv = IDBFactory::Create(this, getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
NS_ASSERTION(factory, "This should never be null!");
|
||||
@ -1291,24 +1366,59 @@ ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsStri
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
|
||||
ContentParent::RecvSyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<nsString>* aRetvals)
|
||||
{
|
||||
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
|
||||
if (ppm) {
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobParent*>& blobParents = aData.blobsParent();
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
if (!blobParents.IsEmpty()) {
|
||||
PRUint32 length = blobParents.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
BlobParent* blobParent = static_cast<BlobParent*>(blobParents[index]);
|
||||
MOZ_ASSERT(blobParent);
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobParent->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
aMsg,true, aJSON, nullptr, aRetvals);
|
||||
aMsg, true, &cloneData, nullptr, aRetvals);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON)
|
||||
ContentParent::RecvAsyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData)
|
||||
{
|
||||
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
|
||||
if (ppm) {
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobParent*>& blobParents = aData.blobsParent();
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
if (!blobParents.IsEmpty()) {
|
||||
PRUint32 length = blobParents.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
BlobParent* blobParent = static_cast<BlobParent*>(blobParents[index]);
|
||||
MOZ_ASSERT(blobParent);
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobParent->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
|
||||
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
|
||||
aMsg, false, aJSON, nullptr, nullptr);
|
||||
aMsg, false, &cloneData, nullptr, nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1402,5 +1512,64 @@ ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAddFileWatch(const nsString& root)
|
||||
{
|
||||
nsRefPtr<WatchedFile> f;
|
||||
if (mFileWatchers.Get(root, getter_AddRefs(f))) {
|
||||
f->mUsageCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
f = new WatchedFile(this, root);
|
||||
mFileWatchers.Put(root, f);
|
||||
|
||||
f->Watch();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvRemoveFileWatch(const nsString& root)
|
||||
{
|
||||
nsRefPtr<WatchedFile> f;
|
||||
bool result = mFileWatchers.Get(root, getter_AddRefs(f));
|
||||
if (!result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!f)
|
||||
return true;
|
||||
|
||||
f->mUsageCount--;
|
||||
|
||||
if (f->mUsageCount > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
f->Unwatch();
|
||||
mFileWatchers.Remove(root);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ContentParent::WatchedFile, nsIFileUpdateListener)
|
||||
|
||||
nsresult
|
||||
ContentParent::WatchedFile::Update(const char* aReason, nsIFile* aFile)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsString path;
|
||||
aFile->GetPath(path);
|
||||
|
||||
unused << mParent->SendFilePathUpdate(path, nsDependentCString(aReason));
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCString cpath;
|
||||
aFile->GetNativePath(cpath);
|
||||
printf("ContentParent::WatchedFile::Update: %s -- %s\n", cpath.get(), aReason);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/dom/PContentParent.h"
|
||||
#include "mozilla/dom/PMemoryReportRequestParent.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
@ -21,8 +22,12 @@
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsFrameMessageManager;
|
||||
class nsIDOMBlob;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
@ -37,6 +42,7 @@ namespace dom {
|
||||
|
||||
class TabParent;
|
||||
class PStorageParent;
|
||||
class ClonedMessageData;
|
||||
|
||||
class ContentParent : public PContentParent
|
||||
, public nsIObserver
|
||||
@ -47,6 +53,7 @@ private:
|
||||
typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
|
||||
typedef mozilla::ipc::TestShellParent TestShellParent;
|
||||
typedef mozilla::layers::PCompositorParent PCompositorParent;
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
static ContentParent* GetNewOrUsed();
|
||||
@ -97,6 +104,8 @@ public:
|
||||
return mSendPermissionUpdates;
|
||||
}
|
||||
|
||||
BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32 pid);
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
@ -130,7 +139,7 @@ private:
|
||||
*/
|
||||
void ShutDown();
|
||||
|
||||
PCompositorParent* AllocPCompositor(ipc::Transport* aTransport,
|
||||
PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags, const bool& aIsBrowserElement, const PRUint32& aAppId);
|
||||
@ -139,6 +148,9 @@ private:
|
||||
virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*);
|
||||
|
||||
virtual PBlobParent* AllocPBlob(const BlobConstructorParams& aParams);
|
||||
virtual bool DeallocPBlob(PBlobParent*);
|
||||
|
||||
virtual PCrashReporterParent* AllocPCrashReporter(const NativeThreadId& tid,
|
||||
const PRUint32& processType);
|
||||
virtual bool DeallocPCrashReporter(PCrashReporterParent* crashreporter);
|
||||
@ -226,9 +238,11 @@ private:
|
||||
|
||||
virtual bool RecvLoadURIExternal(const IPC::URI& uri);
|
||||
|
||||
virtual bool RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
|
||||
virtual bool RecvSyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<nsString>* aRetvals);
|
||||
virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
|
||||
virtual bool RecvAsyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData);
|
||||
|
||||
virtual bool RecvAddGeolocationListener();
|
||||
virtual bool RecvRemoveGeolocationListener();
|
||||
@ -243,6 +257,10 @@ private:
|
||||
const nsCString& aCategory);
|
||||
|
||||
virtual bool RecvPrivateDocShellsExist(const bool& aExist);
|
||||
|
||||
virtual bool RecvAddFileWatch(const nsString& root);
|
||||
virtual bool RecvRemoveFileWatch(const nsString& root);
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
||||
PRInt32 mGeolocationWatchID;
|
||||
@ -261,6 +279,34 @@ private:
|
||||
const nsString mAppManifestURL;
|
||||
nsRefPtr<nsFrameMessageManager> mMessageManager;
|
||||
|
||||
class WatchedFile : public nsIFileUpdateListener {
|
||||
public:
|
||||
WatchedFile(ContentParent* aParent, const nsString& aPath)
|
||||
: mParent(aParent)
|
||||
, mUsageCount(1)
|
||||
{
|
||||
NS_NewLocalFile(aPath, false, getter_AddRefs(mFile));
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIFILEUPDATELISTENER
|
||||
|
||||
void Watch() {
|
||||
mFile->Watch(this);
|
||||
}
|
||||
|
||||
void Unwatch() {
|
||||
mFile->Watch(this);
|
||||
}
|
||||
|
||||
nsRefPtr<ContentParent> mParent;
|
||||
PRInt32 mUsageCount;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
};
|
||||
|
||||
// This is a cache of all of the registered file watchers.
|
||||
nsInterfaceHashtable<nsStringHashKey, WatchedFile> mFileWatchers;
|
||||
|
||||
friend class CrashReporterParent;
|
||||
};
|
||||
|
||||
|
21
dom/ipc/DOMTypes.ipdlh
Normal file
21
dom/ipc/DOMTypes.ipdlh
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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 PBlob;
|
||||
|
||||
using mozilla::SerializedStructuredCloneBuffer;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct ClonedMessageData
|
||||
{
|
||||
SerializedStructuredCloneBuffer data;
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -21,7 +21,10 @@ endif
|
||||
|
||||
EXPORTS = PCOMContentPermissionRequestChild.h
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/dom
|
||||
EXPORTS_NAMESPACES = \
|
||||
mozilla/dom \
|
||||
mozilla/dom/ipc \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
ContentChild.h \
|
||||
@ -29,17 +32,25 @@ EXPORTS_mozilla/dom = \
|
||||
ContentProcess.h \
|
||||
CrashReporterChild.h \
|
||||
CrashReporterParent.h \
|
||||
StructuredCloneUtils.h \
|
||||
TabParent.h \
|
||||
TabChild.h \
|
||||
TabMessageUtils.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom/ipc = \
|
||||
Blob.h \
|
||||
nsIRemoteBlob.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
Blob.cpp \
|
||||
ContentProcess.cpp \
|
||||
ContentParent.cpp \
|
||||
ContentChild.cpp \
|
||||
CrashReporterParent.cpp \
|
||||
CrashReporterChild.cpp \
|
||||
StructuredCloneUtils.cpp \
|
||||
TabParent.cpp \
|
||||
TabChild.cpp \
|
||||
TabMessageUtils.cpp \
|
||||
|
23
dom/ipc/PBlob.ipdl
Normal file
23
dom/ipc/PBlob.ipdl
Normal file
@ -0,0 +1,23 @@
|
||||
/* 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 PBlobStream;
|
||||
include protocol PContent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
protocol PBlob
|
||||
{
|
||||
manager PContent;
|
||||
manages PBlobStream;
|
||||
|
||||
both:
|
||||
__delete__();
|
||||
|
||||
PBlobStream();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
23
dom/ipc/PBlobStream.ipdl
Normal file
23
dom/ipc/PBlobStream.ipdl
Normal file
@ -0,0 +1,23 @@
|
||||
/* 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 PBlob;
|
||||
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
using IPC::InputStream;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
protocol PBlobStream
|
||||
{
|
||||
manager PBlob;
|
||||
|
||||
both:
|
||||
__delete__(InputStream stream);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -5,6 +5,7 @@
|
||||
* 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 PBlob;
|
||||
include protocol PContent;
|
||||
include protocol PContentDialog;
|
||||
include protocol PDocumentRenderer;
|
||||
@ -19,6 +20,8 @@ include "mozilla/dom/TabMessageUtils.h";
|
||||
include "mozilla/layout/RenderFrameUtils.h";
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
include DOMTypes;
|
||||
|
||||
using IPC::URI;
|
||||
using gfxMatrix;
|
||||
using gfxSize;
|
||||
@ -56,7 +59,7 @@ rpc protocol PBrowser
|
||||
manages PIndexedDB;
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, nsString aJSON);
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData);
|
||||
|
||||
parent:
|
||||
/**
|
||||
@ -69,7 +72,7 @@ parent:
|
||||
|
||||
rpc CreateWindow() returns (PBrowser window);
|
||||
|
||||
sync SyncMessage(nsString aMessage, nsString aJSON)
|
||||
sync SyncMessage(nsString aMessage, ClonedMessageData aData)
|
||||
returns (nsString[] retval);
|
||||
|
||||
/**
|
||||
@ -339,4 +342,4 @@ state DYING:
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PAudio;
|
||||
include protocol PBlob;
|
||||
include protocol PBrowser;
|
||||
include protocol PCompositor;
|
||||
include protocol PCrashReporter;
|
||||
@ -25,6 +26,8 @@ include "mozilla/dom/TabMessageUtils.h";
|
||||
include "nsGeoPositionIPCSerialiser.h";
|
||||
include "PPrefTuple.h";
|
||||
|
||||
include DOMTypes;
|
||||
|
||||
using GeoPosition;
|
||||
using PrefTuple;
|
||||
|
||||
@ -34,6 +37,7 @@ using OverrideMapping;
|
||||
using IPC::URI;
|
||||
using IPC::Permission;
|
||||
using mozilla::null_t;
|
||||
using mozilla::void_t;
|
||||
using mozilla::dom::NativeThreadId;
|
||||
using gfxIntSize;
|
||||
|
||||
@ -96,11 +100,41 @@ union DeviceStorageParams
|
||||
DeviceStorageDeleteParams;
|
||||
DeviceStorageEnumerationParams;
|
||||
};
|
||||
|
||||
struct NormalBlobConstructorParams
|
||||
{
|
||||
nsString contentType;
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
struct FileBlobConstructorParams
|
||||
{
|
||||
nsString name;
|
||||
nsString contentType;
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
struct SlicedBlobConstructorParams
|
||||
{
|
||||
PBlob source;
|
||||
uint64_t begin;
|
||||
uint64_t end;
|
||||
nsString contentType;
|
||||
};
|
||||
|
||||
union BlobConstructorParams
|
||||
{
|
||||
NormalBlobConstructorParams;
|
||||
FileBlobConstructorParams;
|
||||
SlicedBlobConstructorParams;
|
||||
};
|
||||
|
||||
rpc protocol PContent
|
||||
{
|
||||
parent opens PCompositor;
|
||||
|
||||
manages PAudio;
|
||||
manages PBlob;
|
||||
manages PBrowser;
|
||||
manages PCrashReporter;
|
||||
manages PDeviceStorageRequest;
|
||||
@ -122,6 +156,8 @@ both:
|
||||
// as part of ContentParent::CreateTab.
|
||||
async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, PRUint32 appId);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
child:
|
||||
PMemoryReportRequest();
|
||||
|
||||
@ -163,6 +199,8 @@ child:
|
||||
// Notify child that last-pb-context-exited notification was observed
|
||||
LastPrivateDocShellDestroyed();
|
||||
|
||||
FilePathUpdate(nsString filepath, nsCString reasons);
|
||||
|
||||
parent:
|
||||
PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
|
||||
|
||||
@ -199,7 +237,7 @@ parent:
|
||||
|
||||
sync ReadFontList() returns (FontListEntry[] retValue);
|
||||
|
||||
sync SyncMessage(nsString aMessage, nsString aJSON)
|
||||
sync SyncMessage(nsString aMessage, ClonedMessageData aData)
|
||||
returns (nsString[] retval);
|
||||
|
||||
ShowAlertNotification(nsString imageUrl,
|
||||
@ -245,9 +283,11 @@ parent:
|
||||
// Notify the parent of the presence or absence of private docshells
|
||||
PrivateDocShellsExist(bool aExist);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, nsString aJSON);
|
||||
AddFileWatch(nsString filepath);
|
||||
RemoveFileWatch(nsString filepath);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData);
|
||||
};
|
||||
|
||||
}
|
||||
|
187
dom/ipc/StructuredCloneUtils.cpp
Normal file
187
dom/ipc/StructuredCloneUtils.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et 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 "StructuredCloneUtils.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIDOMDOMException.h"
|
||||
#include "nsIMutable.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "StructuredCloneTags.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
Error(JSContext* aCx, uint32_t aErrorId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_DOMStructuredCloneError(aCx, aErrorId);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
|
||||
uint32_t aData, void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
StructuredCloneClosure* closure =
|
||||
static_cast<StructuredCloneClosure*>(aClosure);
|
||||
|
||||
if (aTag == SCTAG_DOM_FILE) {
|
||||
MOZ_ASSERT(aData < closure->mBlobs.Length());
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(closure->mBlobs[aData]);
|
||||
MOZ_ASSERT(file);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// File should not be mutable.
|
||||
nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
|
||||
bool isMutable;
|
||||
if (NS_FAILED(mutableFile->GetMutable(&isMutable))) {
|
||||
MOZ_NOT_REACHED("GetMutable failed!");
|
||||
}
|
||||
else {
|
||||
MOZ_ASSERT(!isMutable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
jsval wrappedFile;
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), file,
|
||||
&NS_GET_IID(nsIDOMFile), &wrappedFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &wrappedFile.toObject();
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_BLOB) {
|
||||
MOZ_ASSERT(aData < closure->mBlobs.Length());
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(closure->mBlobs[aData]);
|
||||
MOZ_ASSERT(blob);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Blob should not be mutable.
|
||||
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
|
||||
bool isMutable;
|
||||
if (NS_FAILED(mutableBlob->GetMutable(&isMutable))) {
|
||||
MOZ_NOT_REACHED("GetMutable failed!");
|
||||
}
|
||||
else {
|
||||
MOZ_ASSERT(!isMutable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
jsval wrappedBlob;
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx), blob,
|
||||
&NS_GET_IID(nsIDOMBlob), &wrappedBlob);
|
||||
if (NS_FAILED(rv)) {
|
||||
Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &wrappedBlob.toObject();
|
||||
}
|
||||
|
||||
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
|
||||
}
|
||||
|
||||
JSBool
|
||||
Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj,
|
||||
void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
StructuredCloneClosure* closure =
|
||||
static_cast<StructuredCloneClosure*>(aClosure);
|
||||
|
||||
// See if this is a wrapped native.
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
|
||||
nsContentUtils::XPConnect()->
|
||||
GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative));
|
||||
|
||||
if (wrappedNative) {
|
||||
// Get the raw nsISupports out of it.
|
||||
nsISupports* wrappedObject = wrappedNative->Native();
|
||||
MOZ_ASSERT(wrappedObject);
|
||||
|
||||
// See if the wrapped native is a nsIDOMFile.
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(wrappedObject);
|
||||
if (file) {
|
||||
nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
|
||||
if (mutableFile &&
|
||||
NS_SUCCEEDED(mutableFile->SetMutable(false)) &&
|
||||
JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILE,
|
||||
closure->mBlobs.Length())) {
|
||||
closure->mBlobs.AppendElement(file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// See if the wrapped native is a nsIDOMBlob.
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(wrappedObject);
|
||||
if (blob) {
|
||||
nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
|
||||
if (mutableBlob &&
|
||||
NS_SUCCEEDED(mutableBlob->SetMutable(false)) &&
|
||||
JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
|
||||
closure->mBlobs.Length())) {
|
||||
closure->mBlobs.AppendElement(blob);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
|
||||
}
|
||||
|
||||
JSStructuredCloneCallbacks gCallbacks = {
|
||||
Read,
|
||||
Write,
|
||||
Error
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
bool
|
||||
ReadStructuredClone(JSContext* aCx, const uint64_t* aData, size_t aDataLength,
|
||||
const StructuredCloneClosure& aClosure, JS::Value* aClone)
|
||||
{
|
||||
void* closure = &const_cast<StructuredCloneClosure&>(aClosure);
|
||||
return !!JS_ReadStructuredClone(aCx, aData, aDataLength,
|
||||
JS_STRUCTURED_CLONE_VERSION, aClone,
|
||||
&gCallbacks, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
WriteStructuredClone(JSContext* aCx, const JS::Value& aSource,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
StructuredCloneClosure& aClosure)
|
||||
{
|
||||
return aBuffer.write(aCx, aSource, &gCallbacks, &aClosure);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
56
dom/ipc/StructuredCloneUtils.h
Normal file
56
dom/ipc/StructuredCloneUtils.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et 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_StructuredCloneUtils_h
|
||||
#define mozilla_dom_StructuredCloneUtils_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIDOMFile.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct SerializedStructuredCloneBuffer;
|
||||
|
||||
namespace dom {
|
||||
|
||||
struct
|
||||
StructuredCloneClosure
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
|
||||
};
|
||||
|
||||
struct
|
||||
StructuredCloneData
|
||||
{
|
||||
StructuredCloneData() : mData(nullptr), mDataLength(0) {}
|
||||
uint64_t* mData;
|
||||
size_t mDataLength;
|
||||
StructuredCloneClosure mClosure;
|
||||
};
|
||||
|
||||
bool
|
||||
ReadStructuredClone(JSContext* aCx, const uint64_t* aData, size_t aDataLength,
|
||||
const StructuredCloneClosure& aClosure, JS::Value* aClone);
|
||||
|
||||
inline bool
|
||||
ReadStructuredClone(JSContext* aCx, const StructuredCloneData& aData,
|
||||
JS::Value* aClone)
|
||||
{
|
||||
return ReadStructuredClone(aCx, aData.mData, aData.mDataLength,
|
||||
aData.mClosure, aClone);
|
||||
}
|
||||
|
||||
bool
|
||||
WriteStructuredClone(JSContext* aCx, const JS::Value& aSource,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
StructuredCloneClosure& aClosure);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_StructuredCloneUtils_h
|
@ -6,7 +6,11 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "TabChild.h"
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "Blob.h"
|
||||
#include "ContentChild.h"
|
||||
#include "IndexedDBChild.h"
|
||||
#include "mozilla/IntentionalCrash.h"
|
||||
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
|
||||
@ -58,9 +62,10 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "PCOMContentPermissionRequestChild.h"
|
||||
#include "TabChild.h"
|
||||
#include "StructuredCloneUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
@ -646,6 +651,9 @@ TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort,
|
||||
const gfxSize& aResolution,
|
||||
const nsIntRect& aScreenSize)
|
||||
{
|
||||
if (!mCx || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
nsCString data;
|
||||
data += nsPrintfCString("{ \"x\" : %d", aScrollOffset.x);
|
||||
data += nsPrintfCString(", \"y\" : %d", aScrollOffset.y);
|
||||
@ -665,10 +673,25 @@ TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort,
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(" }");
|
||||
|
||||
jsval json = JSVAL_NULL;
|
||||
StructuredCloneData cloneData;
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
if (JS_ParseJSON(mCx,
|
||||
static_cast<const jschar*>(NS_ConvertUTF8toUTF16(data).get()),
|
||||
data.Length(),
|
||||
&json)) {
|
||||
WriteStructuredClone(mCx, json, buffer, cloneData.mClosure);
|
||||
}
|
||||
|
||||
nsFrameScriptCx cx(static_cast<nsIWebBrowserChrome*>(this), this);
|
||||
// Let the BrowserElementScrolling helper (if it exists) for this
|
||||
// content manipulate the frame state.
|
||||
return RecvAsyncMessage(NS_LITERAL_STRING("Viewport:Change"),
|
||||
NS_ConvertUTF8toUTF16(data));
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
|
||||
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
|
||||
NS_LITERAL_STRING("Viewport:Change"), false,
|
||||
&cloneData, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -958,14 +981,36 @@ TabChild::RecvLoadRemoteScript(const nsString& aURL)
|
||||
|
||||
bool
|
||||
TabChild::RecvAsyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON)
|
||||
const ClonedMessageData& aData)
|
||||
{
|
||||
if (mTabChildGlobal) {
|
||||
nsFrameScriptCx cx(static_cast<nsIWebBrowserChrome*>(this), this);
|
||||
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobChild*>& blobChildList = aData.blobsChild();
|
||||
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
|
||||
if (!blobChildList.IsEmpty()) {
|
||||
PRUint32 length = blobChildList.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = static_cast<BlobChild*>(blobChildList[i]);
|
||||
MOZ_ASSERT(blobChild);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobChild->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
|
||||
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
|
||||
aMessage, false, aJSON, nullptr, nullptr);
|
||||
aMessage, false, &cloneData, nullptr, nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1184,23 +1229,62 @@ TabChild::DeallocPIndexedDB(PIndexedDBChild* aActor)
|
||||
static bool
|
||||
SendSyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
const StructuredCloneData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
return static_cast<TabChild*>(aCallbackData)->
|
||||
SendSyncMessage(nsString(aMessage), nsString(aJSON),
|
||||
aJSONRetVal);
|
||||
TabChild* tabChild = static_cast<TabChild*>(aCallbackData);
|
||||
ContentChild* cc = static_cast<ContentChild*>(tabChild->Manager());
|
||||
ClonedMessageData data;
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild();
|
||||
PRUint32 length = blobs.Length();
|
||||
blobChildList.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobChild) {
|
||||
return false;
|
||||
}
|
||||
blobChildList.AppendElement(blobChild);
|
||||
}
|
||||
}
|
||||
return tabChild->SendSyncMessage(nsString(aMessage), data, aJSONRetVal);
|
||||
}
|
||||
|
||||
static bool
|
||||
SendAsyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON)
|
||||
const StructuredCloneData& aData)
|
||||
{
|
||||
return static_cast<TabChild*>(aCallbackData)->
|
||||
SendAsyncMessage(nsString(aMessage), nsString(aJSON));
|
||||
TabChild* tabChild = static_cast<TabChild*>(aCallbackData);
|
||||
ContentChild* cc = static_cast<ContentChild*>(tabChild->Manager());
|
||||
ClonedMessageData data;
|
||||
SerializedStructuredCloneBuffer& buffer = data.data();
|
||||
buffer.data = aData.mData;
|
||||
buffer.dataLength = aData.mDataLength;
|
||||
|
||||
const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
|
||||
if (!blobs.IsEmpty()) {
|
||||
InfallibleTArray<PBlobChild*>& blobChildList = data.blobsChild();
|
||||
PRUint32 length = blobs.Length();
|
||||
blobChildList.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobChild* blobChild = cc->GetOrCreateActorForBlob(blobs[i]);
|
||||
if (!blobChild) {
|
||||
return false;
|
||||
}
|
||||
blobChildList.AppendElement(blobChild);
|
||||
}
|
||||
}
|
||||
|
||||
return tabChild->SendAsyncMessage(nsString(aMessage), data);
|
||||
}
|
||||
|
||||
|
||||
TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
|
||||
: mTabChild(aTabChild)
|
||||
{
|
||||
|
@ -59,6 +59,7 @@ namespace dom {
|
||||
|
||||
class TabChild;
|
||||
class PContentDialogChild;
|
||||
class ClonedMessageData;
|
||||
|
||||
class TabChildGlobal : public nsDOMEventTargetHelper,
|
||||
public nsIContentFrameMessageManager,
|
||||
@ -142,6 +143,7 @@ class TabChild : public PBrowserChild,
|
||||
public nsITabChild
|
||||
{
|
||||
typedef mozilla::layout::RenderFrameChild RenderFrameChild;
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -196,7 +198,7 @@ public:
|
||||
virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture);
|
||||
virtual bool RecvLoadRemoteScript(const nsString& aURL);
|
||||
virtual bool RecvAsyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON);
|
||||
const ClonedMessageData& aData);
|
||||
|
||||
virtual PDocumentRendererChild*
|
||||
AllocPDocumentRenderer(const nsRect& documentRect, const gfxMatrix& transform,
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "TabParent.h"
|
||||
|
||||
#include "Blob.h"
|
||||
#include "IDBFactory.h"
|
||||
#include "IndexedDBParent.h"
|
||||
#include "mozilla/BrowserElementParent.h"
|
||||
@ -42,8 +45,8 @@
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "StructuredCloneUtils.h"
|
||||
#include "TabChild.h"
|
||||
#include "TabParent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
@ -344,17 +347,51 @@ bool TabParent::SendRealTouchEvent(nsTouchEvent& event)
|
||||
|
||||
bool
|
||||
TabParent::RecvSyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
return ReceiveMessage(aMessage, true, aJSON, aJSONRetVal);
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobParent*>& blobParents = aData.blobsParent();
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
if (!blobParents.IsEmpty()) {
|
||||
PRUint32 length = blobParents.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobParent* blobParent = static_cast<BlobParent*>(blobParents[i]);
|
||||
MOZ_ASSERT(blobParent);
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobParent->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
return ReceiveMessage(aMessage, true, &cloneData, aJSONRetVal);
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvAsyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON)
|
||||
const ClonedMessageData& aData)
|
||||
{
|
||||
return ReceiveMessage(aMessage, false, aJSON, nullptr);
|
||||
const SerializedStructuredCloneBuffer& buffer = aData.data();
|
||||
const InfallibleTArray<PBlobParent*>& blobParents = aData.blobsParent();
|
||||
|
||||
StructuredCloneData cloneData;
|
||||
cloneData.mData = buffer.data;
|
||||
cloneData.mDataLength = buffer.dataLength;
|
||||
|
||||
if (!blobParents.IsEmpty()) {
|
||||
PRUint32 length = blobParents.Length();
|
||||
cloneData.mClosure.mBlobs.SetCapacity(length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
BlobParent* blobParent = static_cast<BlobParent*>(blobParents[i]);
|
||||
MOZ_ASSERT(blobParent);
|
||||
nsCOMPtr<nsIDOMBlob> blob = blobParent->GetBlob();
|
||||
MOZ_ASSERT(blob);
|
||||
cloneData.mClosure.mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
return ReceiveMessage(aMessage, false, &cloneData, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -697,7 +734,7 @@ TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
|
||||
bool
|
||||
TabParent::ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
const nsString& aJSON,
|
||||
const StructuredCloneData* aCloneData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
@ -717,7 +754,7 @@ TabParent::ReceiveMessage(const nsString& aMessage,
|
||||
manager->ReceiveMessage(mFrameElement,
|
||||
aMessage,
|
||||
aSync,
|
||||
aJSON,
|
||||
aCloneData,
|
||||
objectsArray,
|
||||
aJSONRetVal);
|
||||
}
|
||||
@ -758,9 +795,13 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
||||
nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow();
|
||||
NS_ENSURE_TRUE(window, false);
|
||||
|
||||
ContentParent* contentParent = static_cast<ContentParent*>(Manager());
|
||||
NS_ASSERTION(contentParent, "Null manager?!");
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv =
|
||||
IDBFactory::Create(window, aASCIIOrigin, getter_AddRefs(factory));
|
||||
IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
||||
getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!factory) {
|
||||
|
@ -40,6 +40,9 @@ class RenderFrameParent;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class ClonedMessageData;
|
||||
struct StructuredCloneData;
|
||||
|
||||
class ContentDialogParent : public PContentDialogParent {};
|
||||
|
||||
class TabParent : public PBrowserParent
|
||||
@ -47,6 +50,8 @@ class TabParent : public PBrowserParent
|
||||
, public nsIAuthPromptProvider
|
||||
, public nsISecureBrowserUI
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
TabParent();
|
||||
virtual ~TabParent();
|
||||
@ -68,10 +73,10 @@ public:
|
||||
bool* aOutWindowOpened);
|
||||
virtual bool AnswerCreateWindow(PBrowserParent** retval);
|
||||
virtual bool RecvSyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal);
|
||||
virtual bool RecvAsyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON);
|
||||
const ClonedMessageData& aData);
|
||||
virtual bool RecvNotifyIMEFocus(const bool& aFocus,
|
||||
nsIMEUpdatePreference* aPreference,
|
||||
PRUint32* aSeqno);
|
||||
@ -172,7 +177,7 @@ public:
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
const nsString& aJSON,
|
||||
const StructuredCloneData* aCloneData,
|
||||
InfallibleTArray<nsString>* aJSONRetVal = nullptr);
|
||||
|
||||
virtual bool Recv__delete__() MOZ_OVERRIDE;
|
||||
|
@ -3,7 +3,10 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
IPDLSRCS = \
|
||||
DOMTypes.ipdlh \
|
||||
PAudio.ipdl \
|
||||
PBlob.ipdl \
|
||||
PBlobStream.ipdl \
|
||||
PBrowser.ipdl \
|
||||
PContent.ipdl \
|
||||
PContentDialog.ipdl \
|
||||
|
28
dom/ipc/nsIRemoteBlob.h
Normal file
28
dom/ipc/nsIRemoteBlob.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* 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_ipc_nsIRemoteBlob_h
|
||||
#define mozilla_dom_ipc_nsIRemoteBlob_h
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
#ifndef NS_NO_VTABLE
|
||||
#define NS_NO_VTABLE
|
||||
#endif
|
||||
|
||||
#define NS_IREMOTEBLOB_IID \
|
||||
{0x74ce3cdd, 0xbfc9, 0x4edb, {0x98, 0x26, 0x50, 0xcf, 0x00, 0x26, 0x58, 0x70}}
|
||||
|
||||
class NS_NO_VTABLE nsIRemoteBlob : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IREMOTEBLOB_IID)
|
||||
|
||||
// This will either return a PBlobChild or PBlobParent.
|
||||
virtual void* GetPBlob() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIRemoteBlob, NS_IREMOTEBLOB_IID)
|
||||
|
||||
#endif // mozilla_dom_ipc_nsIRemoteBlob_h
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user