import change from rmottola/Arctic-Fox:

- Bug 1141392 - Disallow a line break between ArrowParameters and the arrow. (386dac894)
- Bug 1138651 - Enable CSS Scroll Snapping by Default on B2G. (2e416be93)
- Bug 1140623 - Correct mochitest failures that occur when the layout.css.scroll-snap.enabled preference is enabled (V3 Patch). (cfb1ccd33)
- Bug 1136467 - ServiceWorker: client.postMessage should land in navigator.serviceWorker.onmessage. (547bc9d03)
- Bug 1137419 - Use correct principal for update. (9b409bd5c)
- Bug 1137408 - Use inner window to create ServiceWorker for Fetch Event (11958cf2b)
-  Bug 1137250 - Fix incorrect initialization of Request object. (ec637ee57)
-  Bug 1139990 - Remove No activatingWorker warning. (49154e967)
- Bug 1058311 - Update client interface. Implement matchAll WindowClient. (cde7ba62a)
- Bug 1131353 - Make ServiceWorkerGlobalScope.close() throw InvalidAccessError; (0ec3f45d9)
- Bug 1137816 - Add a test for interfaces exposed to service workers; (19b5f9504)
- Bug 1137816 follow-up: Add WindowClient, added by bug 1058311 (ce6f0ba73)
- Bug 1141274 - Allocate shared workers and service workers from separate namespaces; (776221d45)
- Bug 1133763 - Part 1: Remember the security info associated with HTTP fetches and record it inside InternalResponse; (fec70ad02)
- Bug 1133763 - Part 2: Transfer the security info associated with an InternalResponse across the IPC layer (e7192f129)
-  Bug 1133763 - Part 3: Wipe out the cache directory when detecting a change in the DB schema; (82d81819a)
- Bug 1133763 - Part 4: Store the response's security info in the cache database; (426e94e4b)
- Bug 1133763 - Part 5: Allow the security info on intercepted HTTP channels to be overridden (4d079bf92)
- Bug 1133763 - Part 6: Set the correct security info on intercepted channels when using the respondWith API (83e2b2a7d)
- Bug 1133763 - Part 7: Add automated tests for using FetchEvent.respondWith on an HTTPS request (e0ee10e17)
- Bug 1133763 - Part 8: Ensure that FetchEvent.respondWith works correctly on HTTPS requests with a cloned response (0db13351e)
- Bug 1139425 - Service Worker Client uuid tests. (480b262ed)
- Bug 1139425 - Service Worker Client id should return a DOMString uuid. (8b9ea176d)
- Bug 1142853 - Add caret resources to package-manifest.in. (7e1a59681)
This commit is contained in:
2019-06-18 19:45:21 +08:00
parent b33dced904
commit a6abc84e91
81 changed files with 2012 additions and 222 deletions
+3
View File
@@ -625,6 +625,9 @@ pref("ui.scrollbarFadeDuration", 200);
// Scrollbar position follows the document `dir` attribute
pref("layout.scrollbar.side", 1);
// CSS Scroll Snapping
pref("layout.css.scroll-snap.enabled", true);
// Enable the ProcessPriorityManager, and give processes with no visible
// documents a 1s grace period before they're eligible to be marked as
// background. Background processes that are perceivable due to playing
+12
View File
@@ -742,6 +742,18 @@
@RESPATH@/res/table-remove-row-active.gif
@RESPATH@/res/table-remove-row-hover.gif
@RESPATH@/res/table-remove-row.gif
@RESPATH@/res/text_caret.png
@RESPATH@/res/text_caret@1.5x.png
@RESPATH@/res/text_caret@2.25x.png
@RESPATH@/res/text_caret@2x.png
@RESPATH@/res/text_caret_tilt_left.png
@RESPATH@/res/text_caret_tilt_left@1.5x.png
@RESPATH@/res/text_caret_tilt_left@2.25x.png
@RESPATH@/res/text_caret_tilt_left@2x.png
@RESPATH@/res/text_caret_tilt_right.png
@RESPATH@/res/text_caret_tilt_right@1.5x.png
@RESPATH@/res/text_caret_tilt_right@2.25x.png
@RESPATH@/res/text_caret_tilt_right@2x.png
@RESPATH@/res/grabber.gif
#ifdef XP_MACOSX
@RESPATH@/res/cursors/*
+29
View File
@@ -12872,6 +12872,35 @@ nsIDocument::CreateHTMLElement(nsIAtom* aTag)
return element.forget();
}
nsresult
nsIDocument::GetId(nsAString& aId)
{
if (mId.IsEmpty()) {
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Build a string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format
char buffer[NSID_LENGTH];
id.ToProvidedString(buffer);
NS_ConvertASCIItoUTF16 uuid(buffer);
// Remove {} and the null terminator
mId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
}
aId = mId;
return NS_OK;
}
bool
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
{
+15
View File
@@ -671,6 +671,21 @@ public:
mCleanedUp);
}
bool
HadOriginalOpener() const
{
MOZ_ASSERT(IsOuterWindow());
return mHadOriginalOpener;
}
bool
IsTopLevelWindow()
{
MOZ_ASSERT(IsOuterWindow());
nsPIDOMWindow* parentWindow = GetScriptableTop();
return parentWindow == static_cast<nsPIDOMWindow*>(this);
}
virtual void
FirePopupBlockedEvent(nsIDocument* aDoc,
nsIURI* aPopupURI,
+5
View File
@@ -17,6 +17,8 @@
#include "nsINode.h" // for base class
#include "nsIPrincipal.h"
#include "nsIScriptGlobalObject.h" // for member (in nsCOMPtr)
#include "nsIServiceManager.h"
#include "nsIUUIDGenerator.h"
#include "nsIURI.h"
#include "nsPIDOMWindow.h" // for use in inline functions
#include "nsPropertyTable.h" // for member
@@ -770,6 +772,8 @@ public:
return mAnonymousContents;
}
nsresult GetId(nsAString& aId);
protected:
virtual Element *GetRootElementInternal() const = 0;
@@ -2852,6 +2856,7 @@ protected:
nsCOMPtr<nsIChannel> mChannel;
private:
nsCString mContentType;
nsString mId;
protected:
// The document's security info
+7 -5
View File
@@ -1935,15 +1935,15 @@ struct FakeString {
return reinterpret_cast<const nsString*>(this);
}
nsAString* ToAStringPtr() {
return reinterpret_cast<nsString*>(this);
}
operator const nsAString& () const {
operator const nsAString& () const {
return *reinterpret_cast<const nsString*>(this);
}
private:
nsAString* ToAStringPtr() {
return reinterpret_cast<nsString*>(this);
}
nsString::char_type* mData;
nsString::size_type mLength;
uint32_t mFlags;
@@ -1959,6 +1959,8 @@ private:
mData = const_cast<nsString::char_type*>(aData);
}
friend class NonNull<nsAString>;
// A class to use for our static asserts to ensure our object layout
// matches that of nsString.
class StringAsserter;
+5
View File
@@ -1270,6 +1270,11 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::TextTrackRegion',
},
'WindowClient': {
'nativeType': 'mozilla::dom::workers::ServiceWorkerWindowClient',
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerWindowClient.h',
},
'WebGLActiveInfo': {
'nativeType': 'mozilla::WebGLActiveInfo',
'headerFile': 'WebGLActiveInfo.h'
+37 -6
View File
@@ -14,6 +14,8 @@
#include "nsIFile.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "DBSchema.h"
#include "FileUtils.h"
namespace mozilla {
namespace dom {
@@ -75,6 +77,8 @@ DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
MOZ_ASSERT(aDBDir);
MOZ_ASSERT(aConnOut);
nsCOMPtr<mozIStorageConnection> conn;
bool exists;
nsresult rv = aDBDir->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@@ -123,21 +127,48 @@ DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
if (NS_WARN_IF(!ss)) { return NS_ERROR_UNEXPECTED; }
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, aConnOut);
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
if (rv == NS_ERROR_FILE_CORRUPTED) {
NS_WARNING("Cache database corrupted. Recreating empty database.");
conn = nullptr;
// There is nothing else we can do to recover. Also, this data can
// be deleted by QuotaManager at any time anyways.
rv = dbFile->Remove(false);
rv = WipeDatabase(dbFile, aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// TODO: clean up any orphaned body files (bug 1110446)
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, aConnOut);
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
MOZ_ASSERT(*aConnOut);
// Check the schema to make sure it is not too old.
int32_t schemaVersion = 0;
rv = conn->GetSchemaVersion(&schemaVersion);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (schemaVersion > 0 && schemaVersion < DBSchema::kMaxWipeSchemaVersion) {
conn = nullptr;
rv = WipeDatabase(dbFile, aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
}
conn.forget(aConnOut);
return rv;
}
nsresult
DBAction::WipeDatabase(nsIFile* aDBFile, nsIFile* aDBDir)
{
nsresult rv = aDBFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// Delete the morgue as well.
rv = FileUtils::BodyDeleteDir(aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
return rv;
}
+2
View File
@@ -49,6 +49,8 @@ private:
nsresult OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aQuotaDir,
mozIStorageConnection** aConnOut);
nsresult WipeDatabase(nsIFile* aDBFile, nsIFile* aDBDir);
const Mode mMode;
};
+20 -4
View File
@@ -20,7 +20,8 @@ namespace dom {
namespace cache {
const int32_t DBSchema::kLatestSchemaVersion = 1;
const int32_t DBSchema::kMaxWipeSchemaVersion = 2;
const int32_t DBSchema::kLatestSchemaVersion = 2;
const int32_t DBSchema::kMaxEntriesPerStatement = 255;
using mozilla::void_t;
@@ -96,6 +97,7 @@ DBSchema::CreateSchema(mozIStorageConnection* aConn)
"response_status_text TEXT NOT NULL, "
"response_headers_guard INTEGER NOT NULL, "
"response_body_id TEXT NULL, "
"response_security_info BLOB NULL, "
"cache_id INTEGER NOT NULL REFERENCES caches(id) ON DELETE CASCADE"
");"
));
@@ -938,8 +940,9 @@ DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"response_status_text, "
"response_headers_guard, "
"response_body_id, "
"response_security_info, "
"cache_id "
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)"
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16)"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@@ -988,7 +991,12 @@ DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
rv = BindId(state, 13, aResponseBodyId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(14, aCacheId);
rv = state->BindBlobParameter(14, reinterpret_cast<const uint8_t*>
(aResponse.securityInfo().get()),
aResponse.securityInfo().Length());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(15, aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@@ -1075,7 +1083,8 @@ DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"response_status, "
"response_status_text, "
"response_headers_guard, "
"response_body_id "
"response_body_id, "
"response_security_info "
"FROM entries "
"WHERE id=?1;"
), getter_AddRefs(state));
@@ -1120,6 +1129,13 @@ DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
uint8_t* data = nullptr;
uint32_t dataLength = 0;
rv = state->GetBlob(6, &dataLength, &data);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
aSavedResponseOut->mValue.securityInfo().Adopt(
reinterpret_cast<char*>(data), dataLength);
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT "
"name, "
+3
View File
@@ -89,6 +89,9 @@ public:
Namespace aNamespace,
nsTArray<nsString>& aKeysOut);
// We will wipe out databases with a schema versions less than this.
static const int32_t kMaxWipeSchemaVersion;
private:
typedef int32_t EntryId;
+23
View File
@@ -47,6 +47,29 @@ FileUtils::BodyCreateDir(nsIFile* aBaseDir)
return rv;
}
// static
nsresult
FileUtils::BodyDeleteDir(nsIFile* aBaseDir)
{
MOZ_ASSERT(aBaseDir);
nsCOMPtr<nsIFile> aBodyDir;
nsresult rv = aBaseDir->Clone(getter_AddRefs(aBodyDir));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = aBodyDir->Append(NS_LITERAL_STRING("morgue"));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = aBodyDir->Remove(/* recursive = */ true);
if (rv == NS_ERROR_FILE_NOT_FOUND ||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
rv = NS_OK;
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
return rv;
}
// static
nsresult
FileUtils::BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId,
+4
View File
@@ -30,6 +30,10 @@ public:
};
static nsresult BodyCreateDir(nsIFile* aBaseDir);
// Note that this function can only be used during the initialization of the
// database. We're unlikely to be able to delete the DB successfully past
// that point due to the file being in use.
static nsresult BodyDeleteDir(nsIFile* aBaseDir);
static nsresult BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId,
nsIFile** aCacheDirOut);
+1
View File
@@ -70,6 +70,7 @@ struct PCacheResponse
PHeadersEntry[] headers;
HeadersGuardEnum headersGuard;
PCacheReadStreamOrVoid body;
nsCString securityInfo;
};
union PCacheResponseOrVoid
+3
View File
@@ -233,6 +233,7 @@ TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut,
MOZ_ASSERT(headers);
headers->GetPHeaders(aOut.headers());
aOut.headersGuard() = headers->Guard();
aOut.securityInfo() = aIn.GetSecurityInfo();
}
void
@@ -319,6 +320,8 @@ TypeUtils::ToResponse(const PCacheResponse& aIn)
ir->Headers()->Fill(*internalHeaders, result);
MOZ_ASSERT(!result.Failed());
ir->SetSecurityInfo(aIn.securityInfo());
nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
ir->SetBody(stream);
+6
View File
@@ -665,6 +665,12 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
mResponse = BeginAndGetFilteredResponse(response);
nsCOMPtr<nsISupports> securityInfo;
rv = channel->GetSecurityInfo(getter_AddRefs(securityInfo));
if (securityInfo) {
mResponse->SetSecurityInfo(securityInfo);
}
// We open a pipe so that we can immediately set the pipe's read end as the
// response's body. Setting the segment size to UINT32_MAX means that the
// pipe has infinite space. The nsIChannel will continue to buffer data in
+21
View File
@@ -9,6 +9,7 @@
#include "mozilla/dom/InternalHeaders.h"
#include "nsStreamUtils.h"
#include "nsSerializationHelper.h"
namespace mozilla {
namespace dom {
@@ -32,6 +33,7 @@ InternalResponse::InternalResponse(const InternalResponse& aOther)
, mStatus(aOther.mStatus)
, mStatusText(aOther.mStatusText)
, mContentType(aOther.mContentType)
, mSecurityInfo(aOther.mSecurityInfo)
{
}
@@ -84,5 +86,24 @@ InternalResponse::CORSResponse(InternalResponse* aInner)
return cors.forget();
}
void
InternalResponse::SetSecurityInfo(nsISupports* aSecurityInfo)
{
MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aSecurityInfo);
if (!serializable) {
NS_WARNING("A non-serializable object was passed to InternalResponse::SetSecurityInfo");
return;
}
NS_SerializeToString(serializable, mSecurityInfo);
}
void
InternalResponse::SetSecurityInfo(const nsCString& aSecurityInfo)
{
MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
mSecurityInfo = aSecurityInfo;
}
} // namespace dom
} // namespace mozilla
+13
View File
@@ -123,6 +123,18 @@ public:
mBody = aBody;
}
const nsCString&
GetSecurityInfo() const
{
return mSecurityInfo;
}
void
SetSecurityInfo(nsISupports* aSecurityInfo);
void
SetSecurityInfo(const nsCString& aSecurityInfo);
private:
~InternalResponse()
{ }
@@ -140,6 +152,7 @@ private:
nsRefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBody;
nsCString mContentType;
nsCString mSecurityInfo;
};
} // namespace dom
+17 -1
View File
@@ -10,8 +10,24 @@
[Exposed=ServiceWorker]
interface Client {
readonly attribute unsigned long id;
readonly attribute DOMString id;
readonly attribute USVString url;
[Throws]
void postMessage(any message, optional sequence<Transferable> transfer);
};
[Exposed=ServiceWorker]
interface WindowClient : Client {
readonly attribute VisibilityState visibilityState;
readonly attribute boolean focused;
readonly attribute FrameType frameType;
Promise<WindowClient> focus();
};
enum FrameType {
"auxiliary",
"top-level",
"nested",
"none"
};
+3 -2
View File
@@ -10,10 +10,11 @@
[Exposed=ServiceWorker]
interface Clients {
// A list of client objects, identifiable by ID, that correspond to windows
// (or workers) that are "controlled" by this SW
// The objects returned will be new instances every time
[Throws]
Promise<sequence<Client>?> matchAll(optional ClientQueryOptions options);
Promise<WindowClient> openWindow(USVString url);
Promise<void> claim();
};
dictionary ClientQueryOptions {
+3 -1
View File
@@ -12,7 +12,9 @@
Exposed=(ServiceWorker)]
interface FetchEvent : Event {
readonly attribute Request request;
readonly attribute Client client; // The window issuing the request.
// https://github.com/slightlyoff/ServiceWorker/issues/631
readonly attribute Client? client; // The window issuing the request.
readonly attribute boolean isReload;
[Throws] void respondWith(Promise<Response> r);
+1
View File
@@ -32,6 +32,7 @@ interface ServiceWorkerContainer : EventTarget {
attribute EventHandler oncontrollerchange;
attribute EventHandler onreloadpage;
attribute EventHandler onerror;
attribute EventHandler onmessage;
};
// Testing only.
@@ -36,10 +36,6 @@ interface ServiceWorkerGlobalScope : WorkerGlobalScope {
// The event.source of these MessageEvents are instances of Client
attribute EventHandler onmessage;
// close() method inherited from WorkerGlobalScope is not exposed.
// FIXME(nsm): For now, overridden so it can be a no-op.
void close();
};
+1
View File
@@ -22,6 +22,7 @@ interface WorkerGlobalScope : EventTarget {
readonly attribute WorkerLocation location;
[Throws]
void close();
attribute OnErrorEventHandler onerror;
+19 -7
View File
@@ -267,14 +267,23 @@ GetWorkerPref(const nsACString& aPref,
return result;
}
// This function creates a key for a SharedWorker composed by "name|scriptSpec".
// This function creates a key for a SharedWorker composed by "shared|name|scriptSpec"
// and a key for a ServiceWorker composed by "service|scope|scriptSpec".
// If the name contains a '|', this will be replaced by '||'.
void
GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName,
nsCString& aKey)
WorkerType aWorkerType, nsCString& aKey)
{
aKey.Truncate();
aKey.SetCapacity(aScriptSpec.Length() + aName.Length() + 1);
NS_NAMED_LITERAL_CSTRING(sharedPrefix, "shared|");
NS_NAMED_LITERAL_CSTRING(servicePrefix, "service|");
MOZ_ASSERT(servicePrefix.Length() > sharedPrefix.Length());
MOZ_ASSERT(aWorkerType == WorkerTypeShared ||
aWorkerType == WorkerTypeService);
aKey.SetCapacity(servicePrefix.Length() + aScriptSpec.Length() +
aName.Length() + 1);
aKey.Append(aWorkerType == WorkerTypeService ? servicePrefix : sharedPrefix);
nsACString::const_iterator start, end;
aName.BeginReading(start);
@@ -1457,7 +1466,8 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
const nsCString& sharedWorkerName = aWorkerPrivate->SharedWorkerName();
nsAutoCString key;
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName, key);
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName,
aWorkerPrivate->Type(), key);
MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key));
SharedWorkerInfo* sharedWorkerInfo =
@@ -1562,7 +1572,8 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
if (match.mSharedWorkerInfo) {
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
match.mSharedWorkerInfo->mName,
aWorkerPrivate->Type(), key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}
@@ -2354,7 +2365,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString key;
GenerateSharedWorkerKey(scriptSpec, aName, key);
GenerateSharedWorkerKey(scriptSpec, aName, aType, key);
if (mDomainMap.Get(aLoadInfo->mDomain, &domainInfo) &&
domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) {
@@ -2429,7 +2440,8 @@ RuntimeService::ForgetSharedWorker(WorkerPrivate* aWorkerPrivate)
if (match.mSharedWorkerInfo) {
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
match.mSharedWorkerInfo->mName,
aWorkerPrivate->Type(), key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}
+48 -11
View File
@@ -5,13 +5,13 @@
*/
#include "ServiceWorkerClient.h"
#include "ServiceWorkerContainer.h"
#include "mozilla/dom/MessageEvent.h"
#include "nsGlobalWindow.h"
#include "nsIDocument.h"
#include "WorkerPrivate.h"
#include "mozilla/dom/ClientBinding.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
@@ -26,6 +26,36 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
{
MOZ_ASSERT(aDoc);
MOZ_ASSERT(aDoc->GetWindow());
nsresult rv = aDoc->GetId(mClientId);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get the UUID of the document.");
}
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
mWindowId = outerWindow->WindowID();
aDoc->GetURL(mUrl);
mVisibilityState = aDoc->VisibilityState();
ErrorResult result;
mFocused = aDoc->HasFocus(result);
if (result.Failed()) {
NS_WARNING("Failed to get focus information.");
}
if (!outerWindow->IsTopLevelWindow()) {
mFrameType = FrameType::Nested;
} else if (outerWindow->HadOriginalOpener()) {
mFrameType = FrameType::Auxiliary;
} else {
mFrameType = FrameType::Top_level;
}
}
JSObject*
ServiceWorkerClient::WrapObject(JSContext* aCx)
{
@@ -36,15 +66,15 @@ namespace {
class ServiceWorkerClientPostMessageRunnable final : public nsRunnable
{
uint64_t mId;
uint64_t mWindowId;
JSAutoStructuredCloneBuffer mBuffer;
nsTArray<nsCOMPtr<nsISupports>> mClonedObjects;
public:
ServiceWorkerClientPostMessageRunnable(uint64_t aId,
ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId,
JSAutoStructuredCloneBuffer&& aData,
nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
: mId(aId),
: mWindowId(aWindowId),
mBuffer(Move(aData))
{
mClonedObjects.SwapElements(aClonedObjects);
@@ -54,21 +84,28 @@ public:
Run()
{
AssertIsOnMainThread();
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mId);
nsGlobalWindow* window = nsGlobalWindow::GetOuterWindowWithId(mWindowId);
if (!window) {
return NS_ERROR_FAILURE;
}
ErrorResult result;
dom::Navigator* navigator = window->GetNavigator(result);
if (NS_WARN_IF(result.Failed())) {
return result.ErrorCode();
}
nsRefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
AutoJSAPI jsapi;
jsapi.Init(window);
JSContext* cx = jsapi.cx();
return DispatchDOMEvent(cx, window);
return DispatchDOMEvent(cx, container);
}
private:
NS_IMETHOD
DispatchDOMEvent(JSContext* aCx, nsGlobalWindow* aTargetWindow)
DispatchDOMEvent(JSContext* aCx, ServiceWorkerContainer* aTargetContainer)
{
AssertIsOnMainThread();
@@ -84,7 +121,7 @@ private:
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMMessageEvent> event = new MessageEvent(aTargetWindow,
nsCOMPtr<nsIDOMMessageEvent> event = new MessageEvent(aTargetContainer,
nullptr, nullptr);
nsresult rv =
event->InitMessageEvent(NS_LITERAL_STRING("message"),
@@ -101,7 +138,7 @@ private:
event->SetTrusted(true);
bool status = false;
aTargetWindow->DispatchEvent(event, &status);
aTargetContainer->DispatchEvent(event, &status);
if (!status) {
return NS_ERROR_FAILURE;
@@ -150,7 +187,7 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
}
nsRefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
new ServiceWorkerClientPostMessageRunnable(mId, Move(buffer), clonedObjects);
new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer), clonedObjects);
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_FAILURE);
+57 -17
View File
@@ -11,47 +11,87 @@
#include "nsWrapperCache.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ClientBinding.h"
namespace mozilla {
namespace dom {
namespace workers {
class ServiceWorkerClient final : public nsISupports,
public nsWrapperCache
class ServiceWorkerClient;
class ServiceWorkerWindowClient;
// Used as a container object for information needed to create
// client objects.
class ServiceWorkerClientInfo MOZ_FINAL
{
friend class ServiceWorkerClient;
friend class ServiceWorkerWindowClient;
public:
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
private:
nsString mClientId;
uint64_t mWindowId;
nsString mUrl;
// Window Clients
VisibilityState mVisibilityState;
bool mFocused;
FrameType mFrameType;
};
class ServiceWorkerClient : public nsISupports,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClient)
ServiceWorkerClient(nsISupports* aOwner, uint64_t aId)
ServiceWorkerClient(nsISupports* aOwner,
const ServiceWorkerClientInfo& aClientInfo)
: mOwner(aOwner),
mId(aId)
mId(aClientInfo.mClientId),
mWindowId(aClientInfo.mWindowId),
mUrl(aClientInfo.mUrl)
{
MOZ_ASSERT(aOwner);
}
uint32_t Id() const
{
return mId;
}
nsISupports* GetParentObject() const
nsISupports*
GetParentObject() const
{
return mOwner;
}
void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv);
void GetId(nsString& aRetval) const
{
aRetval = mId;
}
void
GetUrl(nsAString& aUrl) const
{
aUrl.Assign(mUrl);
}
void
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv);
JSObject* WrapObject(JSContext* aCx) override;
private:
~ServiceWorkerClient()
{
}
protected:
virtual ~ServiceWorkerClient()
{ }
private:
nsCOMPtr<nsISupports> mOwner;
uint64_t mId;
nsString mId;
uint64_t mWindowId;
nsString mUrl;
};
} // namespace workers
+35 -8
View File
@@ -8,6 +8,7 @@
#include "ServiceWorkerClient.h"
#include "ServiceWorkerClients.h"
#include "ServiceWorkerManager.h"
#include "ServiceWorkerWindowClient.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@@ -122,17 +123,17 @@ private:
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
{
nsRefPtr<PromiseHolder> mPromiseHolder;
nsAutoPtr<nsTArray<uint64_t>> mValue;
nsTArray<ServiceWorkerClientInfo> mValue;
public:
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
PromiseHolder* aPromiseHolder,
nsAutoPtr<nsTArray<uint64_t>>& aValue)
nsTArray<ServiceWorkerClientInfo>& aValue)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mPromiseHolder(aPromiseHolder),
mValue(aValue)
mPromiseHolder(aPromiseHolder)
{
AssertIsOnMainThread();
mValue.SwapElements(aValue);
}
bool
@@ -145,10 +146,10 @@ public:
MOZ_ASSERT(promise);
nsTArray<nsRefPtr<ServiceWorkerClient>> ret;
for (size_t i = 0; i < mValue->Length(); i++) {
for (size_t i = 0; i < mValue.Length(); i++) {
ret.AppendElement(nsRefPtr<ServiceWorkerClient>(
new ServiceWorkerClient(promise->GetParentObject(),
mValue->ElementAt(i))));
new ServiceWorkerWindowClient(promise->GetParentObject(),
mValue.ElementAt(i))));
}
promise->MaybeResolve(ret);
@@ -216,7 +217,7 @@ public:
}
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsAutoPtr<nsTArray<uint64_t>> result(new nsTArray<uint64_t>());
nsTArray<ServiceWorkerClientInfo> result;
swm->GetAllClients(mScope, result);
nsRefPtr<ResolvePromiseWorkerRunnable> r =
@@ -282,3 +283,29 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
return promise.forget();
}
already_AddRefed<Promise>
ServiceWorkerClients::OpenWindow(const nsAString& aUrl)
{
ErrorResult result;
nsRefPtr<Promise> promise = Promise::Create(mWorkerScope, result);
if (NS_WARN_IF(result.Failed())) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
already_AddRefed<Promise>
ServiceWorkerClients::Claim()
{
ErrorResult result;
nsRefPtr<Promise> promise = Promise::Create(mWorkerScope, result);
if (NS_WARN_IF(result.Failed())) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
+6
View File
@@ -31,6 +31,12 @@ public:
already_AddRefed<Promise>
MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
already_AddRefed<Promise>
OpenWindow(const nsAString& aUrl);
already_AddRefed<Promise>
Claim();
JSObject*
WrapObject(JSContext* aCx) override;
+1
View File
@@ -31,6 +31,7 @@ public:
IMPL_EVENT_HANDLER(controllerchange)
IMPL_EVENT_HANDLER(reloadpage)
IMPL_EVENT_HANDLER(error)
IMPL_EVENT_HANDLER(message)
explicit ServiceWorkerContainer(nsPIDOMWindow* aWindow);
+35 -10
View File
@@ -14,6 +14,7 @@
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsNetCID.h"
#include "nsSerializationHelper.h"
#include "mozilla/dom/FetchEventBinding.h"
#include "mozilla/dom/PromiseNativeHandler.h"
@@ -28,7 +29,6 @@ BEGIN_WORKERS_NAMESPACE
FetchEvent::FetchEvent(EventTarget* aOwner)
: Event(aOwner, nullptr, nullptr)
, mWindowId(0)
, mIsReload(false)
, mWaitToRespond(false)
{
@@ -41,11 +41,11 @@ FetchEvent::~FetchEvent()
void
FetchEvent::PostInit(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
uint64_t aWindowId)
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo)
{
mChannel = aChannel;
mServiceWorker = aServiceWorker;
mWindowId = aWindowId;
mClientInfo = aClientInfo;
}
/*static*/ already_AddRefed<FetchEvent>
@@ -92,9 +92,12 @@ public:
class FinishResponse final : public nsRunnable
{
nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
nsRefPtr<InternalResponse> mInternalResponse;
public:
explicit FinishResponse(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel)
FinishResponse(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
InternalResponse* aInternalResponse)
: mChannel(aChannel)
, mInternalResponse(aInternalResponse)
{
}
@@ -102,7 +105,17 @@ public:
Run()
{
AssertIsOnMainThread();
nsresult rv = mChannel->FinishSynthesizedResponse();
nsCOMPtr<nsISupports> infoObj;
nsresult rv = NS_DeserializeObject(mInternalResponse->GetSecurityInfo(), getter_AddRefs(infoObj));
if (NS_SUCCEEDED(rv)) {
rv = mChannel->SetSecurityInfo(infoObj);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
rv = mChannel->FinishSynthesizedResponse();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to finish synthesized response");
return rv;
}
@@ -130,9 +143,12 @@ public:
struct RespondWithClosure
{
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
nsRefPtr<InternalResponse> mInternalResponse;
explicit RespondWithClosure(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel)
RespondWithClosure(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
InternalResponse* aInternalResponse)
: mInterceptedChannel(aChannel)
, mInternalResponse(aInternalResponse)
{
}
};
@@ -142,7 +158,7 @@ void RespondWithCopyComplete(void* aClosure, nsresult aStatus)
nsAutoPtr<RespondWithClosure> data(static_cast<RespondWithClosure*>(aClosure));
nsCOMPtr<nsIRunnable> event;
if (NS_SUCCEEDED(aStatus)) {
event = new FinishResponse(data->mInterceptedChannel);
event = new FinishResponse(data->mInterceptedChannel, data->mInternalResponse);
} else {
event = new CancelChannelRunnable(data->mInterceptedChannel);
}
@@ -187,6 +203,11 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
return;
}
nsRefPtr<InternalResponse> ir = response->GetInternalResponse();
if (NS_WARN_IF(!ir)) {
return;
}
nsCOMPtr<nsIInputStream> body;
response->GetBody(getter_AddRefs(body));
if (NS_WARN_IF(!body) || NS_WARN_IF(response->BodyUsed())) {
@@ -200,7 +221,7 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
return;
}
nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel));
nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel, ir));
nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(!stsThread)) {
@@ -244,10 +265,14 @@ FetchEvent::RespondWith(Promise& aPromise, ErrorResult& aRv)
}
already_AddRefed<ServiceWorkerClient>
FetchEvent::Client()
FetchEvent::GetClient()
{
if (!mClient) {
mClient = new ServiceWorkerClient(GetParentObject(), mWindowId);
if (!mClientInfo) {
return nullptr;
}
mClient = new ServiceWorkerClient(GetParentObject(), *mClientInfo);
}
nsRefPtr<ServiceWorkerClient> client = mClient;
return client.forget();
+3 -3
View File
@@ -32,7 +32,7 @@ class FetchEvent final : public Event
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
nsRefPtr<ServiceWorkerClient> mClient;
nsRefPtr<Request> mRequest;
uint64_t mWindowId;
nsAutoPtr<ServiceWorkerClientInfo> mClientInfo;
bool mIsReload;
bool mWaitToRespond;
protected:
@@ -51,7 +51,7 @@ public:
void PostInit(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
uint64_t aWindowId);
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo);
static already_AddRefed<FetchEvent>
Constructor(const GlobalObject& aGlobal,
@@ -72,7 +72,7 @@ public:
}
already_AddRefed<ServiceWorkerClient>
Client();
GetClient();
bool
IsReload() const
+23 -25
View File
@@ -691,18 +691,10 @@ private:
return Fail(rv);
}
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
rv = ssm->GetNoAppCodebasePrincipal(uri, getter_AddRefs(principal));
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(rv);
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
uri,
principal,
mPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT); // FIXME(nsm): TYPE_SERVICEWORKER
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1121,7 +1113,6 @@ ServiceWorkerRegistrationInfo::Activate()
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::WAITING_WORKER | WhichServiceWorker::ACTIVE_WORKER);
if (!activatingWorker) {
NS_WARNING("No activatingWorker!");
return;
}
@@ -2134,7 +2125,7 @@ class FetchEventRunnable : public WorkerRunnable
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
nsTArray<nsCString> mHeaderNames;
nsTArray<nsCString> mHeaderValues;
uint64_t mWindowId;
nsAutoPtr<ServiceWorkerClientInfo> mClientInfo;
nsCString mSpec;
nsCString mMethod;
bool mIsReload;
@@ -2142,11 +2133,11 @@ public:
FetchEventRunnable(WorkerPrivate* aWorkerPrivate,
nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
uint64_t aWindowId)
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
, mInterceptedChannel(aChannel)
, mServiceWorker(aServiceWorker)
, mWindowId(aWindowId)
, mClientInfo(aClientInfo)
{
MOZ_ASSERT(aWorkerPrivate);
}
@@ -2229,8 +2220,9 @@ private:
MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper());
NS_ConvertUTF8toUTF16 local(mSpec);
RequestOrUSVString requestInfo;
*requestInfo.SetAsUSVString().ToAStringPtr() = NS_ConvertUTF8toUTF16(mSpec);
requestInfo.SetAsUSVString().Rebind(local.Data(), local.Length());
RootedDictionary<RequestInit> reqInit(aCx);
reqInit.mMethod.Construct(mMethod);
@@ -2270,7 +2262,7 @@ private:
return false;
}
event->PostInit(mInterceptedChannel, mServiceWorker, mWindowId);
event->PostInit(mInterceptedChannel, mServiceWorker, mClientInfo);
event->SetTrusted(true);
nsRefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
@@ -2295,9 +2287,12 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
nsresult rv = aChannel->GetIsNavigation(&isNavigation);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoPtr<ServiceWorkerClientInfo> clientInfo;
if (!isNavigation) {
MOZ_ASSERT(aDoc);
rv = GetDocumentController(aDoc->GetWindow(), getter_AddRefs(serviceWorker));
rv = GetDocumentController(aDoc->GetInnerWindow(), getter_AddRefs(serviceWorker));
clientInfo = new ServiceWorkerClientInfo(aDoc);
} else {
nsCOMPtr<nsIChannel> internalChannel;
rv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@@ -2328,14 +2323,13 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
nsMainThreadPtrHandle<nsIInterceptedChannel> handle(
new nsMainThreadPtrHolder<nsIInterceptedChannel>(aChannel, false));
uint64_t windowId = aDoc ? aDoc->GetInnerWindow()->WindowID() : 0;
nsRefPtr<ServiceWorker> sw = static_cast<ServiceWorker*>(serviceWorker.get());
nsMainThreadPtrHandle<ServiceWorker> serviceWorkerHandle(
new nsMainThreadPtrHolder<ServiceWorker>(sw));
// clientInfo is null if we don't have a controlled document
nsRefPtr<FetchEventRunnable> event =
new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle, windowId);
new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle, clientInfo);
rv = event->Init();
NS_ENSURE_SUCCESS(rv, rv);
@@ -2563,14 +2557,14 @@ namespace {
class MOZ_STACK_CLASS FilterRegistrationData
{
public:
FilterRegistrationData(nsTArray<uint64_t>* aDocuments,
ServiceWorkerRegistrationInfo* aRegistration)
FilterRegistrationData(nsTArray<ServiceWorkerClientInfo>& aDocuments,
ServiceWorkerRegistrationInfo* aRegistration)
: mDocuments(aDocuments),
mRegistration(aRegistration)
{
}
nsTArray<uint64_t>* mDocuments;
nsTArray<ServiceWorkerClientInfo>& mDocuments;
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
};
@@ -2583,12 +2577,16 @@ EnumControlledDocuments(nsISupports* aKey,
if (data->mRegistration != aRegistration) {
return PL_DHASH_NEXT;
}
nsCOMPtr<nsIDocument> document = do_QueryInterface(aKey);
if (!document || !document->GetInnerWindow()) {
if (!document || !document->GetWindow()) {
return PL_DHASH_NEXT;
}
data->mDocuments->AppendElement(document->GetInnerWindow()->WindowID());
ServiceWorkerClientInfo clientInfo(document);
data->mDocuments.AppendElement(clientInfo);
return PL_DHASH_NEXT;
}
@@ -2635,7 +2633,7 @@ FireControllerChangeOnMatchingDocument(nsISupports* aKey,
void
ServiceWorkerManager::GetAllClients(const nsCString& aScope,
nsTArray<uint64_t>* aControlledDocuments)
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments)
{
nsRefPtr<ServiceWorkerRegistrationInfo> registration = GetRegistration(aScope);
+2 -1
View File
@@ -43,6 +43,7 @@ class ServiceWorkerRegistration;
namespace workers {
class ServiceWorker;
class ServiceWorkerClientInfo;
class ServiceWorkerInfo;
class ServiceWorkerJobQueue;
@@ -381,7 +382,7 @@ public:
void
GetAllClients(const nsCString& aScope,
nsTArray<uint64_t>* aControlledDocuments);
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments);
static already_AddRefed<ServiceWorkerManager>
GetInstance();
+34
View File
@@ -0,0 +1,34 @@
/* -*- 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 "ServiceWorkerWindowClient.h"
#include "mozilla/dom/ClientBinding.h"
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
JSObject*
ServiceWorkerWindowClient::WrapObject(JSContext* aCx)
{
return WindowClientBinding::Wrap(aCx, this);
}
already_AddRefed<Promise>
ServiceWorkerWindowClient::Focus() const
{
ErrorResult result;
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, result);
if (NS_WARN_IF(result.Failed())) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
+65
View File
@@ -0,0 +1,65 @@
/* -*- 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/.
*/
#ifndef mozilla_dom_workers_serviceworkerwindowclient_h
#define mozilla_dom_workers_serviceworkerwindowclient_h
#include "ServiceWorkerClient.h"
namespace mozilla {
namespace dom {
namespace workers {
class ServiceWorkerWindowClient MOZ_FINAL : public ServiceWorkerClient
{
public:
ServiceWorkerWindowClient(nsISupports* aOwner,
const ServiceWorkerClientInfo& aClientInfo)
: ServiceWorkerClient(aOwner, aClientInfo),
mVisibilityState(aClientInfo.mVisibilityState),
mFocused(aClientInfo.mFocused),
mFrameType(aClientInfo.mFrameType)
{
}
virtual JSObject*
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
mozilla::dom::VisibilityState
VisibilityState() const
{
return mVisibilityState;
}
bool
Focused() const
{
return mFocused;
}
mozilla::dom::FrameType
FrameType() const
{
return mFrameType;
}
already_AddRefed<Promise>
Focus() const;
private:
~ServiceWorkerWindowClient()
{ }
mozilla::dom::VisibilityState mVisibilityState;
bool mFocused;
mozilla::dom::FrameType mFrameType;
};
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_workers_serviceworkerwindowclient_h
+6 -2
View File
@@ -171,11 +171,15 @@ WorkerGlobalScope::GetExistingNavigator() const
}
void
WorkerGlobalScope::Close(JSContext* aCx)
WorkerGlobalScope::Close(JSContext* aCx, ErrorResult& aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->CloseInternal(aCx);
if (mWorkerPrivate->IsServiceWorker()) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
} else {
mWorkerPrivate->CloseInternal(aCx);
}
}
OnErrorEventHandlerNonNull*
+1 -7
View File
@@ -98,7 +98,7 @@ public:
GetExistingNavigator() const;
void
Close(JSContext* aCx);
Close(JSContext* aCx, ErrorResult& aRv);
OnErrorEventHandlerNonNull*
GetOnerror();
@@ -218,12 +218,6 @@ public:
aScope = mScope;
}
void
Close() const
{
// no-op close.
}
void
Update();
+2
View File
@@ -34,6 +34,7 @@ EXPORTS.mozilla.dom.workers.bindings += [
'ServiceWorker.h',
'ServiceWorkerClient.h',
'ServiceWorkerClients.h',
'ServiceWorkerWindowClient.h',
'SharedWorker.h',
'URL.h',
'WorkerFeature.h',
@@ -69,6 +70,7 @@ UNIFIED_SOURCES += [
'ServiceWorkerManager.cpp',
'ServiceWorkerRegistrar.cpp',
'ServiceWorkerRegistration.cpp',
'ServiceWorkerWindowClient.cpp',
'SharedWorker.cpp',
'URL.cpp',
'WorkerDebuggerManager.cpp',
@@ -0,0 +1,19 @@
function ok(v, msg) {
client.postMessage({status: "ok", result: !!v, message: msg});
}
var client;
onmessage = function(e) {
if (e.data.message == "start") {
self.clients.matchAll().then(function(clients) {
client = clients[0];
try {
close();
ok(false, "close() should throw");
} catch (e) {
ok(e.name === "InvalidAccessError", "close() should throw InvalidAccessError");
}
client.postMessage({status: "done"});
});
}
}
@@ -0,0 +1,15 @@
self.addEventListener("install", function(event) {
event.waitUntil(caches.open("cache").then(function(cache) {
return cache.add("index.html");
}));
});
self.addEventListener("fetch", function(event) {
if (event.request.url.indexOf("index.html") >= 0) {
event.respondWith(new Promise(function(resolve, reject) {
caches.match(event.request).then(function(response) {
resolve(response.clone());
});
}));
}
});
@@ -0,0 +1,4 @@
<!DOCTYPE html>
<script>
window.parent.postMessage({status: "done"}, "*");
</script>
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<script>
function ok(v, msg) {
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
}
var isDone = false;
function done(reg) {
if (!isDone) {
ok(reg.waiting || reg.active, "Either active or waiting worker should be available.");
window.parent.postMessage({status: "registrationdone"}, "*");
isDone = true;
}
}
navigator.serviceWorker.register("https_test.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
done(registration);
};
} else {
done(registration);
}
});
</script>
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.getRegistration(".").then(function(registration) {
registration.unregister().then(function(success) {
if (success) {
window.parent.postMessage({status: "unregistrationdone"}, "*");
}
});
});
</script>
@@ -0,0 +1,11 @@
self.addEventListener("install", function(event) {
event.waitUntil(caches.open("cache").then(function(cache) {
return cache.add("index.html");
}));
});
self.addEventListener("fetch", function(event) {
if (event.request.url.indexOf("index.html") >= 0) {
event.respondWith(caches.match(event.request));
}
});
@@ -0,0 +1,4 @@
<!DOCTYPE html>
<script>
window.parent.postMessage({status: "done"}, "*");
</script>
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<script>
function ok(v, msg) {
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
}
var isDone = false;
function done(reg) {
if (!isDone) {
ok(reg.waiting || reg.active, "Either active or waiting worker should be available.");
window.parent.postMessage({status: "registrationdone"}, "*");
isDone = true;
}
}
navigator.serviceWorker.register("https_test.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
done(registration);
};
} else {
done(registration);
}
});
</script>
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.getRegistration(".").then(function(registration) {
registration.unregister().then(function(success) {
if (success) {
window.parent.postMessage({status: "unregistrationdone"}, "*");
}
});
});
</script>
@@ -0,0 +1,31 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1139425 - controlled page</title>
<script class="testbody" type="text/javascript">
var testWindow = parent;
if (opener) {
testWindow = opener;
}
window.onload = function() {
navigator.serviceWorker.ready.then(function(swr) {
swr.active.postMessage("Start");
});
}
navigator.serviceWorker.onmessage = function(msg) {
// worker message;
testWindow.postMessage(msg.data, "*");
window.close();
};
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,28 @@
onmessage = function(e) {
dump("MatchAllClientIdWorker:" + e.data + "\n");
var id = [];
var iterations = 5;
var counter = 0;
for (var i = 0; i < iterations; i++) {
self.clients.matchAll().then(function(res) {
if (!res.length) {
dump("ERROR: no clients are currently controlled.\n");
}
client = res[0];
id[counter] = client.id;
counter++;
if (counter >= iterations) {
var response = true;
for (var index = 1; index < iterations; index++) {
if (id[0] != id[index]) {
response = false;
break;
}
}
client.postMessage(response);
}
});
}
}
@@ -0,0 +1,65 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1058311 - controlled page</title>
<script class="testbody" type="text/javascript">
var re = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
var frameType = "none";
var testWindow = parent;
if (parent != window) {
frameType = "nested";
} else if (opener) {
frameType = "auxiliary";
testWindow = opener;
} else if (parent != window) {
frameType = "top-level";
} else {
postResult(false, "Unexpected frameType");
}
window.onload = function() {
navigator.serviceWorker.ready.then(function(swr) {
swr.active.postMessage("Start");
});
}
function postResult(result, msg) {
response = {
result: result,
message: msg
};
testWindow.postMessage(response, "*");
}
navigator.serviceWorker.onmessage = function(msg) {
// worker message;
result = re.test(msg.data.id);
postResult(result, "Client id test");
result = msg.data.url == window.location;
postResult(result, "Client url test");
result = msg.data.visibilityState === document.visibilityState;
postResult(result, "Client visibility test. expected=" +document.visibilityState);
result = msg.data.focused === document.hasFocus();
postResult(result, "Client focus test. expected=" + document.hasFocus());
result = msg.data.frameType === frameType;
postResult(result, "Client frameType test. expected=" + frameType);
postResult(true, "DONE");
window.close();
};
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,20 @@
onmessage = function(e) {
dump("MatchAllPropertiesWorker:" + e.data + "\n");
self.clients.matchAll().then(function(res) {
if (!res.length) {
dump("ERROR: no clients are currently controlled.\n");
}
for (i = 0; i < res.length; i++) {
client = res[i];
response = {
id: client.id,
url: client.url,
visibilityState: client.visibilityState,
focused: client.focused,
frameType: client.frameType
};
client.postMessage(response);
}
});
}
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.onmessage = function(e) {
window.parent.postMessage(e.data, "*");
};
</script>
@@ -24,11 +24,30 @@ support-files =
fetch/index.html
fetch/fetch_worker_script.js
fetch/fetch_tests.js
fetch/https/index.html
fetch/https/register.html
fetch/https/unregister.html
fetch/https/https_test.js
fetch/https/clonedresponse/index.html
fetch/https/clonedresponse/register.html
fetch/https/clonedresponse/unregister.html
fetch/https/clonedresponse/https_test.js
match_all_properties_worker.js
match_all_clients/match_all_controlled.html
test_serviceworker_interfaces.js
serviceworker_wrapper.js
message_receiver.html
close_test.js
serviceworker_not_sharedworker.js
match_all_client/match_all_client_id.html
match_all_client_id_worker.js
[test_unregister.html]
skip-if = true # Bug 1133805
[test_installation_simple.html]
[test_fetch_event.html]
[test_https_fetch.html]
[test_https_fetch_cloned_response.html]
[test_match_all.html]
[test_install_event.html]
[test_navigator.html]
@@ -40,3 +59,8 @@ skip-if = true # Bug 1133805
skip-if = true # Bug 1133805
[test_post_message.html]
[test_post_message_advanced.html]
[test_match_all_client_properties.html]
[test_close.html]
[test_serviceworker_interfaces.html]
[test_serviceworker_not_sharedworker.html]
[test_match_all_client_id.html]
@@ -0,0 +1,21 @@
function OnMessage(e)
{
if (e.data.msg == "whoareyou") {
if ("ServiceWorker" in self) {
self.clients.matchAll().then(function(clients) {
clients[0].postMessage({result: "serviceworker"});
});
} else {
port.postMessage({result: "sharedworker"});
}
}
};
var port;
onconnect = function(e) {
port = e.ports[0];
port.onmessage = OnMessage;
port.start();
};
onmessage = OnMessage;
@@ -0,0 +1,131 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
//
// ServiceWorker equivalent of worker_wrapper.js.
var client;
function ok(a, msg) {
dump("OK: " + !!a + " => " + a + ": " + msg + "\n");
client.postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
}
function is(a, b, msg) {
dump("IS: " + (a===b) + " => " + a + " | " + b + ": " + msg + "\n");
client.postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
}
function workerTestArrayEquals(a, b) {
if (!Array.isArray(a) || !Array.isArray(b) || a.length != b.length) {
return false;
}
for (var i = 0, n = a.length; i < n; ++i) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
function workerTestDone() {
client.postMessage({ type: 'finish' });
}
function workerTestGetPrefs(prefs, cb) {
addEventListener('message', function workerTestGetPrefsCB(e) {
if (e.data.type != 'returnPrefs' ||
!workerTestArrayEquals(prefs, e.data.prefs)) {
return;
}
removeEventListener('message', workerTestGetPrefsCB);
cb(e.data.result);
});
client.postMessage({
type: 'getPrefs',
prefs: prefs
});
}
function workerTestGetPermissions(permissions, cb) {
addEventListener('message', function workerTestGetPermissionsCB(e) {
if (e.data.type != 'returnPermissions' ||
!workerTestArrayEquals(permissions, e.data.permissions)) {
return;
}
removeEventListener('message', workerTestGetPermissionsCB);
cb(e.data.result);
});
client.postMessage({
type: 'getPermissions',
permissions: permissions
});
}
function workerTestGetVersion(cb) {
addEventListener('message', function workerTestGetVersionCB(e) {
if (e.data.type !== 'returnVersion') {
return;
}
removeEventListener('message', workerTestGetVersionCB);
cb(e.data.result);
});
client.postMessage({
type: 'getVersion'
});
}
function workerTestGetUserAgent(cb) {
addEventListener('message', function workerTestGetUserAgentCB(e) {
if (e.data.type !== 'returnUserAgent') {
return;
}
removeEventListener('message', workerTestGetUserAgentCB);
cb(e.data.result);
});
client.postMessage({
type: 'getUserAgent'
});
}
function workerTestGetOSCPU(cb) {
addEventListener('message', function workerTestGetOSCPUCB(e) {
if (e.data.type !== 'returnOSCPU') {
return;
}
removeEventListener('message', workerTestGetOSCPUCB);
cb(e.data.result);
});
client.postMessage({
type: 'getOSCPU'
});
}
function workerTestGetIsB2G(cb) {
addEventListener('message', function workerTestGetIsB2GCB(e) {
if (e.data.type !== 'returnIsB2G') {
return;
}
removeEventListener('message', workerTestGetIsB2GCB);
cb(e.data.result);
});
client.postMessage({
type: 'getIsB2G'
});
}
addEventListener('message', function workerWrapperOnMessage(e) {
removeEventListener('message', workerWrapperOnMessage);
var data = e.data;
self.clients.matchAll().then(function(clients) {
client = clients[0];
try {
importScripts(data.script);
} catch(e) {
client.postMessage({
type: 'status',
status: false,
msg: 'worker failed to import ' + data.script + "; error: " + e.message
});
}
});
});
@@ -26,7 +26,7 @@
});
}
window.onmessage = function(msg) {
navigator.serviceWorker.onmessage = function(msg) {
// forward message to the test page.
parent.postMessage(msg.data, "*");
};
@@ -0,0 +1,69 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1131353 - test WorkerGlobalScope.close() on service workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
navigator.serviceWorker.register("close_test.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
setupSW(registration);
e.target.onstatechange = null;
};
} else {
setupSW(registration);
}
});
function setupSW(registration) {
var worker = registration.waiting ||
registration.active;
var iframe = document.createElement("iframe");
iframe.src = "message_receiver.html";
iframe.onload = function() {
worker.postMessage({ message: "start" });
};
document.body.appendChild(iframe);
}
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "done") {
navigator.serviceWorker.getRegistration().then(function(registration) {
registration.unregister().then(function() {
SimpleTest.finish();
});
});
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>
@@ -0,0 +1,56 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1133763 - test fetch event in HTTPS origins</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/register.html";
var ios;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
ios.offline = true;
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/index.html";
} else if (e.data.status == "done") {
ios.offline = false;
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.fetch.enabled", true],
["dom.caches.enabled", true]
]}, runTest);
};
</script>
</pre>
</body>
</html>
@@ -0,0 +1,56 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1133763 - test fetch event in HTTPS origins with a cloned response</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/clonedresponse/register.html";
var ios;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
ios.offline = true;
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/clonedresponse/index.html";
} else if (e.data.status == "done") {
ios.offline = false;
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/clonedresponse/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.fetch.enabled", true],
["dom.caches.enabled", true]
]}, runTest);
};
</script>
</pre>
</body>
</html>
@@ -0,0 +1,86 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1058311 - Test matchAll client id </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var registration;
var clientURL = "match_all_client/match_all_client_id.html";
function start() {
return navigator.serviceWorker.register("match_all_client_id_worker.js",
{ scope: "./match_all_client/" })
.then((swr) => registration = swr);
}
function unregister() {
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
});
}
function getMessageListener() {
return new Promise(function(res, rej) {
window.onmessage = function(e) {
ok(e.data, "Same client id for multiple calls.");
if (!e.data) {
rej();
return;
}
info("DONE from: " + e.source);
res();
}
});
}
function testNestedWindow() {
var p = getMessageListener();
var content = document.getElementById("content");
ok(content, "Parent exists.");
iframe = document.createElement("iframe");
content.appendChild(iframe);
iframe.setAttribute('src', clientURL);
return p.then(() => content.removeChild(iframe));
}
function testAuxiliaryWindow() {
var p = getMessageListener();
var w = window.open(clientURL);
return p.then(() => w.close());
}
function runTest() {
info(window.opener == undefined);
start()
.then(testAuxiliaryWindow)
.then(testNestedWindow)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
</script>
</pre>
</body>
</html>
@@ -0,0 +1,93 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1058311 - Test matchAll clients properties </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var registration;
var clientURL = "match_all_clients/match_all_controlled.html";
function start() {
return navigator.serviceWorker.register("match_all_properties_worker.js",
{ scope: "./match_all_clients/" })
.then((swr) => registration = swr);
}
function unregister() {
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
});
}
function getMessageListener() {
return new Promise(function(res, rej) {
window.onmessage = function(e) {
if (e.data.message === undefined) {
info("rejecting promise");
rej();
return;
}
ok(e.data.result, e.data.message);
if (!e.data.result) {
rej();
}
if (e.data.message == "DONE") {
info("DONE from: " + e.source);
res();
}
}
});
}
function testNestedWindow() {
var p = getMessageListener();
var content = document.getElementById("content");
ok(content, "Parent exists.");
iframe = document.createElement("iframe");
content.appendChild(iframe);
iframe.setAttribute('src', clientURL);
return p.then(() => content.removeChild(iframe));
}
function testAuxiliaryWindow() {
var p = getMessageListener();
var w = window.open(clientURL);
return p.then(() => w.close());
}
function runTest() {
info("catalin");
info(window.opener == undefined);
start()
.then(testAuxiliaryWindow)
.then(testNestedWindow)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
</script>
</pre>
</body>
</html>
@@ -0,0 +1,113 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>Validate Interfaces Exposed to Service Workers</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" src="../worker_driver.js"></script>
</head>
<body>
<script class="testbody" type="text/javascript">
function setupSW(registration) {
var worker = registration.waiting ||
registration.active;
window.onmessage = function(event) {
if (event.data.type == 'finish') {
registration.unregister().then(function(success) {
ok(success, "The service worker should be unregistered successfully");
SimpleTest.finish();
});
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
} else if (event.data.type == 'getPrefs') {
var result = {};
event.data.prefs.forEach(function(pref) {
result[pref] = SpecialPowers.Services.prefs.getBoolPref(pref);
});
worker.postMessage({
type: 'returnPrefs',
prefs: event.data.prefs,
result: result
});
} else if (event.data.type == 'getPermissions') {
var result = {};
event.data.permissions.forEach(function(permission) {
result[permission] = SpecialPowers.hasPermission(permission, window.document);
});
worker.postMessage({
type: 'returnPermissions',
permissions: event.data.permissions,
result: result
});
} else if (event.data.type == 'getVersion') {
var result = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
worker.postMessage({
type: 'returnVersion',
result: result
});
} else if (event.data.type == 'getUserAgent') {
worker.postMessage({
type: 'returnUserAgent',
result: navigator.userAgent
});
} else if (event.data.type == 'getOSCPU') {
worker.postMessage({
type: 'returnOSCPU',
result: navigator.oscpu
});
} else if (event.data.type == 'getIsB2G') {
worker.postMessage({
type: 'returnIsB2G',
result: SpecialPowers.isB2G
});
}
}
worker.onerror = function(event) {
ok(false, 'Worker had an error: ' + event.data);
SimpleTest.finish();
};
var iframe = document.createElement("iframe");
iframe.src = "message_receiver.html";
iframe.onload = function() {
worker.postMessage({ script: "test_serviceworker_interfaces.js" });
};
document.body.appendChild(iframe);
}
function runTest() {
navigator.serviceWorker.register("serviceworker_wrapper.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
setupSW(registration);
e.target.onstatechange = null;
};
} else {
setupSW(registration);
}
});
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.fetch.enabled", true],
["dom.caches.enabled", true]
]}, runTest);
};
</script>
</body>
</html>
@@ -0,0 +1,280 @@
// This is a list of all interfaces that are exposed to workers.
// Please only add things to this list with great care and proper review
// from the associated module peers.
// This file lists global interfaces we want exposed and verifies they
// are what we intend. Each entry in the arrays below can either be a
// simple string with the interface name, or an object with a 'name'
// property giving the interface name as a string, and additional
// properties which qualify the exposure of that interface. For example:
//
// [
// "AGlobalInterface",
// {name: "ExperimentalThing", release: false},
// {name: "OptionalThing", pref: "some.thing.enabled"},
// ];
//
// See createInterfaceMap() below for a complete list of properties.
// IMPORTANT: Do not change this list without review from
// a JavaScript Engine peer!
var ecmaGlobals =
[
"Array",
"ArrayBuffer",
"Boolean",
"DataView",
"Date",
"Error",
"EvalError",
"Float32Array",
"Float64Array",
"Function",
"Infinity",
"Int16Array",
"Int32Array",
"Int8Array",
"InternalError",
{name: "Intl", b2g: false, android: false},
"Iterator",
"JSON",
"Map",
"Math",
"NaN",
"Number",
"Object",
"Proxy",
"RangeError",
"ReferenceError",
"RegExp",
"Set",
{name: "SharedArrayBuffer", nightly: true},
{name: "SharedInt8Array", nightly: true},
{name: "SharedUint8Array", nightly: true},
{name: "SharedUint8ClampedArray", nightly: true},
{name: "SharedInt16Array", nightly: true},
{name: "SharedUint16Array", nightly: true},
{name: "SharedInt32Array", nightly: true},
{name: "SharedUint32Array", nightly: true},
{name: "SharedFloat32Array", nightly: true},
{name: "SharedFloat64Array", nightly: true},
{name: "SIMD", nightly: true},
{name: "Atomics", nightly: true},
"StopIteration",
"String",
"Symbol",
"SyntaxError",
{name: "TypedObject", nightly: true},
"TypeError",
"Uint16Array",
"Uint32Array",
"Uint8Array",
"Uint8ClampedArray",
"URIError",
"WeakMap",
"WeakSet",
];
// IMPORTANT: Do not change the list above without review from
// a JavaScript Engine peer!
// IMPORTANT: Do not change the list below without review from a DOM peer!
var interfaceNamesInGlobalScope =
[
// IMPORTANT: Do not change this list without review from a DOM peer!
"Blob",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "BroadcastChannel", pref: "dom.broadcastChannel.enabled" },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Cache", pref: "dom.caches.enabled" },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "CacheStorage", pref: "dom.caches.enabled" },
// IMPORTANT: Do not change this list without review from a DOM peer!
"Client",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Clients",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "DataStore", b2g: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "DataStoreCursor", b2g: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
"DOMError",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DOMException",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DOMStringList",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Event",
// IMPORTANT: Do not change this list without review from a DOM peer!
"EventTarget",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ExtendableEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"FetchEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"File",
// IMPORTANT: Do not change this list without review from a DOM peer!
"FileReaderSync",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "Headers", pref: "dom.fetch.enabled" },
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBCursor",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBDatabase",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBFactory",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBIndex",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBKeyRange",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBObjectStore",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBOpenDBRequest",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBRequest",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBTransaction",
// IMPORTANT: Do not change this list without review from a DOM peer!
"IDBVersionChangeEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ImageData",
// IMPORTANT: Do not change this list without review from a DOM peer!
"InstallEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"MessageEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"MessagePort",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Performance",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Promise",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Response",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ServiceWorker",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ServiceWorkerGlobalScope",
// IMPORTANT: Do not change this list without review from a DOM peer!
"TextDecoder",
// IMPORTANT: Do not change this list without review from a DOM peer!
"TextEncoder",
// IMPORTANT: Do not change this list without review from a DOM peer!
"XMLHttpRequest",
// IMPORTANT: Do not change this list without review from a DOM peer!
"XMLHttpRequestEventTarget",
// IMPORTANT: Do not change this list without review from a DOM peer!
"XMLHttpRequestUpload",
// IMPORTANT: Do not change this list without review from a DOM peer!
"URL",
// IMPORTANT: Do not change this list without review from a DOM peer!
"URLSearchParams",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "WebSocket", pref: "dom.workers.websocket.enabled" },
// IMPORTANT: Do not change this list without review from a DOM peer!
"WindowClient",
// IMPORTANT: Do not change this list without review from a DOM peer!
"WorkerGlobalScope",
// IMPORTANT: Do not change this list without review from a DOM peer!
"WorkerLocation",
// IMPORTANT: Do not change this list without review from a DOM peer!
"WorkerNavigator",
// IMPORTANT: Do not change this list without review from a DOM peer!
];
// IMPORTANT: Do not change the list above without review from a DOM peer!
function createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G) {
var isNightly = version.endsWith("a1");
var isRelease = !version.contains("a");
var isDesktop = !/Mobile|Tablet/.test(userAgent);
var isAndroid = !!navigator.userAgent.contains("Android");
var interfaceMap = {};
function addInterfaces(interfaces)
{
for (var entry of interfaces) {
if (typeof(entry) === "string") {
interfaceMap[entry] = true;
} else if ((entry.nightly === !isNightly) ||
(entry.desktop === !isDesktop) ||
(entry.android === !isAndroid) ||
(entry.b2g === !isB2G) ||
(entry.release === !isRelease) ||
(entry.pref && !prefMap[entry.pref]) ||
(entry.permission && !permissionMap[entry.permission])) {
interfaceMap[entry.name] = false;
} else {
interfaceMap[entry.name] = true;
}
}
}
addInterfaces(ecmaGlobals);
addInterfaces(interfaceNamesInGlobalScope);
return interfaceMap;
}
function runTest(prefMap, permissionMap, version, userAgent, isB2G) {
var interfaceMap = createInterfaceMap(prefMap, permissionMap, version, userAgent, isB2G);
for (var name of Object.getOwnPropertyNames(self)) {
// An interface name should start with an upper case character.
if (!/^[A-Z]/.test(name)) {
continue;
}
ok(interfaceMap[name],
"If this is failing: DANGER, are you sure you want to expose the new interface " + name +
" to all webpages as a property on the service worker? Do not make a change to this file without a " +
" review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)");
delete interfaceMap[name];
}
for (var name of Object.keys(interfaceMap)) {
ok(name in self === interfaceMap[name],
name + " should " + (interfaceMap[name] ? "" : " NOT") + " be defined on the global scope");
if (!interfaceMap[name]) {
delete interfaceMap[name];
}
}
is(Object.keys(interfaceMap).length, 0,
"The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", "));
}
function appendPrefs(prefs, interfaces) {
for (var entry of interfaces) {
if (entry.pref !== undefined && prefs.indexOf(entry.pref) === -1) {
prefs.push(entry.pref);
}
}
}
var prefs = [];
appendPrefs(prefs, ecmaGlobals);
appendPrefs(prefs, interfaceNamesInGlobalScope);
function appendPermissions(permissions, interfaces) {
for (var entry of interfaces) {
if (entry.permission !== undefined &&
permissions.indexOf(entry.permission) === -1) {
permissions.push(entry.permission);
}
}
}
var permissions = [];
appendPermissions(permissions, ecmaGlobals);
appendPermissions(permissions, interfaceNamesInGlobalScope);
workerTestGetPrefs(prefs, function(prefMap) {
workerTestGetPermissions(permissions, function(permissionMap) {
workerTestGetVersion(function(version) {
workerTestGetUserAgent(function(userAgent) {
workerTestGetIsB2G(function(isB2G) {
runTest(prefMap, permissionMap, version, userAgent, isB2G);
workerTestDone();
});
});
});
});
});
@@ -0,0 +1,72 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1141274 - test that service workers and shared workers are separate</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
const SCOPE = "http://mochi.test:8888/tests/dom/workers/test/serviceworkers/";
function runTest() {
navigator.serviceWorker.register("serviceworker_not_sharedworker.js",
{scope: SCOPE})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
e.target.onstatechange = null;
setupSW(registration);
};
} else {
setupSW(registration);
}
});
}
var sw, worker;
function setupSW(registration) {
sw = registration.waiting || registration.active;
worker = new SharedWorker("serviceworker_not_sharedworker.js", SCOPE);
worker.port.start();
iframe = document.querySelector("iframe");
iframe.src = "message_receiver.html";
iframe.onload = function() {
window.onmessage = function(e) {
is(e.data.result, "serviceworker", "We should be talking to a service worker");
window.onmessage = null;
worker.port.onmessage = function(e) {
is(e.data.result, "sharedworker", "We should be talking to a shared worker");
registration.unregister().then(function(success) {
ok(success, "unregister should succeed");
SimpleTest.finish();
});
};
worker.port.postMessage({msg: "whoareyou"});
};
sw.postMessage({msg: "whoareyou"});
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
};
</script>
</pre>
</body>
</html>
+11 -2
View File
@@ -2513,7 +2513,7 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, Fu
if (!body)
return false;
if (kind != Method && kind != Lazy &&
if (kind != Method && kind != Lazy &&
fun->name() && !checkStrictBinding(fun->name(), pn))
{
return false;
@@ -6232,6 +6232,15 @@ Parser<ParseHandler>::assignExpr(InvokedPrediction invoked)
case TOK_POWASSIGN: kind = PNK_POWASSIGN; op = JSOP_POW; break;
case TOK_ARROW: {
// A line terminator between ArrowParameters and the => should trigger a SyntaxError.
tokenStream.ungetToken();
TokenKind next;
if (!tokenStream.peekTokenSameLine(&next) || next != TOK_ARROW) {
report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN,
"expression", TokenKindToDesc(TOK_ARROW));
return null();
}
tokenStream.seek(start);
if (!abortIfSyntaxParser())
return null();
@@ -8248,7 +8257,7 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt, InvokedPrediction invoked)
return null();
}
if (!tokenStream.peekToken(&next))
if (!tokenStream.peekTokenSameLine(&next))
return null();
if (next != TOK_ARROW) {
report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN,
@@ -0,0 +1,9 @@
assertThrowsInstanceOf(() => eval("() \n => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("a \n => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("(a) /*\n*/ => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("(a, b) \n => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("(a, b = 1) \n => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("(a, ...b) \n => {}"), SyntaxError);
assertThrowsInstanceOf(() => eval("(a, b = 1, ...c) \n => {}"), SyntaxError);
reportCompare(0, 0, "ok");
+1 -1
View File
@@ -64,7 +64,7 @@ STYLE_STRUCTS = [("INHERITED",) + x for x in [
("Background", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Position", "nullptr", NORMAL_DEP + LENGTH_DEP),
("TextReset", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Display", "nullptr", NORMAL_DEP),
("Display", "nullptr", NORMAL_DEP + LENGTH_DEP),
("Content", "nullptr", NORMAL_DEP + LENGTH_DEP),
("UIReset", "nullptr", NORMAL_DEP),
("Table", "nullptr", NORMAL_DEP),
+1
View File
@@ -14961,6 +14961,7 @@ CSSParserImpl::ParseScrollSnapPoints(nsCSSValue& aValue, nsCSSProperty aPropID)
functionArray->Item(1) = lengthValue;
return true;
}
UngetToken();
return false;
}
+35 -35
View File
@@ -3071,31 +3071,30 @@ CSS_PROP_DISPLAY(
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_DISPLAY(
scroll-snap-type-x,
scroll_snap_type_x,
ScrollSnapTypeX,
CSS_PROPERTY_PARSE_VALUE,
scroll-snap-coordinate,
scroll_snap_coordinate,
ScrollSnapCoordinate,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_STORES_CALC,
"layout.css.scroll-snap.enabled",
VARIANT_HK,
kScrollSnapTypeKTable,
0,
kBackgroundPositionKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_DISPLAY(
scroll-snap-type-y,
scroll_snap_type_y,
ScrollSnapTypeY,
CSS_PROPERTY_PARSE_VALUE,
scroll-snap-destination,
scroll_snap_destination,
ScrollSnapDestination,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_STORES_CALC,
"layout.css.scroll-snap.enabled",
VARIANT_HK,
kScrollSnapTypeKTable,
0,
kBackgroundPositionKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SHORTHAND(
scroll-snap-type,
scroll_snap_type,
ScrollSnapType,
CSS_PROPERTY_PARSE_FUNCTION,
"layout.css.scroll-snap.enabled")
CSS_PROP_DISPLAY(
scroll-snap-points-x,
scroll_snap_points_x,
@@ -3120,29 +3119,30 @@ CSS_PROP_DISPLAY(
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SHORTHAND(
scroll-snap-type,
scroll_snap_type,
ScrollSnapType,
CSS_PROPERTY_PARSE_FUNCTION,
"layout.css.scroll-snap.enabled")
CSS_PROP_DISPLAY(
scroll-snap-destination,
scroll_snap_destination,
ScrollSnapDestination,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_STORES_CALC,
scroll-snap-type-x,
scroll_snap_type_x,
ScrollSnapTypeX,
CSS_PROPERTY_PARSE_VALUE,
"layout.css.scroll-snap.enabled",
0,
kBackgroundPositionKTable,
VARIANT_HK,
kScrollSnapTypeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_DISPLAY(
scroll-snap-coordinate,
scroll_snap_coordinate,
ScrollSnapCoordinate,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_STORES_CALC,
scroll-snap-type-y,
scroll_snap_type_y,
ScrollSnapTypeY,
CSS_PROPERTY_PARSE_VALUE,
"layout.css.scroll-snap.enabled",
0,
kBackgroundPositionKTable,
VARIANT_HK,
kScrollSnapTypeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_BACKENDONLY(
@@ -209,12 +209,12 @@ COMPUTED_STYLE_PROP(right, Right)
COMPUTED_STYLE_PROP(ruby_align, RubyAlign)
COMPUTED_STYLE_PROP(ruby_position, RubyPosition)
COMPUTED_STYLE_PROP(scroll_behavior, ScrollBehavior)
COMPUTED_STYLE_PROP(scroll_snap_type_x, ScrollSnapTypeX)
COMPUTED_STYLE_PROP(scroll_snap_type_y, ScrollSnapTypeY)
COMPUTED_STYLE_PROP(scroll_snap_coordinate, ScrollSnapCoordinate)
COMPUTED_STYLE_PROP(scroll_snap_destination, ScrollSnapDestination)
COMPUTED_STYLE_PROP(scroll_snap_points_x, ScrollSnapPointsX)
COMPUTED_STYLE_PROP(scroll_snap_points_y, ScrollSnapPointsY)
COMPUTED_STYLE_PROP(scroll_snap_destination, ScrollSnapDestination)
COMPUTED_STYLE_PROP(scroll_snap_coordinate, ScrollSnapCoordinate)
COMPUTED_STYLE_PROP(scroll_snap_type_x, ScrollSnapTypeX)
COMPUTED_STYLE_PROP(scroll_snap_type_y, ScrollSnapTypeY)
//// COMPUTED_STYLE_PROP(size, Size)
COMPUTED_STYLE_PROP(table_layout, TableLayout)
COMPUTED_STYLE_PROP(text_align, TextAlign)
+8 -4
View File
@@ -5260,10 +5260,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
// scroll-snap-points-x: none, inherit, initial
const nsCSSValue& scrollSnapPointsX = *aRuleData->ValueForScrollSnapPointsX();
switch (scrollSnapPointsX.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
case eCSSUnit_None:
case eCSSUnit_Null:
display->mScrollSnapPointsX.SetNoneValue();
break;
case eCSSUnit_Inherit:
@@ -5294,10 +5295,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
// scroll-snap-points-y: none, inherit, initial
const nsCSSValue& scrollSnapPointsY = *aRuleData->ValueForScrollSnapPointsY();
switch (scrollSnapPointsY.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
case eCSSUnit_None:
case eCSSUnit_Null:
display->mScrollSnapPointsY.SetNoneValue();
break;
case eCSSUnit_Inherit:
@@ -5328,9 +5330,10 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
// scroll-snap-destination: inherit, initial
const nsCSSValue& snapDestination = *aRuleData->ValueForScrollSnapDestination();
switch (snapDestination.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
case eCSSUnit_Null:
display->mScrollSnapDestination.SetInitialZeroValues();
break;
case eCSSUnit_Inherit:
@@ -5348,10 +5351,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
const nsCSSValue& snapCoordinate = *aRuleData->ValueForScrollSnapCoordinate();
switch (snapCoordinate.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
case eCSSUnit_None:
case eCSSUnit_Null:
// Unset and Initial is none, indicated by an empty array
display->mScrollSnapCoordinate.Clear();
break;
+58 -58
View File
@@ -6436,64 +6436,6 @@ if (SpecialPowers.getBoolPref("layout.css.scroll-behavior.property-enabled")) {
}
if (SpecialPowers.getBoolPref("layout.css.scroll-snap.enabled")) {
gCSSProperties["scroll-snap-type-x"] = {
domProp: "scrollSnapTypeX",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: ["mandatory", "proximity"],
invalid_values: [ "auto", "1px" ]
};
gCSSProperties["scroll-snap-type-y"] = {
domProp: "scrollSnapTypeY",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: ["mandatory", "proximity"],
invalid_values: [ "auto", "1px" ]
};
gCSSProperties["scroll-snap-type"] = {
domProp: "scrollSnapType",
inherited: false,
type: CSS_TYPE_TRUE_SHORTHAND,
subproperties: [ "scroll-snap-type-x", "scroll-snap-type-y" ],
initial_values: [ "none" ],
other_values: [ "mandatory", "proximity" ],
invalid_values: [ "auto", "1px" ]
};
gCSSProperties["scroll-snap-points-x"] = {
domProp: "scrollSnapPointsX",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "repeat(100%)", "repeat(120px)", "repeat(calc(3*25px))" ],
invalid_values: [ "auto", "1px", "left", "rgb(1,2,3)" ]
}
gCSSProperties["scroll-snap-points-y"] = {
domProp: "scrollSnapPointsY",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "repeat(100%)", "repeat(120px)", "repeat(calc(3*25px))" ],
invalid_values: [ "auto", "1px", "top", "rgb(1,2,3)" ]
}
gCSSProperties["scroll-snap-destination"] = {
domProp: "scrollSnapDestination",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "0px 0px" ],
other_values: [ "25% 25%", "6px 5px", "20% 3em", "0 0", "0in 1in",
"top", "right", "top left", "top right", "center",
"calc(2px)",
"calc(50%)",
"calc(3*25px)",
"calc(3*25px) 5px",
"5px calc(3*25px)",
"calc(20%) calc(3*25px)",
"calc(25px*3)",
"calc(3*25px + 50%)"],
invalid_values: [ "auto", "none", "default" ]
}
gCSSProperties["scroll-snap-coordinate"] = {
domProp: "scrollSnapCoordinate",
inherited: false,
@@ -6512,6 +6454,64 @@ if (SpecialPowers.getBoolPref("layout.css.scroll-snap.enabled")) {
"calc(20%) calc(3*25px), center"],
invalid_values: [ "auto", "default" ]
}
gCSSProperties["scroll-snap-destination"] = {
domProp: "scrollSnapDestination",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "0px 0px" ],
other_values: [ "25% 25%", "6px 5px", "20% 3em", "0in 1in",
"top", "right", "top left", "top right", "center",
"calc(2px)",
"calc(50%)",
"calc(3*25px)",
"calc(3*25px) 5px",
"5px calc(3*25px)",
"calc(20%) calc(3*25px)",
"calc(25px*3)",
"calc(3*25px + 50%)"],
invalid_values: [ "auto", "none", "default" ]
}
gCSSProperties["scroll-snap-points-x"] = {
domProp: "scrollSnapPointsX",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "repeat(100%)", "repeat(120px)", "repeat(calc(3*25px))" ],
invalid_values: [ "auto", "1px", "left", "rgb(1,2,3)" ]
}
gCSSProperties["scroll-snap-points-y"] = {
domProp: "scrollSnapPointsY",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "repeat(100%)", "repeat(120px)", "repeat(calc(3*25px))" ],
invalid_values: [ "auto", "1px", "top", "rgb(1,2,3)" ]
}
gCSSProperties["scroll-snap-type"] = {
domProp: "scrollSnapType",
inherited: false,
type: CSS_TYPE_TRUE_SHORTHAND,
subproperties: [ "scroll-snap-type-x", "scroll-snap-type-y" ],
initial_values: [ "none" ],
other_values: [ "mandatory", "proximity" ],
invalid_values: [ "auto", "1px" ]
};
gCSSProperties["scroll-snap-type-x"] = {
domProp: "scrollSnapTypeX",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: ["mandatory", "proximity"],
invalid_values: [ "auto", "1px" ]
};
gCSSProperties["scroll-snap-type-y"] = {
domProp: "scrollSnapTypeY",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: ["mandatory", "proximity"],
invalid_values: [ "auto", "1px" ]
};
}
if (SpecialPowers.getBoolPref("layout.css.unset-value.enabled")) {
+1
View File
@@ -147,6 +147,7 @@ EXPORTS += [
'nsMIMEInputStream.h',
'nsNetUtil.h',
'nsReadLine.h',
'nsSerializationHelper.h',
'nsStreamListenerWrapper.h',
'nsTemporaryFileInputStream.h',
'nsURIHashKey.h',
@@ -16,7 +16,7 @@ interface nsIURI;
* which do not implement nsIChannel.
*/
[scriptable, uuid(9d127b63-dfad-484d-a0e1-cb82697a095b)]
[scriptable, uuid(155378c1-ebb2-4492-917f-85483430d5f5)]
interface nsIInterceptedChannel : nsISupports
{
/**
@@ -59,6 +59,11 @@ interface nsIInterceptedChannel : nsISupports
* True if the underlying request was caused by a navigation attempt.
*/
readonly attribute bool isNavigation;
/**
* This method allows to override the security info for the channel.
*/
void setSecurityInfo(in nsISupports securityInfo);
};
/**
+13
View File
@@ -1419,6 +1419,19 @@ HttpBaseChannel::SetRedirectionLimit(uint32_t value)
return NS_OK;
}
nsresult
HttpBaseChannel::OverrideSecurityInfo(nsISupports* aSecurityInfo)
{
MOZ_RELEASE_ASSERT(!mSecurityInfo,
"This can only be called when we don't have a security info object already");
MOZ_RELEASE_ASSERT(aSecurityInfo,
"This can only be called with a valid security info object");
MOZ_RELEASE_ASSERT(ShouldIntercept(),
"This can only be called on channels that can be intercepted");
mSecurityInfo = aSecurityInfo;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::IsNoStoreResponse(bool *value)
{
+3
View File
@@ -239,6 +239,8 @@ public:
const NetAddr& GetSelfAddr() { return mSelfAddr; }
const NetAddr& GetPeerAddr() { return mPeerAddr; }
nsresult OverrideSecurityInfo(nsISupports* aSecurityInfo);
public: /* Necko internal use only... */
bool IsNavigation();
@@ -316,6 +318,7 @@ protected:
nsAutoPtr<nsHttpResponseHead> mResponseHead;
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
nsCOMPtr<nsIProxyInfo> mProxyInfo;
nsCOMPtr<nsISupports> mSecurityInfo;
nsCString mSpec; // ASCII encoded URL spec
nsCString mContentTypeHint;
-1
View File
@@ -163,7 +163,6 @@ private:
RequestHeaderTuples mClientSetRequestHeaders;
nsCOMPtr<nsIChildChannel> mRedirectChannelChild;
nsCOMPtr<nsISupports> mSecurityInfo;
nsRefPtr<InterceptStreamListener> mInterceptListener;
nsRefPtr<nsInputStreamPump> mSynthesizedResponsePump;
@@ -194,6 +194,12 @@ InterceptedChannelChrome::Cancel()
return NS_OK;
}
NS_IMETHODIMP
InterceptedChannelChrome::SetSecurityInfo(nsISupports* aSecurityInfo)
{
return mChannel->OverrideSecurityInfo(aSecurityInfo);
}
InterceptedChannelContent::InterceptedChannelContent(HttpChannelChild* aChannel,
nsINetworkInterceptController* aController,
nsIStreamListener* aListener)
@@ -290,5 +296,11 @@ InterceptedChannelContent::Cancel()
return NS_OK;
}
NS_IMETHODIMP
InterceptedChannelContent::SetSecurityInfo(nsISupports* aSecurityInfo)
{
return mChannel->OverrideSecurityInfo(aSecurityInfo);
}
} // namespace net
} // namespace mozilla
@@ -75,6 +75,7 @@ public:
NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
NS_IMETHOD Cancel() override;
NS_IMETHOD SetSecurityInfo(nsISupports* aSecurityInfo) override;
virtual void NotifyController() override;
};
@@ -103,6 +104,7 @@ public:
NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
NS_IMETHOD Cancel() override;
NS_IMETHOD SetSecurityInfo(nsISupports* aSecurityInfo) override;
virtual void NotifyController() override;
};
-1
View File
@@ -376,7 +376,6 @@ private:
void SetPushedStream(Http2PushedStream *stream);
private:
nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsICancelable> mProxyRequest;
nsRefPtr<nsInputStreamPump> mTransactionPump;