зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. r=merge a=merge
This commit is contained in:
Коммит
b0098afaea
|
@ -1626,7 +1626,6 @@ pref("reader.errors.includeURLs", true);
|
|||
pref("view_source.tab", true);
|
||||
|
||||
pref("dom.serviceWorkers.enabled", true);
|
||||
pref("dom.serviceWorkers.openWindow.enabled", true);
|
||||
|
||||
// Enable Push API.
|
||||
pref("dom.push.enabled", true);
|
||||
|
|
|
@ -994,6 +994,7 @@ add_old_configure_assignment('MOZ_BUILD_APP', build_project)
|
|||
# - otherwise, we're building Release/Beta (define RELEASE_OR_BETA)
|
||||
@depends(check_build_environment, '--help')
|
||||
@imports(_from='__builtin__', _import='open')
|
||||
@imports('re')
|
||||
def milestone(build_env, _):
|
||||
milestone_path = os.path.join(build_env.topsrcdir,
|
||||
'config',
|
||||
|
@ -1008,7 +1009,18 @@ def milestone(build_env, _):
|
|||
elif 'a' not in milestone:
|
||||
is_release_or_beta = True
|
||||
|
||||
major_version = milestone.split('.')[0]
|
||||
m = re.search(r"([ab]\d+)", milestone)
|
||||
ab_patch = m.group(1) if m else ''
|
||||
|
||||
# Only expose the major version milestone in the UA string and hide the
|
||||
# patch leve (bugs 572659 and 870868).
|
||||
#
|
||||
# Only expose major milestone and alpha version in the symbolversion
|
||||
# string; as the name suggests, we use it for symbol versioning on Linux.
|
||||
return namespace(version=milestone,
|
||||
uaversion='%s.0' % major_version,
|
||||
symbolversion='%s%s' % (major_version, ab_patch),
|
||||
is_nightly=is_nightly,
|
||||
is_release_or_beta=is_release_or_beta)
|
||||
|
||||
|
@ -1021,6 +1033,14 @@ set_config('RELEASE_OR_BETA', milestone.is_release_or_beta)
|
|||
set_define('RELEASE_OR_BETA', milestone.is_release_or_beta)
|
||||
add_old_configure_assignment('RELEASE_OR_BETA',
|
||||
milestone.is_release_or_beta)
|
||||
set_define('MOZILLA_VERSION', depends(milestone)(lambda m: '"%s"' % m.version))
|
||||
set_config('MOZILLA_VERSION', milestone.version)
|
||||
set_define('MOZILLA_VERSION_U', milestone.version)
|
||||
set_define('MOZILLA_UAVERSION', depends(milestone)(lambda m: '"%s"' % m.uaversion))
|
||||
set_config('MOZILLA_SYMBOLVERSION', milestone.symbolversion)
|
||||
# JS configure still wants to look at these.
|
||||
add_old_configure_assignment('MOZILLA_VERSION', milestone.version)
|
||||
add_old_configure_assignment('MOZILLA_SYMBOLVERSION', milestone.symbolversion)
|
||||
|
||||
# The app update channel is 'default' when not supplied. The value is used in
|
||||
# the application's confvars.sh (and is made available to a project specific
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# x.x.x.x
|
||||
# x.x.x+
|
||||
#
|
||||
# Referenced by milestone.py.
|
||||
# Referenced by build/moz.configure/init.configure.
|
||||
# Hopefully I'll be able to automate replacement of *all*
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
#include "sunos4.h"
|
||||
#endif
|
||||
|
||||
#ifndef D_INO
|
||||
#define D_INO d_ino
|
||||
#endif
|
||||
|
||||
char *program;
|
||||
|
||||
void
|
||||
|
@ -108,7 +104,7 @@ ino2name(ino_t ino)
|
|||
for (;;) {
|
||||
if (!(ep = readdir(dp)))
|
||||
fail("cannot find current directory");
|
||||
if (ep->D_INO == ino)
|
||||
if (ep->d_ino == ino)
|
||||
break;
|
||||
}
|
||||
name = xstrdup(ep->d_name);
|
||||
|
|
|
@ -47,6 +47,7 @@ skip-if = !e10s # This test is only valid in e10s
|
|||
[browser_service_workers_not_compatible.js]
|
||||
[browser_service_workers_push.js]
|
||||
[browser_service_workers_push_service.js]
|
||||
skip-if = !e10s # Bug 1424895
|
||||
[browser_service_workers_start.js]
|
||||
[browser_service_workers_status.js]
|
||||
[browser_service_workers_timeout.js]
|
||||
|
|
|
@ -15279,18 +15279,13 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
|||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
} else {
|
||||
// For top-level navigations, save a document ID which will be passed to
|
||||
// the FetchEvent as the clientId later on.
|
||||
rv = nsIDocument::GenerateDocumentId(mInterceptedDocumentId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
bool isReload = mLoadType & LOAD_CMD_RELOAD;
|
||||
|
||||
ErrorResult error;
|
||||
swm->DispatchFetchEvent(mOriginAttributes, doc, mInterceptedDocumentId,
|
||||
aChannel, isReload, isSubresourceLoad, error);
|
||||
swm->DispatchFetchEvent(mOriginAttributes, doc, aChannel, isReload,
|
||||
isSubresourceLoad, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
|
|
@ -374,11 +374,6 @@ public:
|
|||
|
||||
nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs);
|
||||
|
||||
void GetInterceptedDocumentId(nsAString& aId)
|
||||
{
|
||||
aId = mInterceptedDocumentId;
|
||||
}
|
||||
|
||||
private:
|
||||
// An observed docshell wrapper is created when recording markers is enabled.
|
||||
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
|
||||
|
@ -1151,8 +1146,6 @@ protected:
|
|||
// origin attribute set.
|
||||
uint32_t mPrivateBrowsingId;
|
||||
|
||||
nsString mInterceptedDocumentId;
|
||||
|
||||
// This represents the CSS display-mode we are currently using.
|
||||
// It can be any of the following values from nsIDocShell.idl:
|
||||
//
|
||||
|
|
|
@ -2957,6 +2957,8 @@ public:
|
|||
eSessionScoped = 2,
|
||||
// Allow access to the storage
|
||||
eAllow = 3,
|
||||
// Keep this at the end. Used for serialization, but not a valid value.
|
||||
eNumValues = 4,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1864,7 +1864,6 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
|||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMXPathEvaluator)
|
||||
NS_INTERFACE_TABLE_END
|
||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
|
||||
|
@ -5136,28 +5135,6 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
|||
}
|
||||
swm->MaybeStopControlling(this);
|
||||
}
|
||||
|
||||
// Remove ourself from the list of clients. We only register
|
||||
// content principal documents in this list.
|
||||
if (!nsContentUtils::IsSystemPrincipal(GetPrincipal()) &&
|
||||
!GetPrincipal()->GetIsNullPrincipal()) {
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
os->RemoveObserver(this, "service-worker-get-client");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!mScriptGlobalObject && aScriptGlobalObject &&
|
||||
mDocumentContainer && GetChannel() &&
|
||||
!nsContentUtils::IsSystemPrincipal(GetPrincipal()) &&
|
||||
!GetPrincipal()->GetIsNullPrincipal()) {
|
||||
// This document is being activated. Register it in the list of
|
||||
// clients. We only do this for content principal documents
|
||||
// since we can never observe system or null principals.
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
os->AddObserver(this, "service-worker-get-client", /* ownsWeak */ false);
|
||||
}
|
||||
}
|
||||
|
||||
// BlockOnload() might be called before mScriptGlobalObject is set.
|
||||
|
@ -5278,15 +5255,7 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
|||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (swm) {
|
||||
// If this document is being resurrected from the bfcache, then we may
|
||||
// already have a document ID. In that case reuse the same ID. Otherwise
|
||||
// get our document ID from the docshell.
|
||||
nsString documentId(GetId());
|
||||
if (documentId.IsEmpty()) {
|
||||
static_cast<nsDocShell*>(docShell.get())->GetInterceptedDocumentId(documentId);
|
||||
}
|
||||
|
||||
swm->MaybeStartControlling(this, documentId);
|
||||
swm->MaybeStartControlling(this);
|
||||
mMaybeServiceWorkerControlled = true;
|
||||
}
|
||||
}
|
||||
|
@ -12442,32 +12411,6 @@ nsIDocument::GetPointerLockElement()
|
|||
return pointerLockedElement;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (strcmp("service-worker-get-client", aTopic) == 0) {
|
||||
// No need to generate the ID if it doesn't exist here. The ID being
|
||||
// requested must already be generated in order to passed in as
|
||||
// aSubject.
|
||||
nsString clientId = GetId();
|
||||
if (!clientId.IsEmpty() && clientId.Equals(aData)) {
|
||||
nsCOMPtr<nsISupportsInterfacePointer> ifptr = do_QueryInterface(aSubject);
|
||||
if (ifptr) {
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsISupports> value;
|
||||
MOZ_ALWAYS_SUCCEEDS(ifptr->GetData(getter_AddRefs(value)));
|
||||
MOZ_ASSERT(!value);
|
||||
#endif
|
||||
ifptr->SetData(static_cast<nsIDocument*>(this));
|
||||
ifptr->SetDataIID(&NS_GET_IID(nsIDocument));
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::UpdateVisibilityState()
|
||||
{
|
||||
|
@ -13197,49 +13140,6 @@ nsIDocument::CreateHTMLElement(nsAtom* aTag)
|
|||
return element.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsIDocument::GenerateDocumentId(nsAString& aId)
|
||||
{
|
||||
nsID id;
|
||||
nsresult rv = nsContentUtils::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
|
||||
aId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIDocument::GetOrCreateId(nsAString& aId)
|
||||
{
|
||||
if (mId.IsEmpty()) {
|
||||
nsresult rv = GenerateDocumentId(mId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
aId = mId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::SetId(const nsAString& aId)
|
||||
{
|
||||
// The ID should only be set one time, but we may get the same value
|
||||
// more than once if the document is controlled coming out of bfcache.
|
||||
MOZ_ASSERT_IF(mId != aId, mId.IsEmpty());
|
||||
mId = aId;
|
||||
}
|
||||
|
||||
bool
|
||||
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
|
||||
{
|
||||
|
|
|
@ -359,7 +359,6 @@ class nsDocument : public nsIDocument,
|
|||
public nsIRadioGroupContainer,
|
||||
public nsIApplicationCacheContainer,
|
||||
public nsStubMutationObserver,
|
||||
public nsIObserver,
|
||||
public nsIDOMXPathEvaluator
|
||||
{
|
||||
friend class nsIDocument;
|
||||
|
@ -698,9 +697,6 @@ public:
|
|||
// nsIApplicationCacheContainer
|
||||
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
||||
|
||||
// nsIObserver
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
NS_DECL_NSIDOMXPATHEVALUATOR
|
||||
|
||||
virtual nsresult Init();
|
||||
|
|
|
@ -1087,10 +1087,6 @@ public:
|
|||
return mAnonymousContents;
|
||||
}
|
||||
|
||||
static nsresult GenerateDocumentId(nsAString& aId);
|
||||
nsresult GetOrCreateId(nsAString& aId);
|
||||
void SetId(const nsAString& aId);
|
||||
|
||||
mozilla::TimeStamp GetPageUnloadingEventTimeStamp() const
|
||||
{
|
||||
if (!mParentDocument) {
|
||||
|
@ -3333,11 +3329,6 @@ protected:
|
|||
FlushUserFontSet();
|
||||
}
|
||||
|
||||
const nsString& GetId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
// Update our frame request callback scheduling state, if needed. This will
|
||||
// schedule or unschedule them, if necessary, and update
|
||||
// mFrameRequestCallbacksScheduled. aOldShell should only be passed when
|
||||
|
@ -3696,7 +3687,6 @@ protected:
|
|||
nsCOMPtr<nsIChannel> mChannel;
|
||||
private:
|
||||
nsCString mContentType;
|
||||
nsString mId;
|
||||
protected:
|
||||
|
||||
// The document's security info
|
||||
|
|
|
@ -149,16 +149,6 @@ DOMInterfaces = {
|
|||
'nativeType': 'mozilla::dom::workers::ChromeWorkerPrivate',
|
||||
},
|
||||
|
||||
'Client': {
|
||||
'nativeType': 'mozilla::dom::workers::ServiceWorkerClient',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerClient.h',
|
||||
},
|
||||
|
||||
'Clients': {
|
||||
'nativeType': 'mozilla::dom::workers::ServiceWorkerClients',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerClients.h',
|
||||
},
|
||||
|
||||
'console': {
|
||||
'nativeType': 'mozilla::dom::Console',
|
||||
},
|
||||
|
@ -1111,8 +1101,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'WindowClient': {
|
||||
'nativeType': 'mozilla::dom::workers::ServiceWorkerWindowClient',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerWindowClient.h',
|
||||
'nativeType': 'mozilla::dom::Client',
|
||||
},
|
||||
|
||||
'WebGLActiveInfo': {
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
#include "ClientDOMUtil.h"
|
||||
#include "mozilla/dom/ClientHandle.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/ClientManager.h"
|
||||
#include "mozilla/dom/ClientState.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerScope.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::dom::workers::Closing;
|
||||
using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
|
||||
using mozilla::dom::workers::WorkerHolderToken;
|
||||
using mozilla::dom::workers::WorkerPrivate;
|
||||
using mozilla::dom::ipc::StructuredCloneData;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::Client);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::Client);
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::Client, mGlobal);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(mozilla::dom::Client)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
void
|
||||
Client::EnsureHandle()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(mozilla::dom::Client);
|
||||
if (!mHandle) {
|
||||
mHandle = ClientManager::CreateHandle(ClientInfo(mData->info()),
|
||||
mGlobal->EventTargetFor(TaskCategory::Other));
|
||||
}
|
||||
}
|
||||
|
||||
Client::Client(nsIGlobalObject* aGlobal, const ClientInfoAndState& aData)
|
||||
: mGlobal(aGlobal)
|
||||
, mData(MakeUnique<ClientInfoAndState>(aData))
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
Client::CreationTime() const
|
||||
{
|
||||
return mData->info().creationTime();
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
Client::LastFocusTime() const
|
||||
{
|
||||
if (mData->info().type() != ClientType::Window) {
|
||||
return TimeStamp();
|
||||
}
|
||||
return mData->state().get_IPCClientWindowState().lastFocusTime();
|
||||
}
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
Client::GetStorageAccess() const
|
||||
{
|
||||
ClientState state(ClientState::FromIPC(mData->state()));
|
||||
return state.GetStorageAccess();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Client::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
if (mData->info().type() == ClientType::Window) {
|
||||
return WindowClientBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
return ClientBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
Client::GetParentObject() const
|
||||
{
|
||||
return mGlobal;
|
||||
}
|
||||
|
||||
void
|
||||
Client::GetUrl(nsAString& aUrlOut) const
|
||||
{
|
||||
CopyUTF8toUTF16(mData->info().url(), aUrlOut);
|
||||
}
|
||||
|
||||
void
|
||||
Client::GetId(nsAString& aIdOut) const
|
||||
{
|
||||
char buf[NSID_LENGTH];
|
||||
mData->info().id().ToProvidedString(buf);
|
||||
NS_ConvertASCIItoUTF16 uuid(buf);
|
||||
|
||||
// Remove {} and the null terminator
|
||||
aIdOut.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
|
||||
}
|
||||
|
||||
ClientType
|
||||
Client::Type() const
|
||||
{
|
||||
return mData->info().type();
|
||||
}
|
||||
|
||||
FrameType
|
||||
Client::GetFrameType() const
|
||||
{
|
||||
return mData->info().frameType();
|
||||
}
|
||||
|
||||
void
|
||||
Client::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
||||
&transferable);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StructuredCloneData data;
|
||||
data.Write(aCx, aMessage, transferable, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureHandle();
|
||||
mHandle->PostMessage(data, workerPrivate->GetServiceWorkerDescriptor());
|
||||
}
|
||||
|
||||
VisibilityState
|
||||
Client::GetVisibilityState() const
|
||||
{
|
||||
return mData->state().get_IPCClientWindowState().visibilityState();
|
||||
}
|
||||
|
||||
bool
|
||||
Client::Focused() const
|
||||
{
|
||||
return mData->state().get_IPCClientWindowState().focused();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Client::Focus(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
||||
outerPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
// Hold the worker thread alive while we perform the async operation
|
||||
// and also avoid invoking callbacks if the worker starts shutting
|
||||
// down.
|
||||
RefPtr<WorkerHolderToken> token =
|
||||
WorkerHolderToken::Create(GetCurrentThreadWorkerPrivate(), Closing);
|
||||
|
||||
EnsureHandle();
|
||||
RefPtr<ClientStatePromise> innerPromise = mHandle->Focus();
|
||||
RefPtr<Client> self = this;
|
||||
|
||||
innerPromise->Then(mGlobal->EventTargetFor(TaskCategory::Other), __func__,
|
||||
[self, token, outerPromise] (const ClientState& aResult) {
|
||||
if (token->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<Client> newClient =
|
||||
new Client(self->mGlobal, ClientInfoAndState(self->mData->info(), aResult.ToIPC()));
|
||||
outerPromise->MaybeResolve(newClient);
|
||||
}, [self, token, outerPromise] (nsresult aResult) {
|
||||
if (token->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
outerPromise->MaybeReject(aResult);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Client::Navigate(const nsAString& aURL, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
ClientNavigateArgs args(mData->info(), NS_ConvertUTF16toUTF8(aURL),
|
||||
workerPrivate->GetLocationInfo().mHref);
|
||||
RefPtr<Client> self = this;
|
||||
|
||||
StartClientManagerOp(&ClientManager::Navigate, args,
|
||||
mGlobal->EventTargetFor(TaskCategory::Other),
|
||||
[self, outerPromise] (const ClientOpResult& aResult) {
|
||||
if (aResult.type() != ClientOpResult::TClientInfoAndState) {
|
||||
outerPromise->MaybeResolve(JS::NullHandleValue);
|
||||
return;
|
||||
}
|
||||
RefPtr<Client> newClient =
|
||||
new Client(self->mGlobal, aResult.get_ClientInfoAndState());
|
||||
outerPromise->MaybeResolve(newClient);
|
||||
}, [self, outerPromise] (nsresult aResult) {
|
||||
// TODO: Improve this error in bug 1412856. Ideally we should throw
|
||||
// the TypeError in the child process and pass it back to here.
|
||||
outerPromise->MaybeReject(NS_ERROR_TYPE_ERR);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,99 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef _mozilla_dom_Client_h
|
||||
#define _mozilla_dom_Client_h
|
||||
|
||||
#include "mozilla/dom/ClientBinding.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class ClientHandle;
|
||||
class ClientInfoAndState;
|
||||
class Promise;
|
||||
|
||||
template <typename t> class Sequence;
|
||||
|
||||
class Client final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
UniquePtr<ClientInfoAndState> mData;
|
||||
RefPtr<ClientHandle> mHandle;
|
||||
|
||||
~Client() = default;
|
||||
|
||||
void
|
||||
EnsureHandle();
|
||||
|
||||
public:
|
||||
Client(nsIGlobalObject* aGlobal, const ClientInfoAndState& aData);
|
||||
|
||||
TimeStamp
|
||||
CreationTime() const;
|
||||
|
||||
TimeStamp
|
||||
LastFocusTime() const;
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
GetStorageAccess() const;
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// DOM bindings methods
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const;
|
||||
|
||||
// Client Bindings
|
||||
void
|
||||
GetUrl(nsAString& aUrlOut) const;
|
||||
|
||||
void
|
||||
GetId(nsAString& aIdOut) const;
|
||||
|
||||
ClientType
|
||||
Type() const;
|
||||
|
||||
FrameType
|
||||
GetFrameType() const;
|
||||
|
||||
// WindowClient bindings
|
||||
VisibilityState
|
||||
GetVisibilityState() const;
|
||||
|
||||
bool
|
||||
Focused() const;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Focus(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigate(const nsAString& aURL, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferrable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(mozilla::dom::Client)
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _mozilla_dom_Client_h
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef _mozilla_dom_ClientDOMUtil_h
|
||||
#define _mozilla_dom_ClientDOMUtil_h
|
||||
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/ClientOpPromise.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/workers/bindings/WorkerHolderToken.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Utility method to properly execute a ClientManager operation. It
|
||||
// will properly hold a worker thread alive and avoid executing callbacks
|
||||
// if the thread is shutting down.
|
||||
template<typename Func, typename Arg, typename Resolve, typename Reject>
|
||||
void
|
||||
StartClientManagerOp(Func aFunc, const Arg& aArg, nsISerialEventTarget* aTarget,
|
||||
Resolve aResolve, Reject aReject)
|
||||
{
|
||||
using mozilla::dom::workers::Closing;
|
||||
using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
|
||||
using mozilla::dom::workers::WorkerHolderToken;
|
||||
|
||||
RefPtr<WorkerHolderToken> token;
|
||||
if (!NS_IsMainThread()) {
|
||||
token = WorkerHolderToken::Create(GetCurrentThreadWorkerPrivate(), Closing);
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise> promise = aFunc(aArg, aTarget);
|
||||
promise->Then(aTarget, __func__,
|
||||
[aResolve, token](const ClientOpResult& aResult) {
|
||||
if (token && token->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
aResolve(aResult);
|
||||
}, [aReject, token](nsresult aResult) {
|
||||
if (token && token->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
aReject(aResult);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _mozilla_dom_ClientDOMUtil_h
|
|
@ -0,0 +1,285 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Clients.h"
|
||||
|
||||
#include "ClientDOMUtil.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/ClientManager.h"
|
||||
#include "mozilla/dom/ClientsBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
|
||||
using mozilla::dom::workers::WorkerPrivate;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
using mozilla::ipc::PrincipalInfo;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Clients);
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Clients);
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Clients, mGlobal);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Clients)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Clients::Clients(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mGlobal);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Clients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return ClientsBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
Clients::GetParentObject() const
|
||||
{
|
||||
return mGlobal;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Clients::Get(const nsAString& aClientID, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
nsID id;
|
||||
if (!id.Parse(NS_ConvertUTF16toUTF8(aClientID).get())) {
|
||||
// Invalid ID means we will definitely not find a match, so just
|
||||
// resolve with undefined indicating "not found".
|
||||
outerPromise->MaybeResolveWithUndefined();
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
const PrincipalInfo& principalInfo = workerPrivate->GetPrincipalInfo();
|
||||
nsCOMPtr<nsISerialEventTarget> target =
|
||||
mGlobal->EventTargetFor(TaskCategory::Other);
|
||||
|
||||
RefPtr<ClientOpPromise> innerPromise =
|
||||
ClientManager::GetInfoAndState(ClientGetInfoAndStateArgs(id, principalInfo),
|
||||
target);
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = mGlobal;
|
||||
nsCString scope = workerPrivate->ServiceWorkerScope();
|
||||
|
||||
innerPromise->Then(target, __func__,
|
||||
[outerPromise, global, scope] (const ClientOpResult& aResult) {
|
||||
RefPtr<Client> client = new Client(global, aResult.get_ClientInfoAndState());
|
||||
if (client->GetStorageAccess() == nsContentUtils::StorageAccess::eAllow) {
|
||||
outerPromise->MaybeResolve(Move(client));
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("Clients::MatchAll() storage denied",
|
||||
[scope] {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
scope, "ServiceWorkerGetClientStorageError", nsTArray<nsString>());
|
||||
});
|
||||
SystemGroup::Dispatch(TaskCategory::Other, r.forget());
|
||||
outerPromise->MaybeResolveWithUndefined();
|
||||
}, [outerPromise] (nsresult aResult) {
|
||||
outerPromise->MaybeResolveWithUndefined();
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class MatchAllComparator final
|
||||
{
|
||||
public:
|
||||
bool
|
||||
LessThan(Client* aLeft, Client* aRight) const
|
||||
{
|
||||
TimeStamp leftFocusTime = aLeft->LastFocusTime();
|
||||
TimeStamp rightFocusTime = aRight->LastFocusTime();
|
||||
// If the focus times are the same, then default to creation order.
|
||||
// MatchAll should return oldest Clients first.
|
||||
if (leftFocusTime == rightFocusTime) {
|
||||
return aLeft->CreationTime() < aRight->CreationTime();
|
||||
}
|
||||
|
||||
// Otherwise compare focus times. We reverse the logic here so
|
||||
// that the most recently focused window is first in the list.
|
||||
if (!leftFocusTime.IsNull() && rightFocusTime.IsNull()) {
|
||||
return true;
|
||||
}
|
||||
if (leftFocusTime.IsNull() && !rightFocusTime.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
return leftFocusTime > rightFocusTime;
|
||||
}
|
||||
|
||||
bool
|
||||
Equals(Client* aLeft, Client* aRight) const
|
||||
{
|
||||
return aLeft->LastFocusTime() == aRight->LastFocusTime() &&
|
||||
aLeft->CreationTime() == aRight->CreationTime();
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Clients::MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = mGlobal;
|
||||
nsCString scope = workerPrivate->ServiceWorkerScope();
|
||||
|
||||
ClientMatchAllArgs args(workerPrivate->GetServiceWorkerDescriptor().ToIPC(),
|
||||
aOptions.mType,
|
||||
aOptions.mIncludeUncontrolled);
|
||||
StartClientManagerOp(&ClientManager::MatchAll, args,
|
||||
mGlobal->EventTargetFor(TaskCategory::Other),
|
||||
[outerPromise, global, scope] (const ClientOpResult& aResult) {
|
||||
nsTArray<RefPtr<Client>> clientList;
|
||||
bool storageDenied = false;
|
||||
for (const ClientInfoAndState& value : aResult.get_ClientList().values()) {
|
||||
RefPtr<Client> client = new Client(global, value);
|
||||
if (client->GetStorageAccess() != nsContentUtils::StorageAccess::eAllow) {
|
||||
storageDenied = true;
|
||||
continue;
|
||||
}
|
||||
clientList.AppendElement(Move(client));
|
||||
}
|
||||
if (storageDenied) {
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("Clients::MatchAll() storage denied",
|
||||
[scope] {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
scope, "ServiceWorkerGetClientStorageError", nsTArray<nsString>());
|
||||
});
|
||||
SystemGroup::Dispatch(TaskCategory::Other, r.forget());
|
||||
}
|
||||
clientList.Sort(MatchAllComparator());
|
||||
outerPromise->MaybeResolve(clientList);
|
||||
}, [outerPromise] (nsresult aResult) {
|
||||
outerPromise->MaybeReject(aResult);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Clients::OpenWindow(const nsAString& aURL, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
if (aURL.EqualsLiteral("about:blank")) {
|
||||
// TODO: Improve this error in bug 1412856.
|
||||
outerPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
||||
outerPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
const PrincipalInfo& principalInfo = workerPrivate->GetPrincipalInfo();
|
||||
nsCString baseURL = workerPrivate->GetLocationInfo().mHref;
|
||||
ClientOpenWindowArgs args(principalInfo, NS_ConvertUTF16toUTF8(aURL),
|
||||
baseURL);
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = mGlobal;
|
||||
|
||||
StartClientManagerOp(&ClientManager::OpenWindow, args,
|
||||
mGlobal->EventTargetFor(TaskCategory::Other),
|
||||
[outerPromise, global] (const ClientOpResult& aResult) {
|
||||
if (aResult.type() != ClientOpResult::TClientInfoAndState) {
|
||||
outerPromise->MaybeResolve(JS::NullHandleValue);
|
||||
return;
|
||||
}
|
||||
RefPtr<Client> client =
|
||||
new Client(global, aResult.get_ClientInfoAndState());
|
||||
outerPromise->MaybeResolve(client);
|
||||
}, [outerPromise] (nsresult aResult) {
|
||||
// TODO: Improve this error in bug 1412856. Ideally we should throw
|
||||
// the TypeError in the child process and pass it back to here.
|
||||
outerPromise->MaybeReject(NS_ERROR_TYPE_ERR);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Clients::Claim(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
const ServiceWorkerDescriptor& serviceWorker =
|
||||
workerPrivate->GetServiceWorkerDescriptor();
|
||||
|
||||
if (serviceWorker.State() != ServiceWorkerState::Activating &&
|
||||
serviceWorker.State() != ServiceWorkerState::Activated) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
StartClientManagerOp(&ClientManager::Claim, ClientClaimArgs(serviceWorker.ToIPC()),
|
||||
mGlobal->EventTargetFor(TaskCategory::Other),
|
||||
[outerPromise] (const ClientOpResult& aResult) {
|
||||
outerPromise->MaybeResolveWithUndefined();
|
||||
}, [outerPromise] (nsresult aResult) {
|
||||
outerPromise->MaybeReject(aResult);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef _mozilla_dom_Clients_h
|
||||
#define _mozilla_dom_Clients_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
struct ClientQueryOptions;
|
||||
class Promise;
|
||||
|
||||
class Clients final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
|
||||
~Clients() = default;
|
||||
|
||||
public:
|
||||
explicit Clients(nsIGlobalObject* aGlobal);
|
||||
|
||||
// nsWrapperCache interface methods
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// DOM bindings methods
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Get(const nsAString& aClientID, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
OpenWindow(const nsAString& aURL, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Claim(ErrorResult& aRv);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Clients)
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _mozilla_dom_Clients_h
|
|
@ -0,0 +1,32 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Client.h',
|
||||
'Clients.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Client.cpp',
|
||||
'Clients.cpp',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/workers',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
]
|
|
@ -10,6 +10,7 @@ include ProtocolTypes;
|
|||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||
using ClientType from "mozilla/dom/ClientIPCUtils.h";
|
||||
using FrameType from "mozilla/dom/ClientIPCUtils.h";
|
||||
using nsContentUtils::StorageAccess from "mozilla/dom/ClientIPCUtils.h";
|
||||
using VisibilityState from "mozilla/dom/ClientIPCUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -37,11 +38,13 @@ struct IPCClientWindowState
|
|||
{
|
||||
VisibilityState visibilityState;
|
||||
TimeStamp lastFocusTime;
|
||||
StorageAccess storageAccess;
|
||||
bool focused;
|
||||
};
|
||||
|
||||
struct IPCClientWorkerState
|
||||
{
|
||||
StorageAccess storageAccess;
|
||||
};
|
||||
|
||||
union IPCClientState
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/dom/ClientBinding.h"
|
||||
#include "mozilla/dom/ClientsBinding.h"
|
||||
#include "mozilla/dom/DocumentBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace IPC {
|
||||
template<>
|
||||
|
@ -36,6 +37,13 @@ namespace IPC {
|
|||
mozilla::dom::VisibilityState::Hidden,
|
||||
mozilla::dom::VisibilityState::EndGuard_>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsContentUtils::StorageAccess> :
|
||||
public ContiguousEnumSerializer<nsContentUtils::StorageAccess,
|
||||
nsContentUtils::StorageAccess::eDeny,
|
||||
nsContentUtils::StorageAccess::eNumValues>
|
||||
{};
|
||||
} // namespace IPC
|
||||
|
||||
#endif // _mozilla_dom_ClientIPCUtils_h
|
||||
|
|
|
@ -78,7 +78,9 @@ ClientSource::SnapshotWindowState(ClientState* aStateOut)
|
|||
if (!window || !window->IsCurrentInnerWindow() ||
|
||||
!window->HasActiveDocument()) {
|
||||
*aStateOut = ClientState(ClientWindowState(VisibilityState::Hidden,
|
||||
TimeStamp(), false));
|
||||
TimeStamp(),
|
||||
nsContentUtils::StorageAccess::eDeny,
|
||||
false));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -94,8 +96,12 @@ ClientSource::SnapshotWindowState(ClientState* aStateOut)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsContentUtils::StorageAccess storage =
|
||||
nsContentUtils::StorageAllowedForDocument(doc);
|
||||
|
||||
*aStateOut = ClientState(ClientWindowState(doc->VisibilityState(),
|
||||
doc->LastFocusTime(), focused));
|
||||
doc->LastFocusTime(), storage,
|
||||
focused));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -355,6 +361,23 @@ ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
|
|||
|
||||
mController.reset();
|
||||
mController.emplace(aServiceWorker);
|
||||
|
||||
RefPtr<ServiceWorkerContainer> swc;
|
||||
nsPIDOMWindowInner* window = GetInnerWindow();
|
||||
if (window) {
|
||||
RefPtr<Navigator> navigator =
|
||||
static_cast<Navigator*>(window->GetNavigator());
|
||||
if (navigator) {
|
||||
swc = navigator->ServiceWorker();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Also self.navigator.serviceWorker on workers when its exposed there
|
||||
|
||||
if (swc && nsContentUtils::IsSafeToRunScript()) {
|
||||
IgnoredErrorResult ignored;
|
||||
swc->ControllerChanged(ignored);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
|
@ -549,11 +572,39 @@ ClientSource::PostMessage(const ClientPostMessageArgs& aArgs)
|
|||
RefPtr<ClientOpPromise>
|
||||
ClientSource::Claim(const ClientClaimArgs& aArgs)
|
||||
{
|
||||
SetController(ServiceWorkerDescriptor(aArgs.serviceWorker()));
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
ServiceWorkerDescriptor swd(aArgs.serviceWorker());
|
||||
|
||||
// Today the ServiceWorkerManager maintains its own list of
|
||||
// nsIDocument objects controlled by each service worker. We
|
||||
// need to try to update that data structure for now. If we
|
||||
// can't, however, then simply mark the Client as controlled.
|
||||
// In the future this will be enough for the SWM as well since
|
||||
// it will eventually hold ClientHandle objects instead of
|
||||
// nsIDocuments.
|
||||
nsPIDOMWindowInner* innerWindow = GetInnerWindow();
|
||||
nsIDocument* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
|
||||
RefPtr<ServiceWorkerManager> swm = doc ? ServiceWorkerManager::GetInstance()
|
||||
: nullptr;
|
||||
if (!swm || !doc) {
|
||||
SetController(swd);
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise::Private> outerPromise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
RefPtr<GenericPromise> p = swm->MaybeClaimClient(doc, swd);
|
||||
p->Then(mEventTarget, __func__,
|
||||
[outerPromise] (bool aResult) {
|
||||
outerPromise->Resolve(NS_OK, __func__);
|
||||
}, [outerPromise] (nsresult aResult) {
|
||||
outerPromise->Reject(aResult, __func__);
|
||||
});
|
||||
|
||||
ref = outerPromise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
|
@ -589,7 +640,18 @@ ClientSource::SnapshotState(ClientState* aStateOut)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
*aStateOut = ClientState(ClientWorkerState());
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivate();
|
||||
if (!workerPrivate) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// Workers only keep a boolean for storage access at the moment.
|
||||
// Map this back to eAllow or eDeny for now.
|
||||
nsContentUtils::StorageAccess storage =
|
||||
workerPrivate->IsStorageAllowed() ? nsContentUtils::StorageAccess::eAllow
|
||||
: nsContentUtils::StorageAccess::eDeny;
|
||||
|
||||
*aStateOut = ClientState(ClientWorkerState(storage));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,10 @@ namespace dom {
|
|||
|
||||
ClientWindowState::ClientWindowState(mozilla::dom::VisibilityState aVisibilityState,
|
||||
const TimeStamp& aLastFocusTime,
|
||||
nsContentUtils::StorageAccess aStorageAccess,
|
||||
bool aFocused)
|
||||
: mData(MakeUnique<IPCClientWindowState>(aVisibilityState, aLastFocusTime,
|
||||
aFocused))
|
||||
aStorageAccess, aFocused))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -72,14 +73,20 @@ ClientWindowState::Focused() const
|
|||
return mData->focused();
|
||||
}
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
ClientWindowState::GetStorageAccess() const
|
||||
{
|
||||
return mData->storageAccess();
|
||||
}
|
||||
|
||||
const IPCClientWindowState&
|
||||
ClientWindowState::ToIPC() const
|
||||
{
|
||||
return *mData;
|
||||
}
|
||||
|
||||
ClientWorkerState::ClientWorkerState()
|
||||
: mData(MakeUnique<IPCClientWorkerState>())
|
||||
ClientWorkerState::ClientWorkerState(nsContentUtils::StorageAccess aStorageAccess)
|
||||
: mData(MakeUnique<IPCClientWorkerState>(aStorageAccess))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -118,6 +125,12 @@ ClientWorkerState::~ClientWorkerState()
|
|||
{
|
||||
}
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
ClientWorkerState::GetStorageAccess() const
|
||||
{
|
||||
return mData->storageAccess();
|
||||
}
|
||||
|
||||
const IPCClientWorkerState&
|
||||
ClientWorkerState::ToIPC() const
|
||||
{
|
||||
|
@ -202,6 +215,16 @@ ClientState::AsWorkerState() const
|
|||
return mData.ref().as<ClientWorkerState>();
|
||||
}
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
ClientState::GetStorageAccess() const
|
||||
{
|
||||
if (IsWindowState()) {
|
||||
return AsWindowState().GetStorageAccess();
|
||||
}
|
||||
|
||||
return AsWorkerState().GetStorageAccess();
|
||||
}
|
||||
|
||||
const IPCClientState
|
||||
ClientState::ToIPC() const
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -29,6 +30,7 @@ class ClientWindowState final
|
|||
public:
|
||||
ClientWindowState(mozilla::dom::VisibilityState aVisibilityState,
|
||||
const TimeStamp& aLastFocusTime,
|
||||
nsContentUtils::StorageAccess aStorageAccess,
|
||||
bool aFocused);
|
||||
|
||||
explicit ClientWindowState(const IPCClientWindowState& aData);
|
||||
|
@ -53,6 +55,9 @@ public:
|
|||
bool
|
||||
Focused() const;
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
GetStorageAccess() const;
|
||||
|
||||
const IPCClientWindowState&
|
||||
ToIPC() const;
|
||||
};
|
||||
|
@ -68,7 +73,7 @@ class ClientWorkerState final
|
|||
UniquePtr<IPCClientWorkerState> mData;
|
||||
|
||||
public:
|
||||
ClientWorkerState();
|
||||
explicit ClientWorkerState(nsContentUtils::StorageAccess aStorageAccess);
|
||||
|
||||
explicit ClientWorkerState(const IPCClientWorkerState& aData);
|
||||
|
||||
|
@ -83,6 +88,9 @@ public:
|
|||
|
||||
~ClientWorkerState();
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
GetStorageAccess() const;
|
||||
|
||||
const IPCClientWorkerState&
|
||||
ToIPC() const;
|
||||
};
|
||||
|
@ -128,6 +136,9 @@ public:
|
|||
const ClientWorkerState&
|
||||
AsWorkerState() const;
|
||||
|
||||
nsContentUtils::StorageAccess
|
||||
GetStorageAccess() const;
|
||||
|
||||
const IPCClientState
|
||||
ToIPC() const;
|
||||
};
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'api',
|
||||
'manager',
|
||||
]
|
||||
|
|
|
@ -139,6 +139,7 @@ namespace indexedDB {
|
|||
|
||||
using namespace mozilla::dom::quota;
|
||||
using namespace mozilla::ipc;
|
||||
using mozilla::dom::quota::Client;
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
*
|
||||
* This MUST only be called once per document!
|
||||
*/
|
||||
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc, in DOMString aDocumentId);
|
||||
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc);
|
||||
|
||||
/**
|
||||
* Documents that have called MaybeStartControlling() should call this when
|
||||
|
|
|
@ -249,6 +249,11 @@ bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName)
|
|||
if (!sApplicationASN) {
|
||||
sApplicationASN = ::CFBundleGetFunctionPointerForName(launchServices,
|
||||
CFSTR("_LSGetCurrentApplicationASN"));
|
||||
if (!sApplicationASN) {
|
||||
NS_WARNING("Failed to set process name: Could not get function pointer "
|
||||
"for LaunchServices");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>
|
||||
|
|
|
@ -13,6 +13,7 @@ interface Client {
|
|||
readonly attribute USVString url;
|
||||
|
||||
// Remove frameType in bug 1290936
|
||||
[BinaryName="GetFrameType"]
|
||||
readonly attribute FrameType frameType;
|
||||
|
||||
readonly attribute ClientType type;
|
||||
|
@ -27,6 +28,7 @@ interface Client {
|
|||
|
||||
[Exposed=ServiceWorker]
|
||||
interface WindowClient : Client {
|
||||
[BinaryName="GetVisibilityState"]
|
||||
readonly attribute VisibilityState visibilityState;
|
||||
readonly attribute boolean focused;
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ interface Clients {
|
|||
Promise<any> get(DOMString id);
|
||||
[NewObject]
|
||||
Promise<sequence<Client>> matchAll(optional ClientQueryOptions options);
|
||||
[NewObject,
|
||||
Func="mozilla::dom::ServiceWorkerGlobalScope::OpenWindowEnabled"]
|
||||
[NewObject]
|
||||
Promise<WindowClient?> openWindow(USVString url);
|
||||
[NewObject]
|
||||
Promise<void> claim();
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
[Global=(Worker,ServiceWorker),
|
||||
Exposed=ServiceWorker]
|
||||
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
|
||||
[SameObject] readonly attribute Clients clients;
|
||||
[SameObject, BinaryName="GetClients"]
|
||||
readonly attribute Clients clients;
|
||||
[SameObject] readonly attribute ServiceWorkerRegistration registration;
|
||||
|
||||
[Throws, NewObject]
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerPrivate.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/ClientState.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
|
||||
|
||||
|
@ -102,9 +103,17 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
return;
|
||||
}
|
||||
|
||||
UniquePtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(window->GetExtantDoc()));
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (clientInfo.isNothing() || clientState.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceWorkerPrivate* workerPrivate = mInfo->WorkerPrivate();
|
||||
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, Move(clientInfo));
|
||||
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
||||
ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()));
|
||||
}
|
||||
|
||||
} // namespace workers
|
||||
|
|
|
@ -1,288 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerContainer.h"
|
||||
|
||||
#include "mozilla/dom/MessageEvent.h"
|
||||
#include "mozilla/dom/Navigator.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerPrivate.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClient)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClient)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc, uint32_t aOrdinal)
|
||||
: mType(ClientType::Window)
|
||||
, mOrdinal(aOrdinal)
|
||||
, mWindowId(0)
|
||||
, mFrameType(FrameType::None)
|
||||
{
|
||||
MOZ_ASSERT(aDoc);
|
||||
nsresult rv = aDoc->GetOrCreateId(mClientId);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get the UUID of the document.");
|
||||
}
|
||||
|
||||
RefPtr<nsGlobalWindowInner> innerWindow =
|
||||
nsGlobalWindowInner::Cast(aDoc->GetInnerWindow());
|
||||
if (innerWindow) {
|
||||
// XXXcatalinb: The inner window can be null if the document is navigating
|
||||
// and was detached.
|
||||
mWindowId = innerWindow->WindowID();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> originalURI = aDoc->GetOriginalURI();
|
||||
if (originalURI) {
|
||||
nsAutoCString spec;
|
||||
originalURI->GetSpec(spec);
|
||||
CopyUTF8toUTF16(spec, mUrl);
|
||||
}
|
||||
mVisibilityState = aDoc->VisibilityState();
|
||||
|
||||
mLastFocusTime = aDoc->LastFocusTime();
|
||||
|
||||
ErrorResult result;
|
||||
mFocused = aDoc->HasFocus(result);
|
||||
if (result.Failed()) {
|
||||
NS_WARNING("Failed to get focus information.");
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(mLastFocusTime.IsNull(), !mFocused);
|
||||
MOZ_ASSERT_IF(mFocused, !mLastFocusTime.IsNull());
|
||||
|
||||
RefPtr<nsGlobalWindowOuter> outerWindow =
|
||||
nsGlobalWindowOuter::Cast(aDoc->GetWindow());
|
||||
if (!outerWindow) {
|
||||
MOZ_ASSERT(mFrameType == FrameType::None);
|
||||
} else if (!outerWindow->IsTopLevelWindow()) {
|
||||
mFrameType = FrameType::Nested;
|
||||
} else if (outerWindow->HadOriginalOpener()) {
|
||||
mFrameType = FrameType::Auxiliary;
|
||||
} else {
|
||||
mFrameType = FrameType::Top_level;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerClientInfo::operator<(const ServiceWorkerClientInfo& aRight) const
|
||||
{
|
||||
// Note: the mLastFocusTime comparisons are reversed because we need to
|
||||
// put most recently focused values first. The mOrdinal comparison is
|
||||
// normal, though, because otherwise we want normal creation order.
|
||||
|
||||
if (mLastFocusTime == aRight.mLastFocusTime) {
|
||||
return mOrdinal < aRight.mOrdinal;
|
||||
}
|
||||
|
||||
if (mLastFocusTime.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aRight.mLastFocusTime.IsNull()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return mLastFocusTime > aRight.mLastFocusTime;
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerClientInfo::operator==(const ServiceWorkerClientInfo& aRight) const
|
||||
{
|
||||
return mLastFocusTime == aRight.mLastFocusTime &&
|
||||
mOrdinal == aRight.mOrdinal &&
|
||||
mClientId == aRight.mClientId;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ServiceWorkerClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return ClientBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
ClientType
|
||||
ServiceWorkerClient::Type() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ServiceWorkerClientPostMessageRunnable final
|
||||
: public Runnable
|
||||
, public StructuredCloneHolder
|
||||
{
|
||||
const uint64_t mSourceID;
|
||||
const nsCString mSourceScope;
|
||||
const uint64_t mWindowId;
|
||||
|
||||
public:
|
||||
ServiceWorkerClientPostMessageRunnable(uint64_t aSourceID,
|
||||
const nsACString& aSourceScope,
|
||||
uint64_t aWindowId)
|
||||
: mozilla::Runnable("ServiceWorkerClientPostMessageRunnable")
|
||||
, StructuredCloneHolder(CloningSupported,
|
||||
TransferringSupported,
|
||||
StructuredCloneScope::SameProcessDifferentThread)
|
||||
, mSourceID(aSourceID)
|
||||
, mSourceScope(aSourceScope)
|
||||
, mWindowId(aWindowId)
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsGlobalWindowInner* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowId);
|
||||
if (!window) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
dom::Navigator* navigator = window->Navigator();
|
||||
if (!navigator) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.Init(window))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
return DispatchDOMEvent(cx, window->AsInner(), container);
|
||||
}
|
||||
|
||||
private:
|
||||
NS_IMETHOD
|
||||
DispatchDOMEvent(JSContext* aCx, nsPIDOMWindowInner* aWindow,
|
||||
ServiceWorkerContainer* aTargetContainer)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_ASSERT(aTargetContainer->GetParentObject(),
|
||||
"How come we don't have a window here?!");
|
||||
|
||||
JS::Rooted<JS::Value> messageData(aCx);
|
||||
ErrorResult rv;
|
||||
Read(aTargetContainer->GetParentObject(), aCx, &messageData, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
xpc::Throw(aCx, rv.StealNSResult());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RootedDictionary<MessageEventInit> init(aCx);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = aTargetContainer->GetParentObject()->PrincipalOrNull();
|
||||
NS_WARNING_ASSERTION(principal, "Why is the principal null here?");
|
||||
|
||||
bool isNullPrincipal = false;
|
||||
bool isSystemPrincipal = false;
|
||||
if (principal) {
|
||||
isNullPrincipal = principal->GetIsNullPrincipal();
|
||||
MOZ_ASSERT(!isNullPrincipal);
|
||||
isSystemPrincipal = principal->GetIsSystemPrincipal();
|
||||
MOZ_ASSERT(!isSystemPrincipal);
|
||||
}
|
||||
|
||||
init.mData = messageData;
|
||||
nsAutoCString origin;
|
||||
if (principal && !isNullPrincipal && !isSystemPrincipal) {
|
||||
principal->GetOrigin(origin);
|
||||
}
|
||||
init.mOrigin = NS_ConvertUTF8toUTF16(origin);
|
||||
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
RefPtr<ServiceWorkerRegistrationInfo> reg =
|
||||
swm->GetRegistration(principal, mSourceScope);
|
||||
if (reg) {
|
||||
RefPtr<ServiceWorkerInfo> serviceWorker = reg->GetByID(mSourceID);
|
||||
if (serviceWorker) {
|
||||
init.mSource.SetValue().SetAsServiceWorker() =
|
||||
serviceWorker->GetOrCreateInstance(aWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!TakeTransferredPortsAsSequence(init.mPorts)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
RefPtr<MessageEvent> event =
|
||||
MessageEvent::Constructor(aTargetContainer, NS_LITERAL_STRING("message"),
|
||||
init);
|
||||
|
||||
event->SetTrusted(true);
|
||||
bool status = false;
|
||||
aTargetContainer->DispatchEvent(static_cast<dom::Event*>(event.get()),
|
||||
&status);
|
||||
|
||||
if (!status) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
|
||||
aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
||||
&transferable);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// At the moment we only expose Client on ServiceWorker globals.
|
||||
MOZ_ASSERT(workerPrivate->IsServiceWorker());
|
||||
uint32_t serviceWorkerID = workerPrivate->ServiceWorkerID();
|
||||
nsCString scope = workerPrivate->ServiceWorkerScope();
|
||||
|
||||
RefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
|
||||
new ServiceWorkerClientPostMessageRunnable(serviceWorkerID, scope,
|
||||
mWindowId);
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy().denySharedArrayBuffer(),
|
||||
aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = workerPrivate->DispatchToMainThread(runnable.forget());
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_workers_serviceworkerclient_h
|
||||
#define mozilla_dom_workers_serviceworkerclient_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ClientBinding.h"
|
||||
|
||||
class nsIDocument;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerClient;
|
||||
class ServiceWorkerWindowClient;
|
||||
|
||||
// Used as a container object for information needed to create
|
||||
// client objects.
|
||||
class ServiceWorkerClientInfo final
|
||||
{
|
||||
friend class ServiceWorkerClient;
|
||||
friend class ServiceWorkerWindowClient;
|
||||
|
||||
public:
|
||||
explicit ServiceWorkerClientInfo(nsIDocument* aDoc, uint32_t aOrdinal = 0);
|
||||
|
||||
const nsString& ClientId() const
|
||||
{
|
||||
return mClientId;
|
||||
}
|
||||
|
||||
bool operator<(const ServiceWorkerClientInfo& aRight) const;
|
||||
bool operator==(const ServiceWorkerClientInfo& aRight) const;
|
||||
|
||||
private:
|
||||
const mozilla::dom::ClientType mType;
|
||||
const uint32_t mOrdinal;
|
||||
nsString mClientId;
|
||||
uint64_t mWindowId;
|
||||
nsString mUrl;
|
||||
|
||||
// Window Clients
|
||||
VisibilityState mVisibilityState;
|
||||
FrameType mFrameType;
|
||||
TimeStamp mLastFocusTime;
|
||||
bool mFocused;
|
||||
};
|
||||
|
||||
class ServiceWorkerClient : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClient)
|
||||
|
||||
ServiceWorkerClient(nsISupports* aOwner,
|
||||
const ServiceWorkerClientInfo& aClientInfo)
|
||||
: mOwner(aOwner)
|
||||
, mType(aClientInfo.mType)
|
||||
, mId(aClientInfo.mClientId)
|
||||
, mUrl(aClientInfo.mUrl)
|
||||
, mWindowId(aClientInfo.mWindowId)
|
||||
, mFrameType(aClientInfo.mFrameType)
|
||||
{
|
||||
MOZ_ASSERT(aOwner);
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
void GetId(nsString& aRetval) const
|
||||
{
|
||||
aRetval = mId;
|
||||
}
|
||||
|
||||
void
|
||||
GetUrl(nsAString& aUrl) const
|
||||
{
|
||||
aUrl.Assign(mUrl);
|
||||
}
|
||||
|
||||
mozilla::dom::FrameType
|
||||
FrameType() const
|
||||
{
|
||||
return mFrameType;
|
||||
}
|
||||
|
||||
mozilla::dom::ClientType
|
||||
Type() const;
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
protected:
|
||||
virtual ~ServiceWorkerClient()
|
||||
{ }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
const ClientType mType;
|
||||
nsString mId;
|
||||
nsString mUrl;
|
||||
|
||||
protected:
|
||||
uint64_t mWindowId;
|
||||
mozilla::dom::FrameType mFrameType;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_workers_serviceworkerclient_h
|
|
@ -1,940 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ServiceWorkerClients.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/JSObjectHolder.h"
|
||||
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerPrivate.h"
|
||||
#include "ServiceWorkerWindowClient.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIWindowWatcher.h"
|
||||
#include "nsWindowWatcher.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "FennecJNIWrappers.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClients)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClients)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClients, mWorkerScope)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClients)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
ServiceWorkerClients::ServiceWorkerClients(ServiceWorkerGlobalScope* aWorkerScope)
|
||||
: mWorkerScope(aWorkerScope)
|
||||
{
|
||||
MOZ_ASSERT(mWorkerScope);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ServiceWorkerClients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return ClientsBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class GetRunnable final : public Runnable
|
||||
{
|
||||
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
UniquePtr<ServiceWorkerClientInfo> mValue;
|
||||
nsresult mRv;
|
||||
|
||||
public:
|
||||
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
PromiseWorkerProxy* aPromiseProxy,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aValue,
|
||||
nsresult aRv)
|
||||
: WorkerRunnable(aWorkerPrivate),
|
||||
mPromiseProxy(aPromiseProxy),
|
||||
mValue(Move(aValue)),
|
||||
mRv(Move(aRv))
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
Promise* promise = mPromiseProxy->WorkerPromise();
|
||||
MOZ_ASSERT(promise);
|
||||
|
||||
if (NS_FAILED(mRv)) {
|
||||
promise->MaybeReject(mRv);
|
||||
} else if (mValue) {
|
||||
RefPtr<ServiceWorkerWindowClient> windowClient =
|
||||
new ServiceWorkerWindowClient(promise->GetParentObject(), *mValue);
|
||||
promise->MaybeResolve(windowClient.get());
|
||||
} else {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}
|
||||
mPromiseProxy->CleanUp();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
nsString mClientId;
|
||||
public:
|
||||
GetRunnable(PromiseWorkerProxy* aPromiseProxy, const nsAString& aClientId)
|
||||
: mozilla::Runnable("GetRunnable")
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mClientId(aClientId)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
UniquePtr<ServiceWorkerClientInfo> result;
|
||||
ErrorResult rv;
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
result = swm->GetClient(workerPrivate->GetPrincipal(), mClientId, rv);
|
||||
}
|
||||
|
||||
RefPtr<ResolvePromiseWorkerRunnable> r =
|
||||
new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
|
||||
mPromiseProxy, Move(result),
|
||||
rv.StealNSResult());
|
||||
rv.SuppressException();
|
||||
|
||||
r->Dispatch();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class MatchAllRunnable final : public Runnable
|
||||
{
|
||||
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
nsTArray<ServiceWorkerClientInfo> mValue;
|
||||
|
||||
public:
|
||||
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
PromiseWorkerProxy* aPromiseProxy,
|
||||
nsTArray<ServiceWorkerClientInfo>& aValue)
|
||||
: WorkerRunnable(aWorkerPrivate),
|
||||
mPromiseProxy(aPromiseProxy)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mValue.SwapElements(aValue);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
Promise* promise = mPromiseProxy->WorkerPromise();
|
||||
MOZ_ASSERT(promise);
|
||||
|
||||
nsTArray<RefPtr<ServiceWorkerClient>> ret;
|
||||
for (size_t i = 0; i < mValue.Length(); i++) {
|
||||
ret.AppendElement(RefPtr<ServiceWorkerClient>(
|
||||
new ServiceWorkerWindowClient(promise->GetParentObject(),
|
||||
mValue.ElementAt(i))));
|
||||
}
|
||||
|
||||
promise->MaybeResolve(ret);
|
||||
mPromiseProxy->CleanUp();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
const nsCString mScope;
|
||||
const uint64_t mServiceWorkerID;
|
||||
const bool mIncludeUncontrolled;
|
||||
public:
|
||||
MatchAllRunnable(PromiseWorkerProxy* aPromiseProxy,
|
||||
const nsCString& aScope,
|
||||
uint64_t aServiceWorkerID,
|
||||
bool aIncludeUncontrolled)
|
||||
: mozilla::Runnable("MatchAllRunnable")
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mScope(aScope)
|
||||
, mServiceWorkerID(aServiceWorkerID)
|
||||
, mIncludeUncontrolled(aIncludeUncontrolled)
|
||||
{
|
||||
MOZ_ASSERT(mPromiseProxy);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<ServiceWorkerClientInfo> result;
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(),
|
||||
mScope, mServiceWorkerID, mIncludeUncontrolled,
|
||||
result);
|
||||
}
|
||||
RefPtr<ResolvePromiseWorkerRunnable> r =
|
||||
new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
|
||||
mPromiseProxy, result);
|
||||
|
||||
r->Dispatch();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class ResolveClaimRunnable final : public WorkerRunnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
nsresult mResult;
|
||||
|
||||
public:
|
||||
ResolveClaimRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
PromiseWorkerProxy* aPromiseProxy,
|
||||
nsresult aResult)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mResult(aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
|
||||
MOZ_ASSERT(promise);
|
||||
|
||||
if (NS_SUCCEEDED(mResult)) {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
} else {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
mPromiseProxy->CleanUp();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ClaimRunnable final : public Runnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
nsCString mScope;
|
||||
uint64_t mServiceWorkerID;
|
||||
|
||||
public:
|
||||
ClaimRunnable(PromiseWorkerProxy* aPromiseProxy, const nsCString& aScope)
|
||||
: mozilla::Runnable("ClaimRunnable")
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mScope(aScope)
|
||||
// Safe to call GetWorkerPrivate() since we are being called on the worker
|
||||
// thread via script (so no clean up has occured yet).
|
||||
, mServiceWorkerID(aPromiseProxy->GetWorkerPrivate()->ServiceWorkerID())
|
||||
{
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
// browser shutdown
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
rv = swm->ClaimClients(workerPrivate->GetPrincipal(), mScope,
|
||||
mServiceWorkerID);
|
||||
}
|
||||
|
||||
RefPtr<ResolveClaimRunnable> r =
|
||||
new ResolveClaimRunnable(workerPrivate, mPromiseProxy, rv);
|
||||
|
||||
r->Dispatch();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class ResolveOpenWindowRunnable final : public WorkerRunnable
|
||||
{
|
||||
public:
|
||||
ResolveOpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
|
||||
const nsresult aStatus)
|
||||
: WorkerRunnable(aPromiseProxy->GetWorkerPrivate())
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mClientInfo(Move(aClientInfo))
|
||||
, mStatus(aStatus)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
Promise* promise = mPromiseProxy->WorkerPromise();
|
||||
if (NS_WARN_IF(NS_FAILED(mStatus))) {
|
||||
promise->MaybeReject(mStatus);
|
||||
} else if (mClientInfo) {
|
||||
RefPtr<ServiceWorkerWindowClient> client =
|
||||
new ServiceWorkerWindowClient(promise->GetParentObject(),
|
||||
*mClientInfo);
|
||||
promise->MaybeResolve(client);
|
||||
} else {
|
||||
promise->MaybeResolve(JS::NullHandleValue);
|
||||
}
|
||||
|
||||
mPromiseProxy->CleanUp();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
UniquePtr<ServiceWorkerClientInfo> mClientInfo;
|
||||
const nsresult mStatus;
|
||||
};
|
||||
|
||||
class WebProgressListener final : public nsIWebProgressListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebProgressListener, nsIWebProgressListener)
|
||||
|
||||
WebProgressListener(PromiseWorkerProxy* aPromiseProxy,
|
||||
ServiceWorkerPrivate* aServiceWorkerPrivate,
|
||||
nsPIDOMWindowOuter* aWindow,
|
||||
nsIURI* aBaseURI)
|
||||
: mPromiseProxy(aPromiseProxy)
|
||||
, mServiceWorkerPrivate(aServiceWorkerPrivate)
|
||||
, mWindow(aWindow)
|
||||
, mBaseURI(aBaseURI)
|
||||
{
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
MOZ_ASSERT(aServiceWorkerPrivate);
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aBaseURI);
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mServiceWorkerPrivate->StoreISupports(static_cast<nsIWebProgressListener*>(this));
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aStateFlags, nsresult aStatus) override
|
||||
{
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
||||
!(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Our caller keeps a strong reference, so it is safe to remove the listener
|
||||
// from ServiceWorkerPrivate.
|
||||
mServiceWorkerPrivate->RemoveISupports(static_cast<nsIWebProgressListener*>(this));
|
||||
aWebProgress->RemoveProgressListener(this);
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
||||
UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
||||
if (doc) {
|
||||
// Check same origin.
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
|
||||
mBaseURI, false);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ResolveOpenWindowRunnable> r =
|
||||
new ResolveOpenWindowRunnable(mPromiseProxy,
|
||||
Move(clientInfo),
|
||||
NS_OK);
|
||||
r->Dispatch();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnProgressChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress,
|
||||
int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnLocationChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsIURI* aLocation,
|
||||
uint32_t aFlags) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStatusChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsresult aStatus, const char16_t* aMessage) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSecurityChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aState) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~WebProgressListener()
|
||||
{ }
|
||||
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mWindow;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTION(WebProgressListener, mPromiseProxy,
|
||||
mServiceWorkerPrivate, mWindow)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
class OpenWindowRunnable final : public Runnable
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
nsString mUrl;
|
||||
nsString mScope;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
// Note: |OpenWindowRunnable| cannot be cycle collected because it inherits
|
||||
// thread safe reference counting from |mozilla::Runnable|. On Fennec, we
|
||||
// might use |ServiceWorkerPrivate::StoreISupports| to keep this object alive
|
||||
// while waiting for an event from the observer service. As such, to avoid
|
||||
// creating a cycle that will leak, |OpenWindowRunnable| must not hold a strong
|
||||
// reference to |ServiceWorkerPrivate|.
|
||||
|
||||
OpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aScope)
|
||||
: mozilla::Runnable("OpenWindowRunnable")
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mUrl(aUrl)
|
||||
, mScope(aScope)
|
||||
{
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
|
||||
aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Observe(nsISupports* aSubject, const char* aTopic, const char16_t* /* aData */) override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCString topic(aTopic);
|
||||
if (!topic.EqualsLiteral("BrowserChrome:Ready")) {
|
||||
MOZ_ASSERT(false, "Unexpected topic.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
NS_ENSURE_STATE(os);
|
||||
os->RemoveObserver(this, "BrowserChrome:Ready");
|
||||
|
||||
RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
||||
NS_ENSURE_STATE(swp);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
|
||||
swp->RemoveISupports(static_cast<nsIObserver*>(this));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// This fires an intent that will start launching Fennec and foreground it,
|
||||
// if necessary.
|
||||
if (jni::IsFennec()) {
|
||||
java::GeckoApp::LaunchOrBringToFront();
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window;
|
||||
nsresult rv = OpenWindow(getter_AddRefs(window));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
rv = nsContentUtils::DispatchFocusChromeEvent(window);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
|
||||
if (!webProgress) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
||||
NS_ENSURE_STATE(swp);
|
||||
|
||||
nsCOMPtr<nsIWebProgressListener> listener =
|
||||
new WebProgressListener(mPromiseProxy, swp, window, baseURI);
|
||||
|
||||
rv = webProgress->AddProgressListener(listener,
|
||||
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
else if (rv == NS_ERROR_NOT_AVAILABLE && jni::IsFennec()) {
|
||||
// We couldn't get a browser window, so Fennec must not be running.
|
||||
// Send an Intent to launch Fennec and wait for "BrowserChrome:Ready"
|
||||
// to try opening a window again.
|
||||
RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
|
||||
NS_ENSURE_STATE(swp);
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
NS_ENSURE_STATE(os);
|
||||
|
||||
rv = os->AddObserver(this, "BrowserChrome:Ready", /* weakRef */ true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
swp->StoreISupports(static_cast<nsIObserver*>(this));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
RefPtr<ResolveOpenWindowRunnable> resolveRunnable =
|
||||
new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv);
|
||||
|
||||
Unused << NS_WARN_IF(!resolveRunnable->Dispatch());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~OpenWindowRunnable()
|
||||
{ }
|
||||
|
||||
ServiceWorkerPrivate*
|
||||
GetServiceWorkerPrivate() const
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
// browser shutdown
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
|
||||
MOZ_DIAGNOSTIC_ASSERT(principal);
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
|
||||
registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
|
||||
if (NS_WARN_IF(!serviceWorkerInfo)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return serviceWorkerInfo->WorkerPrivate();
|
||||
}
|
||||
|
||||
nsresult
|
||||
OpenWindow(nsPIDOMWindowOuter** aWindow)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWindow);
|
||||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = workerPrivate->GetPrincipal();
|
||||
MOZ_DIAGNOSTIC_ASSERT(triggeringPrincipal);
|
||||
|
||||
// [[1. Let url be the result of parsing url with entry settings object's API
|
||||
// base URL.]]
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mHref);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mUrl, nullptr, baseURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
// [[6.1 Open Window]]
|
||||
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID,
|
||||
&rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
|
||||
// Let's create a sandbox in order to have a valid JSContext and correctly
|
||||
// propagate the SubjectPrincipal.
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
MOZ_ASSERT(xpc, "This should never be null!");
|
||||
|
||||
JS::Rooted<JSObject*> sandbox(cx);
|
||||
rv = xpc->CreateSandbox(cx, triggeringPrincipal, sandbox.address());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(cx, sandbox);
|
||||
|
||||
// ContentProcess
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
|
||||
NS_ENSURE_STATE(pwwatch);
|
||||
|
||||
nsCString spec;
|
||||
rv = uri->GetSpec(spec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> newWindow;
|
||||
rv = pwwatch->OpenWindow2(nullptr,
|
||||
spec.get(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
false, false, true, nullptr,
|
||||
// Not a spammy popup; we got permission, we swear!
|
||||
/* aIsPopupSpam = */ false,
|
||||
// Don't force noopener. We're not passing in an
|
||||
// opener anyway, and we _do_ want the returned
|
||||
// window.
|
||||
/* aForceNoOpener = */ false,
|
||||
/* aLoadInfp = */ nullptr,
|
||||
getter_AddRefs(newWindow));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
|
||||
pwindow.forget(aWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the most recent browser window and open a new tab in it.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
|
||||
nsContentUtils::GetMostRecentNonPBWindow();
|
||||
if (!browserWindow) {
|
||||
// It is possible to be running without a browser window on Mac OS, so
|
||||
// we need to open a new chrome window.
|
||||
// TODO(catalinb): open new chrome window. Bug 1218080
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow);
|
||||
if (NS_WARN_IF(!chromeWin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBrowserDOMWindow> bwin;
|
||||
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
|
||||
|
||||
if (NS_WARN_IF(!bwin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> win;
|
||||
rv = bwin->OpenURI(uri, nullptr,
|
||||
nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
triggeringPrincipal,
|
||||
getter_AddRefs(win));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
NS_ENSURE_STATE(win);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
|
||||
pWin.forget(aWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(OpenWindowRunnable, Runnable) \
|
||||
NS_IMPL_RELEASE_INHERITED(OpenWindowRunnable, Runnable)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(OpenWindowRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
} // namespace
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerClients::Get(const nsAString& aClientId, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (!promiseProxy) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
RefPtr<GetRunnable> r =
|
||||
new GetRunnable(promiseProxy, aClientId);
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsString scope;
|
||||
mWorkerScope->GetScope(scope);
|
||||
|
||||
if (aOptions.mType != ClientType::Window) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (!promiseProxy) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
RefPtr<MatchAllRunnable> r =
|
||||
new MatchAllRunnable(promiseProxy,
|
||||
NS_ConvertUTF16toUTF8(scope),
|
||||
workerPrivate->ServiceWorkerID(),
|
||||
aOptions.mIncludeUncontrolled);
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerClients::OpenWindow(const nsAString& aUrl,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aUrl.EqualsLiteral("about:blank")) {
|
||||
promise->MaybeReject(NS_ERROR_TYPE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// [[4. If this algorithm is not allowed to show a popup ..]]
|
||||
// In Gecko the service worker is allowed to show a popup only if the user
|
||||
// just clicked on a notification.
|
||||
if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
|
||||
if (!promiseProxy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsString scope;
|
||||
mWorkerScope->GetScope(scope);
|
||||
|
||||
RefPtr<OpenWindowRunnable> r = new OpenWindowRunnable(promiseProxy,
|
||||
aUrl, scope);
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerClients::Claim(ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (!promiseProxy) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
nsString scope;
|
||||
mWorkerScope->GetScope(scope);
|
||||
|
||||
RefPtr<ClaimRunnable> runnable =
|
||||
new ClaimRunnable(promiseProxy, NS_ConvertUTF16toUTF8(scope));
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(runnable.forget()));
|
||||
return promise.forget();
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_workers_serviceworkerclients_h
|
||||
#define mozilla_dom_workers_serviceworkerclients_h
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/WorkerScope.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ClientsBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerClients final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClients)
|
||||
|
||||
explicit ServiceWorkerClients(ServiceWorkerGlobalScope* aWorkerScope);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Get(const nsAString& aClientId, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
OpenWindow(const nsAString& aUrl, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Claim(ErrorResult& aRv);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
ServiceWorkerGlobalScope*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mWorkerScope;
|
||||
}
|
||||
|
||||
private:
|
||||
~ServiceWorkerClients()
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerGlobalScope> mWorkerScope;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_workers_serviceworkerclients_h
|
|
@ -24,13 +24,13 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/BodyUtil.h"
|
||||
#include "mozilla/dom/Client.h"
|
||||
#include "mozilla/dom/FetchEventBinding.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
|
|
|
@ -25,6 +25,7 @@ class nsIInterceptedChannel;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Blob;
|
||||
class Client;
|
||||
class MessagePort;
|
||||
class Request;
|
||||
class ResponseOrPromise;
|
||||
|
@ -269,7 +270,7 @@ class ExtendableMessageEvent final : public ExtendableEvent
|
|||
JS::Heap<JS::Value> mData;
|
||||
nsString mOrigin;
|
||||
nsString mLastEventId;
|
||||
RefPtr<ServiceWorkerClient> mClient;
|
||||
RefPtr<Client> mClient;
|
||||
RefPtr<ServiceWorker> mServiceWorker;
|
||||
RefPtr<MessagePort> mMessagePort;
|
||||
nsTArray<RefPtr<MessagePort>> mPorts;
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
|
||||
#include "RuntimeService.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerContainer.h"
|
||||
#include "ServiceWorkerInfo.h"
|
||||
#include "ServiceWorkerJobQueue.h"
|
||||
|
@ -2302,8 +2301,7 @@ ServiceWorkerManager::MaybeRemoveRegistrationInfo(const nsACString& aScopeKey)
|
|||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc,
|
||||
const nsAString& aDocumentId)
|
||||
ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
@ -2311,7 +2309,7 @@ ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc,
|
|||
GetServiceWorkerRegistrationInfo(aDoc);
|
||||
if (registration) {
|
||||
MOZ_ASSERT(!mControlledDocuments.Contains(aDoc));
|
||||
StartControllingADocument(registration, aDoc, aDocumentId);
|
||||
StartControllingADocument(registration, aDoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2353,8 +2351,7 @@ ServiceWorkerManager::MaybeCheckNavigationUpdate(nsIDocument* aDoc)
|
|||
|
||||
RefPtr<GenericPromise>
|
||||
ServiceWorkerManager::StartControllingADocument(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsIDocument* aDoc,
|
||||
const nsAString& aDocumentId)
|
||||
nsIDocument* aDoc)
|
||||
{
|
||||
MOZ_ASSERT(aRegistration);
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
@ -2368,9 +2365,6 @@ ServiceWorkerManager::StartControllingADocument(ServiceWorkerRegistrationInfo* a
|
|||
|
||||
aRegistration->StartControllingADocument();
|
||||
mControlledDocuments.Put(aDoc, aRegistration);
|
||||
if (!aDocumentId.IsEmpty()) {
|
||||
aDoc->SetId(aDocumentId);
|
||||
}
|
||||
|
||||
// Mark the document's ClientSource as controlled using the ClientHandle
|
||||
// interface. While we could get at the ClientSource directly from the
|
||||
|
@ -2564,20 +2558,17 @@ class ContinueDispatchFetchEventRunnable : public Runnable
|
|||
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
|
||||
nsCOMPtr<nsIInterceptedChannel> mChannel;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsString mDocumentId;
|
||||
bool mIsReload;
|
||||
public:
|
||||
ContinueDispatchFetchEventRunnable(
|
||||
ServiceWorkerPrivate* aServiceWorkerPrivate,
|
||||
nsIInterceptedChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aDocumentId,
|
||||
bool aIsReload)
|
||||
: Runnable("dom::workers::ContinueDispatchFetchEventRunnable")
|
||||
, mServiceWorkerPrivate(aServiceWorkerPrivate)
|
||||
, mChannel(aChannel)
|
||||
, mLoadGroup(aLoadGroup)
|
||||
, mDocumentId(aDocumentId)
|
||||
, mIsReload(aIsReload)
|
||||
{
|
||||
MOZ_ASSERT(aServiceWorkerPrivate);
|
||||
|
@ -2618,8 +2609,19 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mServiceWorkerPrivate->SendFetchEvent(mChannel, mLoadGroup,
|
||||
mDocumentId, mIsReload);
|
||||
nsString clientId;
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
if (loadInfo) {
|
||||
Maybe<ClientInfo> clientInfo = loadInfo->GetClientInfo();
|
||||
if (clientInfo.isSome()) {
|
||||
char buf[NSID_LENGTH];
|
||||
clientInfo.ref().Id().ToProvidedString(buf);
|
||||
CopyUTF8toUTF16(nsDependentCString(buf), clientId);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mServiceWorkerPrivate->SendFetchEvent(mChannel, mLoadGroup, clientId,
|
||||
mIsReload);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
HandleError();
|
||||
}
|
||||
|
@ -2633,7 +2635,6 @@ public:
|
|||
void
|
||||
ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
|
||||
nsIDocument* aDoc,
|
||||
const nsAString& aDocumentIdForTopLevelNavigation,
|
||||
nsIInterceptedChannel* aChannel,
|
||||
bool aIsReload,
|
||||
bool aIsSubresourceLoad,
|
||||
|
@ -2644,7 +2645,6 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
|
|||
|
||||
RefPtr<ServiceWorkerInfo> serviceWorker;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
nsAutoString documentId;
|
||||
|
||||
if (aIsSubresourceLoad) {
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
@ -2656,10 +2656,6 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
|
|||
}
|
||||
|
||||
loadGroup = aDoc->GetDocumentLoadGroup();
|
||||
nsresult rv = aDoc->GetOrCreateId(documentId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIChannel> internalChannel;
|
||||
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
|
||||
|
@ -2669,9 +2665,6 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
|
|||
|
||||
internalChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
|
||||
// TODO: Use aDocumentIdForTopLevelNavigation for potentialClientId, pending
|
||||
// the spec change.
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aRv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -2751,8 +2744,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
|
|||
|
||||
nsCOMPtr<nsIRunnable> continueRunnable =
|
||||
new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(),
|
||||
aChannel, loadGroup,
|
||||
documentId, aIsReload);
|
||||
aChannel, loadGroup, aIsReload);
|
||||
|
||||
// When this service worker was registered, we also sent down the permissions
|
||||
// for the runnable. They should have arrived by now, but we still need to
|
||||
|
@ -2846,22 +2838,42 @@ ServiceWorkerManager::GetDocumentController(nsPIDOMWindowInner* aWindow,
|
|||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (!doc) {
|
||||
Maybe<ServiceWorkerDescriptor> controller = aWindow->GetController();
|
||||
if (controller.isNothing()) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
nsresult rv = GetDocumentRegistration(doc, getter_AddRefs(registration));
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
if (NS_WARN_IF(!principal)) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = PrincipalToScopeKey(principal, scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(registration->GetActive());
|
||||
RefPtr<ServiceWorker> serviceWorker =
|
||||
registration->GetActive()->GetOrCreateInstance(aWindow);
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(scopeKey, controller.ref().Scope());
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerInfo> active = registration->GetActive();
|
||||
if (NS_WARN_IF(!active) ||
|
||||
NS_WARN_IF(active->Descriptor().Id() != controller.ref().Id())) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker> serviceWorker = active->GetOrCreateInstance(aWindow);
|
||||
serviceWorker.forget(aServiceWorker);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3166,208 +3178,19 @@ ServiceWorkerManager::UpdateInternal(nsIPrincipal* aPrincipal,
|
|||
queue->ScheduleJob(job);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static void
|
||||
FireControllerChangeOnDocument(nsIDocument* aDocument)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> w = aDocument->GetInnerWindow();
|
||||
if (!w) {
|
||||
NS_WARNING("Failed to dispatch controllerchange event");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* window = nsGlobalWindowInner::Cast(w.get());
|
||||
dom::Navigator* navigator = window->Navigator();
|
||||
if (!navigator) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
|
||||
ErrorResult result;
|
||||
container->ControllerChanged(result);
|
||||
if (result.Failed()) {
|
||||
NS_WARNING("Failed to dispatch controllerchange event");
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
UniquePtr<ServiceWorkerClientInfo>
|
||||
ServiceWorkerManager::GetClient(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aClientId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
||||
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
|
||||
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
|
||||
if (NS_WARN_IF(!ifptr)) {
|
||||
return clientInfo;
|
||||
}
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (NS_WARN_IF(!obs)) {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
nsresult rv = obs->NotifyObservers(ifptr, "service-worker-get-client",
|
||||
PromiseFlatString(aClientId).get());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> ptr;
|
||||
ifptr->GetData(getter_AddRefs(ptr));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
||||
if (NS_WARN_IF(!doc || !doc->GetInnerWindow())) {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
bool equals = false;
|
||||
aPrincipal->Equals(doc->NodePrincipal(), &equals);
|
||||
if (!equals) {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
if (!IsFromAuthenticatedOrigin(doc)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
// Don't let service worker see 3rd party iframes that are denied storage
|
||||
// access. We don't want these to communicate.
|
||||
auto storageAccess =
|
||||
nsContentUtils::StorageAllowedForWindow(doc->GetInnerWindow());
|
||||
if (storageAccess != nsContentUtils::StorageAccess::eAllow) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Service Workers"), doc,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"ServiceWorkerGetClientStorageError");
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::GetAllClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
uint64_t aServiceWorkerID,
|
||||
bool aIncludeUncontrolled,
|
||||
nsTArray<ServiceWorkerClientInfo>& aDocuments)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(aPrincipal, aScope);
|
||||
|
||||
if (!registration) {
|
||||
// The registration was removed, leave the array empty.
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (NS_WARN_IF(!obs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
nsresult rv = obs->EnumerateObservers("service-worker-get-client",
|
||||
getter_AddRefs(enumerator));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a list of Client documents out of the observer service
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 32> docList;
|
||||
bool loop = true;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&loop)) && loop) {
|
||||
nsCOMPtr<nsISupports> ptr;
|
||||
rv = enumerator->GetNext(getter_AddRefs(ptr));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
||||
if (!doc || !doc->GetWindow() || !doc->GetInnerWindow()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool equals = false;
|
||||
Unused << aPrincipal->Equals(doc->NodePrincipal(), &equals);
|
||||
if (!equals) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Treat http windows with devtools opened as secure if the correct devtools
|
||||
// setting is enabled.
|
||||
if (!doc->GetWindow()->GetServiceWorkersTestingEnabled() &&
|
||||
!Preferences::GetBool("dom.serviceWorkers.testing.enabled") &&
|
||||
!IsFromAuthenticatedOrigin(doc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't let service worker find 3rd party iframes that are denied storage
|
||||
// access. We don't want these to communicate.
|
||||
auto storageAccess =
|
||||
nsContentUtils::StorageAllowedForWindow(doc->GetInnerWindow());
|
||||
if (storageAccess != nsContentUtils::StorageAccess::eAllow) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Service Workers"),
|
||||
doc, nsContentUtils::eDOM_PROPERTIES,
|
||||
"ServiceWorkerGetClientStorageError");
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are only returning controlled Clients then skip any documents
|
||||
// that are for different registrations. We also skip service workers
|
||||
// that don't match the ID of our calling service worker. We should
|
||||
// only return Clients controlled by that precise service worker.
|
||||
if (!aIncludeUncontrolled) {
|
||||
ServiceWorkerRegistrationInfo* reg = mControlledDocuments.GetWeak(doc);
|
||||
if (!reg || reg->mScope != aScope || !reg->GetActive() ||
|
||||
reg->GetActive()->ID() != aServiceWorkerID) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aIncludeUncontrolled && !mControlledDocuments.Contains(doc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
docList.AppendElement(doc.forget());
|
||||
}
|
||||
|
||||
// The observer service gives us the list in reverse creation order.
|
||||
// We need to maintain creation order, so reverse the list before
|
||||
// processing.
|
||||
docList.Reverse();
|
||||
|
||||
// Finally convert to the list of ServiceWorkerClientInfo objects.
|
||||
uint32_t ordinal = 0;
|
||||
for (uint32_t i = 0; i < docList.Length(); ++i) {
|
||||
aDocuments.AppendElement(ServiceWorkerClientInfo(docList[i], ordinal));
|
||||
ordinal += 1;
|
||||
}
|
||||
|
||||
aDocuments.Sort();
|
||||
}
|
||||
|
||||
void
|
||||
already_AddRefed<GenericPromise>
|
||||
ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
||||
ServiceWorkerRegistrationInfo* aWorkerRegistration)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerRegistration);
|
||||
MOZ_ASSERT(aWorkerRegistration->GetActive());
|
||||
|
||||
RefPtr<GenericPromise> ref;
|
||||
|
||||
// Same origin check
|
||||
if (!aWorkerRegistration->mPrincipal->Equals(aDocument->NodePrincipal())) {
|
||||
return;
|
||||
ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_SECURITY_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// The registration that should be controlling the client
|
||||
|
@ -3379,56 +3202,41 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
|||
GetDocumentRegistration(aDocument, getter_AddRefs(controllingRegistration));
|
||||
|
||||
if (aWorkerRegistration != matchingRegistration ||
|
||||
aWorkerRegistration == controllingRegistration) {
|
||||
return;
|
||||
aWorkerRegistration == controllingRegistration) {
|
||||
ref = GenericPromise::CreateAndResolve(true, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
if (controllingRegistration) {
|
||||
StopControllingADocument(controllingRegistration);
|
||||
}
|
||||
|
||||
StartControllingADocument(aWorkerRegistration, aDocument, NS_LITERAL_STRING(""));
|
||||
FireControllerChangeOnDocument(aDocument);
|
||||
ref = StartControllingADocument(aWorkerRegistration, aDocument);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
ServiceWorkerManager::ClaimClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope, uint64_t aId)
|
||||
already_AddRefed<GenericPromise>
|
||||
ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDoc,
|
||||
const ServiceWorkerDescriptor& aServiceWorker)
|
||||
{
|
||||
RefPtr<GenericPromise> ref;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(aServiceWorker.PrincipalInfo());
|
||||
if (!principal) {
|
||||
ref = GenericPromise::CreateAndResolve(false, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(aPrincipal, aScope);
|
||||
|
||||
if (!registration || !registration->GetActive() ||
|
||||
!(registration->GetActive()->ID() == aId)) {
|
||||
// The worker is not active.
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
GetRegistration(principal, aServiceWorker.Scope());
|
||||
if (!registration) {
|
||||
ref = GenericPromise::CreateAndResolve(false, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (NS_WARN_IF(!obs)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
nsresult rv = obs->EnumerateObservers("service-worker-get-client",
|
||||
getter_AddRefs(enumerator));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool loop = true;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&loop)) && loop) {
|
||||
nsCOMPtr<nsISupports> ptr;
|
||||
rv = enumerator->GetNext(getter_AddRefs(ptr));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(ptr);
|
||||
MaybeClaimClient(doc, registration);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
ref = MaybeClaimClient(aDoc, registration);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3457,11 +3265,14 @@ ServiceWorkerManager::SetSkipWaitingFlag(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
ServiceWorkerManager::UpdateClientControllers(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 16> documents;
|
||||
RefPtr<ServiceWorkerInfo> activeWorker = aRegistration->GetActive();
|
||||
MOZ_DIAGNOSTIC_ASSERT(activeWorker);
|
||||
|
||||
AutoTArray<nsCOMPtr<nsPIDOMWindowInner>, 16> innerWindows;
|
||||
for (auto iter = mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData() != aRegistration) {
|
||||
continue;
|
||||
|
@ -3472,13 +3283,24 @@ ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegis
|
|||
continue;
|
||||
}
|
||||
|
||||
documents.AppendElement(doc);
|
||||
nsPIDOMWindowInner* innerWindow = doc->GetInnerWindow();
|
||||
if (NS_WARN_IF(!innerWindow)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
innerWindows.AppendElement(innerWindow);
|
||||
}
|
||||
|
||||
// Fire event after iterating mControlledDocuments is done to prevent
|
||||
// modification by reentering from the event handlers during iteration.
|
||||
for (auto& doc : documents) {
|
||||
FireControllerChangeOnDocument(doc);
|
||||
for (auto& innerWindow : innerWindows) {
|
||||
Maybe<ClientInfo> clientInfo = innerWindow->GetClientInfo();
|
||||
if (clientInfo.isSome()) {
|
||||
RefPtr<ClientHandle> clientHandle =
|
||||
ClientManager::CreateHandle(clientInfo.ref(),
|
||||
innerWindow->EventTargetFor(TaskCategory::Other));
|
||||
clientHandle->Control(activeWorker->Descriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ class ServiceWorkerRegistrationListener;
|
|||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerClientInfo;
|
||||
class ServiceWorkerInfo;
|
||||
class ServiceWorkerJobQueue;
|
||||
class ServiceWorkerManagerChild;
|
||||
|
@ -151,7 +150,6 @@ public:
|
|||
void
|
||||
DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
|
||||
nsIDocument* aDoc,
|
||||
const nsAString& aDocumentIdForTopLevelNavigation,
|
||||
nsIInterceptedChannel* aChannel,
|
||||
bool aIsReload,
|
||||
bool aIsSubresourceLoad,
|
||||
|
@ -273,24 +271,13 @@ public:
|
|||
uint32_t aFlags,
|
||||
JSExnType aExnType);
|
||||
|
||||
UniquePtr<ServiceWorkerClientInfo>
|
||||
GetClient(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aClientId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetAllClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
uint64_t aServiceWorkerID,
|
||||
bool aIncludeUncontrolled,
|
||||
nsTArray<ServiceWorkerClientInfo>& aDocuments);
|
||||
|
||||
void
|
||||
already_AddRefed<GenericPromise>
|
||||
MaybeClaimClient(nsIDocument* aDocument,
|
||||
ServiceWorkerRegistrationInfo* aWorkerRegistration);
|
||||
|
||||
nsresult
|
||||
ClaimClients(nsIPrincipal* aPrincipal, const nsCString& aScope, uint64_t aId);
|
||||
already_AddRefed<GenericPromise>
|
||||
MaybeClaimClient(nsIDocument* aDoc,
|
||||
const ServiceWorkerDescriptor& aServiceWorker);
|
||||
|
||||
void
|
||||
SetSkipWaitingFlag(nsIPrincipal* aPrincipal, const nsCString& aScope,
|
||||
|
@ -393,8 +380,7 @@ private:
|
|||
|
||||
RefPtr<GenericPromise>
|
||||
StartControllingADocument(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsIDocument* aDoc,
|
||||
const nsAString& aDocumentId);
|
||||
nsIDocument* aDoc);
|
||||
|
||||
void
|
||||
StopControllingADocument(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
@ -441,7 +427,7 @@ private:
|
|||
FireUpdateFoundOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
UpdateClientControllers(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
StorePendingReadyPromise(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "ServiceWorkerPrivate.h"
|
||||
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerWindowClient.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
|
@ -26,6 +25,8 @@
|
|||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/Client.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/FetchUtil.h"
|
||||
#include "mozilla/dom/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/InternalHeaders.h"
|
||||
|
@ -40,6 +41,8 @@ using namespace mozilla::dom;
|
|||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
using mozilla::ipc::PrincipalInfo;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(ServiceWorkerPrivate)
|
||||
NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(ServiceWorkerPrivate)
|
||||
NS_IMPL_CYCLE_COLLECTION(ServiceWorkerPrivate, mSupportsArray)
|
||||
|
@ -484,22 +487,21 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class SendMesssageEventRunnable final : public ExtendableEventWorkerRunnable
|
||||
, public StructuredCloneHolder
|
||||
class SendMessageEventRunnable final : public ExtendableEventWorkerRunnable
|
||||
, public StructuredCloneHolder
|
||||
{
|
||||
UniquePtr<ServiceWorkerClientInfo> mEventSource;
|
||||
const ClientInfoAndState mClientInfoAndState;
|
||||
|
||||
public:
|
||||
SendMesssageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
KeepAliveToken* aKeepAliveToken,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aEventSource)
|
||||
SendMessageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
KeepAliveToken* aKeepAliveToken,
|
||||
const ClientInfoAndState& aClientInfoAndState)
|
||||
: ExtendableEventWorkerRunnable(aWorkerPrivate, aKeepAliveToken)
|
||||
, StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcessDifferentThread)
|
||||
, mEventSource(Move(aEventSource))
|
||||
, mClientInfoAndState(aClientInfoAndState)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mEventSource);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -518,8 +520,6 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerClient> client = new ServiceWorkerWindowClient(sgo,
|
||||
*mEventSource);
|
||||
RootedDictionary<ExtendableMessageEventInit> init(aCx);
|
||||
|
||||
init.mBubbles = false;
|
||||
|
@ -527,7 +527,8 @@ public:
|
|||
|
||||
init.mData = messageData;
|
||||
init.mPorts = ports;
|
||||
init.mSource.SetValue().SetAsClient() = client;
|
||||
init.mSource.SetValue().SetAsClient() =
|
||||
new Client(sgo, mClientInfoAndState);
|
||||
|
||||
RefPtr<EventTarget> target = aWorkerPrivate->GlobalScope();
|
||||
RefPtr<ExtendableMessageEvent> extendableEvent =
|
||||
|
@ -553,7 +554,7 @@ nsresult
|
|||
ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
||||
const ClientInfoAndState& aClientInfoAndState)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
|
@ -571,8 +572,8 @@ ServiceWorkerPrivate::SendMessageEvent(JSContext* aCx,
|
|||
}
|
||||
|
||||
RefPtr<KeepAliveToken> token = CreateEventKeepAliveToken();
|
||||
RefPtr<SendMesssageEventRunnable> runnable =
|
||||
new SendMesssageEventRunnable(mWorkerPrivate, token, Move(aClientInfo));
|
||||
RefPtr<SendMessageEventRunnable> runnable =
|
||||
new SendMessageEventRunnable(mWorkerPrivate, token, aClientInfoAndState);
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
|
@ -1334,6 +1335,7 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
|
|||
RequestCredentials mRequestCredentials;
|
||||
nsContentPolicyType mContentPolicyType;
|
||||
nsCOMPtr<nsIInputStream> mUploadStream;
|
||||
int64_t mUploadStreamContentLength;
|
||||
nsCString mReferrer;
|
||||
ReferrerPolicy mReferrerPolicy;
|
||||
nsString mIntegrity;
|
||||
|
@ -1345,14 +1347,14 @@ public:
|
|||
// later on.
|
||||
const nsACString& aScriptSpec,
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
|
||||
const nsAString& aDocumentId,
|
||||
const nsAString& aClientId,
|
||||
bool aIsReload,
|
||||
bool aMarkLaunchServiceWorkerEnd)
|
||||
: ExtendableFunctionalEventWorkerRunnable(
|
||||
aWorkerPrivate, aKeepAliveToken, aRegistration)
|
||||
, mInterceptedChannel(aChannel)
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mClientId(aDocumentId)
|
||||
, mClientId(aClientId)
|
||||
, mIsReload(aIsReload)
|
||||
, mMarkLaunchServiceWorkerEnd(aMarkLaunchServiceWorkerEnd)
|
||||
, mCacheMode(RequestCache::Default)
|
||||
|
@ -1362,6 +1364,7 @@ public:
|
|||
// send credentials to same-origin websites unless explicitly forbidden.
|
||||
, mRequestCredentials(RequestCredentials::Same_origin)
|
||||
, mContentPolicyType(nsIContentPolicy::TYPE_INVALID)
|
||||
, mUploadStreamContentLength(-1)
|
||||
, mReferrer(kFETCH_CLIENT_REFERRER_STR)
|
||||
, mReferrerPolicy(ReferrerPolicy::_empty)
|
||||
{
|
||||
|
@ -1495,7 +1498,8 @@ public:
|
|||
if (uploadChannel) {
|
||||
MOZ_ASSERT(!mUploadStream);
|
||||
nsCOMPtr<nsIInputStream> uploadStream;
|
||||
rv = uploadChannel->CloneUploadStream(getter_AddRefs(uploadStream));
|
||||
rv = uploadChannel->CloneUploadStream(&mUploadStreamContentLength,
|
||||
getter_AddRefs(uploadStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mUploadStream = uploadStream;
|
||||
}
|
||||
|
@ -1605,7 +1609,7 @@ private:
|
|||
mReferrerPolicy,
|
||||
mContentPolicyType,
|
||||
mIntegrity);
|
||||
internalReq->SetBody(mUploadStream, -1);
|
||||
internalReq->SetBody(mUploadStream, mUploadStreamContentLength);
|
||||
// For Telemetry, note that this Request object was created by a Fetch event.
|
||||
internalReq->SetCreatedByFetchEvent();
|
||||
|
||||
|
@ -1637,7 +1641,11 @@ private:
|
|||
init.mRequest = request;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = true;
|
||||
if (!mClientId.IsEmpty()) {
|
||||
// Only expose the FetchEvent.clientId on subresource requests for now.
|
||||
// Once we implement .resultingClientId and .targetClientId we can then
|
||||
// start exposing .clientId on non-subresource requests as well. See
|
||||
// bug 1264177.
|
||||
if (!mClientId.IsEmpty() && !internalReq->IsNavigationRequest()) {
|
||||
init.mClientId = mClientId;
|
||||
}
|
||||
init.mIsReload = mIsReload;
|
||||
|
@ -1683,8 +1691,7 @@ NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVis
|
|||
nsresult
|
||||
ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aDocumentId,
|
||||
bool aIsReload)
|
||||
const nsAString& aClientId, bool aIsReload)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
|
@ -1761,7 +1768,7 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
|||
RefPtr<FetchEventRunnable> r =
|
||||
new FetchEventRunnable(mWorkerPrivate, token, handle,
|
||||
mInfo->ScriptSpec(), regInfo,
|
||||
aDocumentId, aIsReload, newWorkerCreated);
|
||||
aClientId, aIsReload, newWorkerCreated);
|
||||
rv = r->Init();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -1910,7 +1917,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
|
|||
scriptSpec,
|
||||
false, WorkerTypeService,
|
||||
VoidString(),
|
||||
mInfo->Scope(),
|
||||
EmptyCString(),
|
||||
&info, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
|
|
|
@ -18,6 +18,9 @@ class nsIInterceptedChannel;
|
|||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientInfoAndState;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerInfo;
|
||||
|
@ -85,7 +88,7 @@ public:
|
|||
nsresult
|
||||
SendMessageEvent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo);
|
||||
const ClientInfoAndState& aClientInfoAndState);
|
||||
|
||||
// This is used to validate the worker script and continue the installation
|
||||
// process.
|
||||
|
@ -119,10 +122,8 @@ public:
|
|||
const nsAString& aScope);
|
||||
|
||||
nsresult
|
||||
SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aDocumentId,
|
||||
bool aIsReload);
|
||||
SendFetchEvent(nsIInterceptedChannel* aChannel, nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aClientId, bool aIsReload);
|
||||
|
||||
void
|
||||
StoreISupports(nsISupports* aSupports);
|
||||
|
|
|
@ -274,13 +274,8 @@ ServiceWorkerRegistrationInfo::Activate()
|
|||
// FIXME(nsm): Unlink appcache if there is one.
|
||||
|
||||
// "Queue a task to fire a simple event named controllerchange..."
|
||||
nsCOMPtr<nsIRunnable> controllerChangeRunnable =
|
||||
NewRunnableMethod<RefPtr<ServiceWorkerRegistrationInfo>>(
|
||||
"dom::workers::ServiceWorkerManager::FireControllerChange",
|
||||
swm,
|
||||
&ServiceWorkerManager::FireControllerChange,
|
||||
this);
|
||||
NS_DispatchToMainThread(controllerChangeRunnable);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mActiveWorker);
|
||||
swm->UpdateClientControllers(this);
|
||||
|
||||
nsCOMPtr<nsIRunnable> failRunnable = NewRunnableMethod<bool>(
|
||||
"dom::workers::ServiceWorkerRegistrationInfo::FinishActivate",
|
||||
|
|
|
@ -1,556 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "ServiceWorkerWindowClient.h"
|
||||
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/dom/ClientBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerInfo.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
using mozilla::UniquePtr;
|
||||
|
||||
JSObject*
|
||||
ServiceWorkerWindowClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return WindowClientBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ResolveOrRejectPromiseRunnable final : public WorkerRunnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
UniquePtr<ServiceWorkerClientInfo> mClientInfo;
|
||||
nsresult mRv;
|
||||
|
||||
public:
|
||||
// Passing a null clientInfo will resolve the promise with a null value.
|
||||
ResolveOrRejectPromiseRunnable(
|
||||
WorkerPrivate* aWorkerPrivate, PromiseWorkerProxy* aPromiseProxy,
|
||||
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mClientInfo(Move(aClientInfo))
|
||||
, mRv(NS_OK)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
// Reject the promise with passed nsresult.
|
||||
ResolveOrRejectPromiseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
PromiseWorkerProxy* aPromiseProxy,
|
||||
nsresult aRv)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mClientInfo(nullptr)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_FAILED(aRv));
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
|
||||
MOZ_ASSERT(promise);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(mRv))) {
|
||||
promise->MaybeReject(mRv);
|
||||
} else if (mClientInfo) {
|
||||
RefPtr<ServiceWorkerWindowClient> client =
|
||||
new ServiceWorkerWindowClient(promise->GetParentObject(), *mClientInfo);
|
||||
promise->MaybeResolve(client);
|
||||
} else {
|
||||
promise->MaybeResolve(JS::NullHandleValue);
|
||||
}
|
||||
|
||||
// Release the reference on the worker thread.
|
||||
mPromiseProxy->CleanUp();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ClientFocusRunnable final : public Runnable
|
||||
{
|
||||
uint64_t mWindowId;
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
|
||||
public:
|
||||
ClientFocusRunnable(uint64_t aWindowId, PromiseWorkerProxy* aPromiseProxy)
|
||||
: mozilla::Runnable("ClientFocusRunnable")
|
||||
, mWindowId(aWindowId)
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
{
|
||||
MOZ_ASSERT(mPromiseProxy);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsGlobalWindowInner* window =
|
||||
nsGlobalWindowInner::GetInnerWindowWithId(mWindowId);
|
||||
UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIDocument> doc = window->GetDocument();
|
||||
if (doc) {
|
||||
nsContentUtils::DispatchFocusChromeEvent(window->GetOuterWindow());
|
||||
clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
||||
}
|
||||
}
|
||||
|
||||
DispatchResult(Move(clientInfo));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
DispatchResult(UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable;
|
||||
if (aClientInfo) {
|
||||
resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
||||
mPromiseProxy->GetWorkerPrivate(), mPromiseProxy, Move(aClientInfo));
|
||||
} else {
|
||||
resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
||||
mPromiseProxy->GetWorkerPrivate(), mPromiseProxy,
|
||||
NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
}
|
||||
|
||||
resolveRunnable->Dispatch();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (promiseProxy) {
|
||||
RefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId,
|
||||
promiseProxy);
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
||||
} else {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
}
|
||||
|
||||
} else {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
class WebProgressListener final : public nsIWebProgressListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebProgressListener,
|
||||
nsIWebProgressListener)
|
||||
|
||||
WebProgressListener(PromiseWorkerProxy* aPromiseProxy,
|
||||
ServiceWorkerPrivate* aServiceWorkerPrivate,
|
||||
nsPIDOMWindowOuter* aWindow, nsIURI* aBaseURI)
|
||||
: mPromiseProxy(aPromiseProxy)
|
||||
, mServiceWorkerPrivate(aServiceWorkerPrivate)
|
||||
, mWindow(aWindow)
|
||||
, mBaseURI(aBaseURI)
|
||||
{
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
MOZ_ASSERT(aServiceWorkerPrivate);
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aBaseURI);
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mServiceWorkerPrivate->StoreISupports(static_cast<nsIWebProgressListener*>(this));
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
uint32_t aStateFlags, nsresult aStatus) override
|
||||
{
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
||||
!(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// This is safe because our caller holds a strong ref.
|
||||
mServiceWorkerPrivate->RemoveISupports(static_cast<nsIWebProgressListener*>(this));
|
||||
aWebProgress->RemoveProgressListener(this);
|
||||
|
||||
WorkerPrivate* workerPrivate;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
||||
|
||||
RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable;
|
||||
UniquePtr<ServiceWorkerClientInfo> clientInfo;
|
||||
if (!doc) {
|
||||
resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
||||
workerPrivate, mPromiseProxy, NS_ERROR_TYPE_ERR);
|
||||
resolveRunnable->Dispatch();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check same origin.
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
|
||||
mBaseURI, false);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsContentUtils::DispatchFocusChromeEvent(mWindow->GetOuterWindow());
|
||||
clientInfo.reset(new ServiceWorkerClientInfo(doc));
|
||||
}
|
||||
|
||||
resolveRunnable = new ResolveOrRejectPromiseRunnable(
|
||||
workerPrivate, mPromiseProxy, Move(clientInfo));
|
||||
resolveRunnable->Dispatch();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnProgressChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
nsIURI* aLocation, uint32_t aFlags) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
nsresult aStatus, const char16_t* aMessage) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
uint32_t aState) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~WebProgressListener() {}
|
||||
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mWindow;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebProgressListener)
|
||||
NS_IMPL_CYCLE_COLLECTION(WebProgressListener, mPromiseProxy,
|
||||
mServiceWorkerPrivate, mWindow)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
class ClientNavigateRunnable final : public Runnable
|
||||
{
|
||||
uint64_t mWindowId;
|
||||
nsString mUrl;
|
||||
nsCString mBaseUrl;
|
||||
nsString mScope;
|
||||
RefPtr<PromiseWorkerProxy> mPromiseProxy;
|
||||
MOZ_INIT_OUTSIDE_CTOR WorkerPrivate* mWorkerPrivate;
|
||||
|
||||
public:
|
||||
ClientNavigateRunnable(uint64_t aWindowId,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aScope,
|
||||
PromiseWorkerProxy* aPromiseProxy)
|
||||
: mozilla::Runnable("ClientNavigateRunnable")
|
||||
, mWindowId(aWindowId)
|
||||
, mUrl(aUrl)
|
||||
, mScope(aScope)
|
||||
, mPromiseProxy(aPromiseProxy)
|
||||
, mWorkerPrivate(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aPromiseProxy);
|
||||
MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
|
||||
aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mWorkerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
|
||||
mBaseUrl = info.mHref;
|
||||
principal = mWorkerPrivate->GetPrincipal();
|
||||
MOZ_DIAGNOSTIC_ASSERT(principal);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> baseUrl;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsresult rv = ParseUrl(getter_AddRefs(baseUrl), getter_AddRefs(url));
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return RejectPromise(NS_ERROR_TYPE_ERR);
|
||||
}
|
||||
|
||||
nsGlobalWindowInner* window;
|
||||
rv = Navigate(url, principal, &window);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return RejectPromise(rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
if (NS_WARN_IF(!webProgress)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
|
||||
registration->GetServiceWorkerInfoById(mWorkerPrivate->ServiceWorkerID());
|
||||
if (NS_WARN_IF(!serviceWorkerInfo)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebProgressListener> listener =
|
||||
new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(),
|
||||
window->GetOuterWindow(), baseUrl);
|
||||
|
||||
rv = webProgress->AddProgressListener(
|
||||
listener, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return RejectPromise(rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult
|
||||
RejectPromise(nsresult aRv)
|
||||
{
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
|
||||
new ResolveOrRejectPromiseRunnable(mWorkerPrivate, mPromiseProxy, aRv);
|
||||
|
||||
resolveRunnable->Dispatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolvePromise(UniquePtr<ServiceWorkerClientInfo>&& aClientInfo)
|
||||
{
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
|
||||
new ResolveOrRejectPromiseRunnable(mWorkerPrivate, mPromiseProxy,
|
||||
Move(aClientInfo));
|
||||
|
||||
resolveRunnable->Dispatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ParseUrl(nsIURI** aBaseUrl, nsIURI** aUrl)
|
||||
{
|
||||
MOZ_ASSERT(aBaseUrl);
|
||||
MOZ_ASSERT(aUrl);
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIURI> baseUrl;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseUrl), mBaseUrl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = NS_NewURI(getter_AddRefs(url), mUrl, nullptr, baseUrl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
baseUrl.forget(aBaseUrl);
|
||||
url.forget(aUrl);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Navigate(nsIURI* aUrl, nsIPrincipal* aPrincipal, nsGlobalWindowInner** aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
nsGlobalWindowInner* window =
|
||||
nsGlobalWindowInner::GetInnerWindowWithId(mWindowId);
|
||||
if (NS_WARN_IF(!window)) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetDocument();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!doc->IsActive())) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
||||
if (NS_WARN_IF(!docShell)) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
|
||||
nsresult rv = docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
loadInfo->SetTriggeringPrincipal(aPrincipal);
|
||||
loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
|
||||
loadInfo->SetSourceDocShell(docShell);
|
||||
rv =
|
||||
docShell->LoadURI(aUrl, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
*aWindow = window;
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerWindowClient::Navigate(const nsAString& aUrl, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aUrl.EqualsLiteral("about:blank")) {
|
||||
promise->MaybeReject(NS_ERROR_TYPE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
ServiceWorkerGlobalScope* globalScope =
|
||||
static_cast<ServiceWorkerGlobalScope*>(workerPrivate->GlobalScope());
|
||||
nsString scope;
|
||||
globalScope->GetScope(scope);
|
||||
|
||||
RefPtr<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (promiseProxy) {
|
||||
RefPtr<ClientNavigateRunnable> r =
|
||||
new ClientNavigateRunnable(mWindowId, aUrl, scope, promiseProxy);
|
||||
MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
|
||||
} else {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_workers_serviceworkerwindowclient_h
|
||||
#define mozilla_dom_workers_serviceworkerwindowclient_h
|
||||
|
||||
#include "ServiceWorkerClient.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerWindowClient final : public ServiceWorkerClient
|
||||
{
|
||||
public:
|
||||
ServiceWorkerWindowClient(nsISupports* aOwner,
|
||||
const ServiceWorkerClientInfo& aClientInfo)
|
||||
: ServiceWorkerClient(aOwner, aClientInfo),
|
||||
mVisibilityState(aClientInfo.mVisibilityState),
|
||||
mFocused(aClientInfo.mFocused)
|
||||
{
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
mozilla::dom::VisibilityState
|
||||
VisibilityState() const
|
||||
{
|
||||
return mVisibilityState;
|
||||
}
|
||||
|
||||
bool
|
||||
Focused() const
|
||||
{
|
||||
return mFocused;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Focus(ErrorResult& aRv) const;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigate(const nsAString& aUrl, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~ServiceWorkerWindowClient()
|
||||
{ }
|
||||
|
||||
mozilla::dom::VisibilityState mVisibilityState;
|
||||
bool mFocused;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_workers_serviceworkerwindowclient_h
|
|
@ -33,7 +33,6 @@ WORKER_SIMPLE_PREF("dom.webnotifications.serviceworker.enabled", DOMServiceWorke
|
|||
WORKER_SIMPLE_PREF("dom.webnotifications.requireinteraction.enabled", DOMWorkerNotificationRIEnabled, DOM_WORKERNOTIFICATIONRI)
|
||||
WORKER_SIMPLE_PREF("dom.serviceWorkers.enabled", ServiceWorkersEnabled, SERVICEWORKERS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.serviceWorkers.testing.enabled", ServiceWorkersTestingEnabled, SERVICEWORKERS_TESTING_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, OPEN_WINDOW_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.promise_rejection_events.enabled", PromiseRejectionEventsEnabled, PROMISE_REJECTION_EVENTS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "jsapi.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Clients.h"
|
||||
#include "mozilla/dom/Console.h"
|
||||
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
|
||||
#include "mozilla/dom/Fetch.h"
|
||||
|
@ -44,7 +45,6 @@
|
|||
#include "ScriptLoader.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "ServiceWorkerClients.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerRegistration.h"
|
||||
|
||||
|
@ -634,14 +634,15 @@ ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
|
|||
true, aReflector);
|
||||
}
|
||||
|
||||
ServiceWorkerClients*
|
||||
ServiceWorkerGlobalScope::Clients()
|
||||
already_AddRefed<Clients>
|
||||
ServiceWorkerGlobalScope::GetClients()
|
||||
{
|
||||
if (!mClients) {
|
||||
mClients = new ServiceWorkerClients(this);
|
||||
mClients = new Clients(this);
|
||||
}
|
||||
|
||||
return mClients;
|
||||
RefPtr<Clients> ref = mClients;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ServiceWorkerRegistration*
|
||||
|
@ -848,15 +849,6 @@ ServiceWorkerGlobalScope::SkipWaiting(ErrorResult& aRv)
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
worker->AssertIsOnWorkerThread();
|
||||
return worker->OpenWindowEnabled();
|
||||
}
|
||||
|
||||
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace dom {
|
|||
|
||||
class AnyCallback;
|
||||
struct ChannelPixelLayout;
|
||||
class Clients;
|
||||
class Console;
|
||||
class Crypto;
|
||||
class Function;
|
||||
|
@ -40,7 +41,6 @@ class CacheStorage;
|
|||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerClients;
|
||||
class WorkerPrivate;
|
||||
|
||||
} // namespace workers
|
||||
|
@ -282,7 +282,7 @@ public:
|
|||
class ServiceWorkerGlobalScope final : public WorkerGlobalScope
|
||||
{
|
||||
const nsString mScope;
|
||||
RefPtr<workers::ServiceWorkerClients> mClients;
|
||||
RefPtr<Clients> mClients;
|
||||
RefPtr<ServiceWorkerRegistration> mRegistration;
|
||||
|
||||
~ServiceWorkerGlobalScope();
|
||||
|
@ -300,17 +300,14 @@ public:
|
|||
WrapGlobalObject(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aReflector) override;
|
||||
|
||||
static bool
|
||||
OpenWindowEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
void
|
||||
GetScope(nsString& aScope) const
|
||||
{
|
||||
aScope = mScope;
|
||||
}
|
||||
|
||||
workers::ServiceWorkerClients*
|
||||
Clients();
|
||||
already_AddRefed<Clients>
|
||||
GetClients();
|
||||
|
||||
ServiceWorkerRegistration*
|
||||
Registration();
|
||||
|
|
|
@ -37,9 +37,6 @@ EXPORTS.mozilla.dom.workers += [
|
|||
# Stuff needed for the bindings, not really public though.
|
||||
EXPORTS.mozilla.dom.workers.bindings += [
|
||||
'ServiceWorker.h',
|
||||
'ServiceWorkerClient.h',
|
||||
'ServiceWorkerClients.h',
|
||||
'ServiceWorkerWindowClient.h',
|
||||
'SharedWorker.h',
|
||||
'WorkerHolder.h',
|
||||
'WorkerHolderToken.h',
|
||||
|
@ -60,8 +57,6 @@ UNIFIED_SOURCES += [
|
|||
'RuntimeService.cpp',
|
||||
'ScriptLoader.cpp',
|
||||
'ServiceWorker.cpp',
|
||||
'ServiceWorkerClient.cpp',
|
||||
'ServiceWorkerClients.cpp',
|
||||
'ServiceWorkerContainer.cpp',
|
||||
'ServiceWorkerDescriptor.cpp',
|
||||
'ServiceWorkerEvents.cpp',
|
||||
|
@ -82,7 +77,6 @@ UNIFIED_SOURCES += [
|
|||
'ServiceWorkerUpdateJob.cpp',
|
||||
'ServiceWorkerUpdaterChild.cpp',
|
||||
'ServiceWorkerUpdaterParent.cpp',
|
||||
'ServiceWorkerWindowClient.cpp',
|
||||
'SharedWorker.cpp',
|
||||
'WorkerDebuggerManager.cpp',
|
||||
'WorkerHolder.cpp',
|
||||
|
|
|
@ -60,9 +60,9 @@ onmessage = function(event) {
|
|||
promises.push(testForUrl("about:blank", "TypeError", null, results));
|
||||
promises.push(testForUrl("http://example.com", "InvalidAccessError", null, results));
|
||||
promises.push(testForUrl("_._*`InvalidURL", "InvalidAccessError", null, results));
|
||||
Promise.all(promises).then(function(e) {
|
||||
event.waitUntil(Promise.all(promises).then(function(e) {
|
||||
client.postMessage(results);
|
||||
});
|
||||
}));
|
||||
}
|
||||
if (event.data == "NEW_WINDOW") {
|
||||
window_count += 1;
|
||||
|
@ -72,7 +72,7 @@ onmessage = function(event) {
|
|||
}
|
||||
|
||||
if (event.data == "CHECK_NUMBER_OF_WINDOWS") {
|
||||
got_all_windows.then(function() {
|
||||
event.waitUntil(got_all_windows.then(function() {
|
||||
return clients.matchAll();
|
||||
}).then(function(cl) {
|
||||
event.source.postMessage({result: cl.length == expected_window_count,
|
||||
|
@ -80,7 +80,7 @@ onmessage = function(event) {
|
|||
for (i = 0; i < cl.length; i++) {
|
||||
cl[i].postMessage("CLOSE");
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,16 +101,16 @@ onnotificationclick = function(e) {
|
|||
|
||||
// redirect tests
|
||||
promises.push(testForUrl(redirect + "open_window/client.html", null,
|
||||
{url: same_origin}, results));
|
||||
{url: same_origin}, results));
|
||||
promises.push(testForUrl(redirect + different_origin, null, null, results));
|
||||
|
||||
promises.push(testForUrl(redirect_xorigin + "open_window/client.html", null,
|
||||
null, results));
|
||||
null, results));
|
||||
promises.push(testForUrl(redirect_xorigin + same_origin, null,
|
||||
{url: same_origin}, results));
|
||||
{url: same_origin}, results));
|
||||
|
||||
Promise.all(promises).then(function(e) {
|
||||
e.waitUntil(Promise.all(promises).then(function(e) {
|
||||
client.postMessage(results);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,18 @@ SourceSurfaceD2D1::IsValid() const
|
|||
already_AddRefed<DataSourceSurface>
|
||||
SourceSurfaceD2D1::GetDataSurface()
|
||||
{
|
||||
HRESULT hr;
|
||||
Maybe<MutexAutoLock> lock;
|
||||
if (mSnapshotLock) {
|
||||
lock.emplace(*mSnapshotLock);
|
||||
}
|
||||
|
||||
if (!EnsureRealizedBitmap()) {
|
||||
gfxCriticalError() << "Failed to realize a bitmap, device " << hexa(mDevice);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
RefPtr<ID2D1Bitmap1> softwareBitmap;
|
||||
D2D1_BITMAP_PROPERTIES1 props;
|
||||
props.dpiX = 96;
|
||||
|
|
|
@ -46,7 +46,7 @@ static const uint32_t gLBClass20[32] = {
|
|||
0x77775555, // U+2008 - U+200F
|
||||
0x777277B7, // U+2010 - U+2017
|
||||
0x77A777A7, // U+2018 - U+201F
|
||||
0xAAAA7777, // U+2020 - U+2027
|
||||
0xA1117777, // U+2020 - U+2027
|
||||
0xB7777777, // U+2028 - U+202F
|
||||
0x77744444, // U+2030 - U+2037
|
||||
0x7A115107, // U+2038 - U+203F
|
||||
|
|
|
@ -96,10 +96,10 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
<TD>32</TD>
|
||||
<TD>2</TD>
|
||||
<TD></TD>
|
||||
<TD>28</TD>
|
||||
<TD>31</TD>
|
||||
<TD>3</TD>
|
||||
<TD></TD>
|
||||
<TD BGCOLOR=white>65</TD>
|
||||
<TD BGCOLOR=white>68</TD>
|
||||
<TD></TD>
|
||||
<TD></TD>
|
||||
<TD></TD>
|
||||
|
@ -120,7 +120,7 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
<TD>12</TD>
|
||||
<TD>1</TD>
|
||||
<TD></TD>
|
||||
<TD>14</TD>
|
||||
<TD>17</TD>
|
||||
<TD></TD>
|
||||
<TD></TD>
|
||||
<TD>2</TD>
|
||||
|
@ -447,10 +447,10 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
<TD>2</TD>
|
||||
<TD></TD>
|
||||
<TD>6</TD>
|
||||
<TD>28</TD>
|
||||
<TD>25</TD>
|
||||
<TD>14</TD>
|
||||
<TD></TD>
|
||||
<TD BGCOLOR=white>51</TD>
|
||||
<TD BGCOLOR=white>48</TD>
|
||||
<TD></TD>
|
||||
<TD>1</TD>
|
||||
<TD></TD>
|
||||
|
@ -471,7 +471,7 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
<TD>3</TD>
|
||||
<TD>3</TD>
|
||||
<TD></TD>
|
||||
<TD>22</TD>
|
||||
<TD>19</TD>
|
||||
<TD></TD>
|
||||
<TD>2</TD>
|
||||
<TD>3</TD>
|
||||
|
@ -623,7 +623,7 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
</TR>
|
||||
<TR><TH>20<TH>
|
||||
<TD>2</TD>
|
||||
<TD>8</TD>
|
||||
<TD>11</TD>
|
||||
<TD>1</TD>
|
||||
<TD></TD>
|
||||
<TD>5</TD>
|
||||
|
@ -632,7 +632,7 @@ Analysis of JIS X 4051 to Unicode General Category Mapping
|
|||
<TD>100</TD>
|
||||
<TD></TD>
|
||||
<TD></TD>
|
||||
<TD>7</TD>
|
||||
<TD>4</TD>
|
||||
<TD>4</TD>
|
||||
<TD></TD>
|
||||
</TR>
|
||||
|
|
|
@ -50,8 +50,8 @@ open ( OUT , "> anzx4051.html")
|
|||
# Open the output file
|
||||
#
|
||||
######################################################################
|
||||
open ( HEADER , "> ../src/jisx4051class.h")
|
||||
|| die "cannot open output ../src/jisx4051class.h file";
|
||||
open ( HEADER , "> ../jisx4051class.h")
|
||||
|| die "cannot open output ../jisx4051class.h file";
|
||||
|
||||
######################################################################
|
||||
#
|
||||
|
@ -86,7 +86,7 @@ $npl = <<END_OF_NPL;
|
|||
/* 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/. */
|
||||
/*
|
||||
/*
|
||||
DO NOT EDIT THIS DOCUMENT !!! THIS DOCUMENT IS GENERATED BY
|
||||
mozilla/intl/lwbrk/tools/anzx4051.pl
|
||||
*/
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
201D;;23
|
||||
2018;201F;18
|
||||
2020;2023;18
|
||||
2024;2026;23
|
||||
2024;2026;2
|
||||
2027;;23
|
||||
2028;202E;18
|
||||
202F;;24
|
||||
|
|
|
@ -226,11 +226,9 @@ class HashMap
|
|||
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
Generation generation() const {
|
||||
return impl.generation();
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************** Shorthand operations */
|
||||
|
||||
|
@ -475,11 +473,9 @@ class HashSet
|
|||
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
Generation generation() const {
|
||||
return impl.generation();
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************** Shorthand operations */
|
||||
|
||||
|
@ -1129,9 +1125,7 @@ class HashTable : private AllocPolicy
|
|||
// Potentially rehashes the table.
|
||||
~Enum() {
|
||||
if (rekeyed) {
|
||||
#ifdef JS_DEBUG
|
||||
table_.gen++;
|
||||
#endif
|
||||
table_.checkOverRemoved();
|
||||
}
|
||||
|
||||
|
@ -1164,14 +1158,13 @@ class HashTable : private AllocPolicy
|
|||
static const size_t CAP_BITS = 30;
|
||||
|
||||
public:
|
||||
uint64_t gen:56; // entry storage generation number
|
||||
uint64_t hashShift:8; // multiplicative hash shift
|
||||
Entry* table; // entry storage
|
||||
uint32_t hashShift; // multiplicative hash shift
|
||||
uint32_t minCapacity; // minimum table capacity
|
||||
uint32_t entryCount; // number of entries in table
|
||||
uint32_t removedCount; // removed entry sentinels in table
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
uint64_t gen; // entry storage generation number
|
||||
uint64_t mutationCount;
|
||||
mutable bool mEntered;
|
||||
// Note that some updates to these stats are not thread-safe. See the
|
||||
|
@ -1264,12 +1257,12 @@ class HashTable : private AllocPolicy
|
|||
public:
|
||||
explicit HashTable(AllocPolicy ap)
|
||||
: AllocPolicy(ap)
|
||||
, table(nullptr)
|
||||
, gen(0)
|
||||
, hashShift(sHashBits)
|
||||
, table(nullptr)
|
||||
, entryCount(0)
|
||||
, removedCount(0)
|
||||
#ifdef JS_DEBUG
|
||||
, gen(0)
|
||||
, mutationCount(0)
|
||||
, mEntered(false)
|
||||
#endif
|
||||
|
@ -1307,11 +1300,11 @@ class HashTable : private AllocPolicy
|
|||
++roundUpLog2;
|
||||
}
|
||||
|
||||
minCapacity = roundUp;
|
||||
MOZ_ASSERT(minCapacity >= length);
|
||||
MOZ_ASSERT(minCapacity <= sMaxCapacity);
|
||||
newCapacity = roundUp;
|
||||
MOZ_ASSERT(newCapacity >= length);
|
||||
MOZ_ASSERT(newCapacity <= sMaxCapacity);
|
||||
|
||||
table = createTable(*this, minCapacity);
|
||||
table = createTable(*this, newCapacity);
|
||||
if (!table)
|
||||
return false;
|
||||
|
||||
|
@ -1366,19 +1359,18 @@ class HashTable : private AllocPolicy
|
|||
capacity() * sMaxAlphaNumerator / sAlphaDenominator;
|
||||
}
|
||||
|
||||
// Considering its current entryCount, would the table be underloaded if it
|
||||
// had the given capacity?
|
||||
bool wouldBeUnderloaded(uint32_t capacity)
|
||||
// Would the table be underloaded if it had the given capacity and entryCount?
|
||||
static bool wouldBeUnderloaded(uint32_t capacity, uint32_t entryCount)
|
||||
{
|
||||
static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
|
||||
"multiplication below could overflow");
|
||||
return capacity > minCapacity &&
|
||||
return capacity > sMinCapacity &&
|
||||
entryCount <= capacity * sMinAlphaNumerator / sAlphaDenominator;
|
||||
}
|
||||
|
||||
bool underloaded()
|
||||
{
|
||||
return wouldBeUnderloaded(capacity());
|
||||
return wouldBeUnderloaded(capacity(), entryCount);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool match(Entry& e, const Lookup& l)
|
||||
|
@ -1511,11 +1503,8 @@ class HashTable : private AllocPolicy
|
|||
// We can't fail from here on, so update table parameters.
|
||||
setTableSizeLog2(newLog2);
|
||||
removedCount = 0;
|
||||
table = newTable;
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
gen++;
|
||||
#endif
|
||||
table = newTable;
|
||||
|
||||
// Copy only live entries, leaving removed ones behind.
|
||||
Entry* end = oldTable + oldCap;
|
||||
|
@ -1598,7 +1587,7 @@ class HashTable : private AllocPolicy
|
|||
{
|
||||
int32_t resizeLog2 = 0;
|
||||
uint32_t newCapacity = capacity();
|
||||
while (wouldBeUnderloaded(newCapacity)) {
|
||||
while (wouldBeUnderloaded(newCapacity, entryCount)) {
|
||||
newCapacity = newCapacity >> 1;
|
||||
resizeLog2--;
|
||||
}
|
||||
|
@ -1616,9 +1605,7 @@ class HashTable : private AllocPolicy
|
|||
{
|
||||
METER(stats.rehashes++);
|
||||
removedCount = 0;
|
||||
#ifdef JS_DEBUG
|
||||
gen++;
|
||||
#endif
|
||||
for (size_t i = 0; i < capacity(); ++i)
|
||||
table[i].unsetCollision();
|
||||
|
||||
|
@ -1714,10 +1701,10 @@ class HashTable : private AllocPolicy
|
|||
|
||||
destroyTable(*this, table, capacity());
|
||||
table = nullptr;
|
||||
gen++;
|
||||
entryCount = 0;
|
||||
removedCount = 0;
|
||||
#ifdef JS_DEBUG
|
||||
gen++;
|
||||
mutationCount++;
|
||||
#endif
|
||||
}
|
||||
|
@ -1746,13 +1733,11 @@ class HashTable : private AllocPolicy
|
|||
return JS_BIT(sHashBits - hashShift);
|
||||
}
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
Generation generation() const
|
||||
{
|
||||
MOZ_ASSERT(table);
|
||||
return Generation(gen);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
|
|
|
@ -3101,6 +3101,17 @@ HelperThreadCount(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EnableShapeConsistencyChecks(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
#ifdef DEBUG
|
||||
NativeObject::enableShapeConsistencyChecks();
|
||||
#endif
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
static bool
|
||||
EnableTraceLogger(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -5353,6 +5364,10 @@ gc::ZealModeHelpText),
|
|||
"helperThreadCount()",
|
||||
" Returns the number of helper threads available for off-thread tasks."),
|
||||
|
||||
JS_FN_HELP("enableShapeConsistencyChecks", EnableShapeConsistencyChecks, 0, 0,
|
||||
"enableShapeConsistencyChecks()",
|
||||
" Enable some slow Shape assertions.\n"),
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
JS_FN_HELP("startTraceLogger", EnableTraceLogger, 0, 0,
|
||||
"startTraceLogger()",
|
||||
|
|
|
@ -77,20 +77,14 @@ class StoreBuffer
|
|||
*/
|
||||
T last_;
|
||||
|
||||
/*
|
||||
* Maximum number of entries before we request a minor GC.
|
||||
*
|
||||
* This is passed to HashSet::init(), which will pre-allocate a hash
|
||||
* table capable of holding this many entries before rehashing, which is
|
||||
* currently 4/3 this value.
|
||||
*/
|
||||
const static size_t MaxEntries = 8192;
|
||||
/* Maximum number of entries before we request a minor GC. */
|
||||
const static size_t MaxEntries = 48 * 1024 / sizeof(T);
|
||||
|
||||
explicit MonoTypeBuffer() : last_(T()) {}
|
||||
~MonoTypeBuffer() { stores_.finish(); }
|
||||
|
||||
MOZ_MUST_USE bool init() {
|
||||
if (!stores_.initialized() && !stores_.init(MaxEntries))
|
||||
if (!stores_.initialized() && !stores_.init())
|
||||
return false;
|
||||
clear();
|
||||
return true;
|
||||
|
@ -100,7 +94,6 @@ class StoreBuffer
|
|||
last_ = T();
|
||||
if (stores_.initialized())
|
||||
stores_.clear();
|
||||
MOZ_ASSERT(stores_.capacity() > MaxEntries);
|
||||
}
|
||||
|
||||
/* Add one item to the buffer. */
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
enableShapeConsistencyChecks();
|
||||
var o = {};
|
||||
for (var i = 0; i < 50; i++) {
|
||||
o["x" + i] = i;
|
||||
}
|
||||
for (var i = 0; i < 50; i += 2) {
|
||||
delete o["x" + i];
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
function sparse() {
|
||||
var o = {0: 0, 0x10000: 0};
|
||||
|
||||
var tests = [[1, false], [0, true], [-2, false], [0x10000, true], [0x20000, false]];
|
||||
for (var [key, has] of tests) {
|
||||
assertEq(key in o, has);
|
||||
assertEq(o.hasOwnProperty(key), has);
|
||||
}
|
||||
}
|
||||
|
||||
function typedArray() {
|
||||
var o = {0: 0, 0x10000: 0};
|
||||
var t = new Int32Array(0x10001)
|
||||
|
||||
// Only use Int32Array after we attached the sparse stub
|
||||
// in o, in t
|
||||
var tests = [[1, [false, true]],
|
||||
[0, [true, true]],
|
||||
[-2, [false, false]],
|
||||
[0x10000, [true, true]],
|
||||
[0x20000, [false, false]]];
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
for (var [key, has] of tests) {
|
||||
assertEq(key in o, has[i > 5 ? 1 : 0]);
|
||||
assertEq(o.hasOwnProperty(key), has[i > 5 ? 1 : 0]);
|
||||
}
|
||||
|
||||
if (i == 5)
|
||||
o = t;
|
||||
}
|
||||
}
|
||||
|
||||
function protoChange() {
|
||||
var o = {0: 0, 0x10000: 0};
|
||||
|
||||
var tests = [[1, [false, true]],
|
||||
[0, [true, true]],
|
||||
[-2, [false, false]],
|
||||
[0x10000, [true, true]],
|
||||
[0x20000, [false, false]]];
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
for (var [key, has] of tests) {
|
||||
assertEq(key in o, has[i > 5 ? 1 : 0]);
|
||||
// Proto change doesn't affect hasOwnProperty.
|
||||
assertEq(o.hasOwnProperty(key), has[0]);
|
||||
}
|
||||
|
||||
if (i == 5)
|
||||
o.__proto__ = [1, 1, 1, 1];
|
||||
}
|
||||
}
|
||||
|
||||
sparse();
|
||||
typedArray();
|
||||
protoChange();
|
||||
|
|
@ -1730,7 +1730,7 @@ GetPropIRGenerator::tryAttachDenseElement(HandleObject obj, ObjOperandId objId,
|
|||
}
|
||||
|
||||
static bool
|
||||
CanAttachDenseElementHole(JSObject* obj, bool ownProp)
|
||||
CanAttachDenseElementHole(NativeObject* obj, bool ownProp, bool allowIndexedReceiver = false)
|
||||
{
|
||||
// Make sure the objects on the prototype don't have any indexed properties
|
||||
// or that such properties can't appear without a shape change.
|
||||
|
@ -1738,8 +1738,9 @@ CanAttachDenseElementHole(JSObject* obj, bool ownProp)
|
|||
// because we would have to lookup a property on the prototype instead.
|
||||
do {
|
||||
// The first two checks are also relevant to the receiver object.
|
||||
if (obj->isNative() && obj->as<NativeObject>().isIndexed())
|
||||
if (!allowIndexedReceiver && obj->isIndexed())
|
||||
return false;
|
||||
allowIndexedReceiver = false;
|
||||
|
||||
if (ClassCanHaveExtraProperties(obj->getClass()))
|
||||
return false;
|
||||
|
@ -1759,7 +1760,7 @@ CanAttachDenseElementHole(JSObject* obj, bool ownProp)
|
|||
if (proto->as<NativeObject>().getDenseInitializedLength() != 0)
|
||||
return false;
|
||||
|
||||
obj = proto;
|
||||
obj = &proto->as<NativeObject>();
|
||||
} while (true);
|
||||
|
||||
return true;
|
||||
|
@ -1775,7 +1776,7 @@ GetPropIRGenerator::tryAttachDenseElementHole(HandleObject obj, ObjOperandId obj
|
|||
if (obj->as<NativeObject>().containsDenseElement(index))
|
||||
return false;
|
||||
|
||||
if (!CanAttachDenseElementHole(obj, false))
|
||||
if (!CanAttachDenseElementHole(&obj->as<NativeObject>(), false))
|
||||
return false;
|
||||
|
||||
// Guard on the shape, to prevent non-dense elements from appearing.
|
||||
|
@ -2430,7 +2431,7 @@ HasPropIRGenerator::tryAttachDenseHole(HandleObject obj, ObjOperandId objId,
|
|||
return false;
|
||||
if (obj->as<NativeObject>().containsDenseElement(index))
|
||||
return false;
|
||||
if (!CanAttachDenseElementHole(obj, hasOwn))
|
||||
if (!CanAttachDenseElementHole(&obj->as<NativeObject>(), hasOwn))
|
||||
return false;
|
||||
|
||||
// Guard shape to ensure class is NativeObject and to prevent non-dense
|
||||
|
@ -2450,6 +2451,46 @@ HasPropIRGenerator::tryAttachDenseHole(HandleObject obj, ObjOperandId objId,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HasPropIRGenerator::tryAttachSparse(HandleObject obj, ObjOperandId objId,
|
||||
uint32_t index, Int32OperandId indexId)
|
||||
{
|
||||
bool hasOwn = (cacheKind_ == CacheKind::HasOwn);
|
||||
|
||||
if (!obj->isNative())
|
||||
return false;
|
||||
if (!obj->as<NativeObject>().isIndexed())
|
||||
return false;
|
||||
if (!CanAttachDenseElementHole(&obj->as<NativeObject>(), hasOwn,
|
||||
/* allowIndexedReceiver = */ true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Guard that this is a native object.
|
||||
writer.guardIsNativeObject(objId);
|
||||
|
||||
// Generate prototype guards if needed. This includes monitoring that
|
||||
// properties were not added in the chain.
|
||||
if (!hasOwn) {
|
||||
if (!obj->hasUncacheableProto()) {
|
||||
// Make sure the proto does not change without checking the shape.
|
||||
writer.guardProto(objId, obj->staticPrototype());
|
||||
}
|
||||
|
||||
GeneratePrototypeHoleGuards(writer, obj, objId);
|
||||
}
|
||||
|
||||
// Because of the prototype guard we know that the prototype chain
|
||||
// does not include any dense or sparse (i.e indexed) properties.
|
||||
writer.callObjectHasSparseElementResult(objId, indexId);
|
||||
writer.returnFromIC();
|
||||
|
||||
trackAttached("Sparse");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HasPropIRGenerator::tryAttachNamedProp(HandleObject obj, ObjOperandId objId,
|
||||
HandleId key, ValOperandId keyId)
|
||||
|
@ -2718,6 +2759,8 @@ HasPropIRGenerator::tryAttachStub()
|
|||
return true;
|
||||
if (tryAttachTypedArray(obj, objId, index, indexId))
|
||||
return true;
|
||||
if (tryAttachSparse(obj, objId, index, indexId))
|
||||
return true;
|
||||
|
||||
trackNotAttached();
|
||||
return false;
|
||||
|
|
|
@ -175,6 +175,7 @@ extern const char* CacheKindNames[];
|
|||
_(GuardAnyClass) /* Guard an arbitrary class for an object */ \
|
||||
_(GuardCompartment) \
|
||||
_(GuardIsNativeFunction) \
|
||||
_(GuardIsNativeObject) \
|
||||
_(GuardIsProxy) \
|
||||
_(GuardHasProxyHandler) \
|
||||
_(GuardNotDOMProxy) \
|
||||
|
@ -259,6 +260,7 @@ extern const char* CacheKindNames[];
|
|||
_(CallProxyGetResult) \
|
||||
_(CallProxyGetByValueResult) \
|
||||
_(CallProxyHasPropResult) \
|
||||
_(CallObjectHasSparseElementResult) \
|
||||
_(LoadUndefinedResult) \
|
||||
_(LoadBooleanResult) \
|
||||
_(LoadStringResult) \
|
||||
|
@ -556,6 +558,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
writeOpWithOperandId(CacheOp::GuardIsNativeFunction, obj);
|
||||
writePointer(JS_FUNC_TO_DATA_PTR(void*, nativeFunc));
|
||||
}
|
||||
void guardIsNativeObject(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsNativeObject, obj);
|
||||
}
|
||||
void guardIsProxy(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsProxy, obj);
|
||||
}
|
||||
|
@ -975,6 +980,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
writeOperandId(idVal);
|
||||
buffer_.writeByte(uint32_t(hasOwn));
|
||||
}
|
||||
void callObjectHasSparseElementResult(ObjOperandId obj, Int32OperandId index) {
|
||||
writeOpWithOperandId(CacheOp::CallObjectHasSparseElementResult, obj);
|
||||
writeOperandId(index);
|
||||
}
|
||||
void loadEnvironmentFixedSlotResult(ObjOperandId obj, size_t offset) {
|
||||
writeOpWithOperandId(CacheOp::LoadEnvironmentFixedSlotResult, obj);
|
||||
addStubField(offset, StubField::Type::RawWord);
|
||||
|
@ -1447,6 +1456,8 @@ class MOZ_RAII HasPropIRGenerator : public IRGenerator
|
|||
uint32_t index, Int32OperandId indexId);
|
||||
bool tryAttachTypedArray(HandleObject obj, ObjOperandId objId,
|
||||
uint32_t index, Int32OperandId indexId);
|
||||
bool tryAttachSparse(HandleObject obj, ObjOperandId objId,
|
||||
uint32_t index, Int32OperandId indexId);
|
||||
bool tryAttachNamedProp(HandleObject obj, ObjOperandId objId,
|
||||
HandleId key, ValOperandId keyId);
|
||||
bool tryAttachMegamorphic(ObjOperandId objId, ValOperandId keyId);
|
||||
|
|
|
@ -1416,6 +1416,22 @@ CacheIRCompiler::emitGuardIsNativeFunction()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsNativeObject()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadObjClass(obj, scratch);
|
||||
masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
|
||||
Imm32(Class::NON_NATIVE), failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsProxy()
|
||||
{
|
||||
|
@ -2565,3 +2581,49 @@ CacheIRCompiler::emitMegamorphicHasPropResult()
|
|||
masm.adjustStack(sizeof(Value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitCallObjectHasSparseElementResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
Register index = allocator.useRegister(masm, reader.int32OperandId());
|
||||
|
||||
AutoScratchRegisterMaybeOutput scratch1(allocator, masm, output);
|
||||
AutoScratchRegister scratch2(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.reserveStack(sizeof(Value));
|
||||
masm.moveStackPtrTo(scratch2.get());
|
||||
|
||||
LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs());
|
||||
volatileRegs.takeUnchecked(scratch1);
|
||||
volatileRegs.takeUnchecked(index);
|
||||
masm.PushRegsInMask(volatileRegs);
|
||||
|
||||
masm.setupUnalignedABICall(scratch1);
|
||||
masm.loadJSContext(scratch1);
|
||||
masm.passABIArg(scratch1);
|
||||
masm.passABIArg(obj);
|
||||
masm.passABIArg(index);
|
||||
masm.passABIArg(scratch2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, HasNativeElement));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
||||
Label ok;
|
||||
uint32_t framePushed = masm.framePushed();
|
||||
masm.branchIfTrueBool(scratch1, &ok);
|
||||
masm.adjustStack(sizeof(Value));
|
||||
masm.jump(failure->label());
|
||||
|
||||
masm.bind(&ok);
|
||||
masm.setFramePushed(framePushed);
|
||||
masm.loadTypedOrValue(Address(masm.getStackPointer(), 0), output);
|
||||
masm.adjustStack(sizeof(Value));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace jit {
|
|||
_(GuardType) \
|
||||
_(GuardClass) \
|
||||
_(GuardIsNativeFunction) \
|
||||
_(GuardIsNativeObject) \
|
||||
_(GuardIsProxy) \
|
||||
_(GuardNotDOMProxy) \
|
||||
_(GuardSpecificInt32Immediate) \
|
||||
|
@ -62,6 +63,7 @@ namespace jit {
|
|||
_(Breakpoint) \
|
||||
_(MegamorphicLoadSlotByValueResult) \
|
||||
_(MegamorphicHasPropResult) \
|
||||
_(CallObjectHasSparseElementResult) \
|
||||
_(WrapResult)
|
||||
|
||||
// Represents a Value on the Baseline frame's expression stack. Slot 0 is the
|
||||
|
|
|
@ -1234,7 +1234,6 @@ IonCacheIRCompiler::emitCallProxyHasPropResult()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitLoadUnboxedPropertyResult()
|
||||
{
|
||||
|
|
|
@ -1842,6 +1842,45 @@ HasNativeDataProperty<true>(JSContext* cx, JSObject* obj, Value* vp);
|
|||
template bool
|
||||
HasNativeDataProperty<false>(JSContext* cx, JSObject* obj, Value* vp);
|
||||
|
||||
|
||||
bool
|
||||
HasNativeElement(JSContext* cx, NativeObject* obj, int32_t index, Value* vp)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
MOZ_ASSERT(obj->getClass()->isNative());
|
||||
MOZ_ASSERT(!obj->getOpsHasProperty());
|
||||
MOZ_ASSERT(!obj->getOpsLookupProperty());
|
||||
MOZ_ASSERT(!obj->getOpsGetOwnPropertyDescriptor());
|
||||
|
||||
if (MOZ_UNLIKELY(index < 0))
|
||||
return false;
|
||||
|
||||
if (obj->containsDenseElement(index)) {
|
||||
vp[0].setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
jsid id = INT_TO_JSID(index);
|
||||
if (obj->lastProperty()->search(cx, id)) {
|
||||
vp[0].setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fail if there's a resolve hook, unless the mayResolve hook tells
|
||||
// us the resolve hook won't define a property with this id.
|
||||
if (MOZ_UNLIKELY(ClassMayResolveId(cx->names(), obj->getClass(), id, obj)))
|
||||
return false;
|
||||
// TypedArrayObject are also native and contain indexed properties.
|
||||
if (MOZ_UNLIKELY(obj->is<TypedArrayObject>())) {
|
||||
vp[0].setBoolean(uint32_t(index) < obj->as<TypedArrayObject>().length());
|
||||
return true;
|
||||
}
|
||||
|
||||
vp[0].setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString*
|
||||
TypeOfObject(JSObject* obj, JSRuntime* rt)
|
||||
{
|
||||
|
|
|
@ -925,6 +925,9 @@ template <bool HasOwn>
|
|||
bool
|
||||
HasNativeDataProperty(JSContext* cx, JSObject* obj, Value* vp);
|
||||
|
||||
bool
|
||||
HasNativeElement(JSContext* cx, NativeObject* obj, int32_t index, Value* vp);
|
||||
|
||||
template <bool NeedsTypeBarrier>
|
||||
bool
|
||||
SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
|
|
|
@ -356,21 +356,6 @@ XCFLAGS="$X_CFLAGS"
|
|||
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl ==============================================================
|
||||
dnl Get mozilla version from central milestone file
|
||||
dnl ==============================================================
|
||||
MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir`
|
||||
MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion`
|
||||
MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion`
|
||||
if test -z "$MOZILLA_VERSION"; then
|
||||
AC_MSG_ERROR([failed to read version info from milestone file])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION")
|
||||
AC_SUBST(MOZILLA_SYMBOLVERSION)
|
||||
|
||||
# Separate version into components for use in shared object naming etc
|
||||
changequote(,)
|
||||
MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"`
|
||||
|
@ -412,7 +397,6 @@ AS_BIN=$AS
|
|||
AR_EXTRACT='$(AR) x'
|
||||
AS='$(CC)'
|
||||
AS_DASH_C_FLAG='-c'
|
||||
DIRENT_INO=d_ino
|
||||
MOZ_USER_DIR=".mozilla"
|
||||
|
||||
MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin -Wl,-rpath-link,${prefix}/lib"
|
||||
|
@ -883,10 +867,6 @@ if test -z "$MOZ_OPTIMIZE_FLAGS"; then
|
|||
MOZ_OPTIMIZE_FLAGS="-O"
|
||||
fi
|
||||
|
||||
dnl Only one oddball right now (QNX), but this gives us flexibility
|
||||
dnl if any other platforms need to override this in the future.
|
||||
AC_DEFINE_UNQUOTED(D_INO,$DIRENT_INO)
|
||||
|
||||
if test -z "$COMPILE_ENVIRONMENT"; then
|
||||
SKIP_COMPILER_CHECKS=1
|
||||
SKIP_LIBRARY_CHECKS=1
|
||||
|
@ -1931,8 +1911,6 @@ MOZ_CHECK_ALLOCATOR
|
|||
|
||||
AC_CHECK_FUNCS(setlocale localeconv)
|
||||
|
||||
AC_SUBST(MOZILLA_VERSION)
|
||||
|
||||
AC_SUBST(ac_configure_args)
|
||||
|
||||
if test -n "$JS_STANDALONE"; then
|
||||
|
|
|
@ -125,17 +125,18 @@ ObjectElements::FreezeElements(JSContext* cx, HandleNativeObject obj)
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static mozilla::Atomic<bool, mozilla::Relaxed> gShapeConsistencyChecksEnabled(false);
|
||||
|
||||
/* static */ void
|
||||
js::NativeObject::enableShapeConsistencyChecks()
|
||||
{
|
||||
gShapeConsistencyChecksEnabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
js::NativeObject::checkShapeConsistency()
|
||||
{
|
||||
static int throttle = -1;
|
||||
if (throttle < 0) {
|
||||
if (const char* var = getenv("JS_CHECK_SHAPE_THROTTLE"))
|
||||
throttle = atoi(var);
|
||||
if (throttle < 0)
|
||||
throttle = 0;
|
||||
}
|
||||
if (throttle == 0)
|
||||
if (!gShapeConsistencyChecksEnabled)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(isNative());
|
||||
|
@ -153,18 +154,20 @@ js::NativeObject::checkShapeConsistency()
|
|||
MOZ_ASSERT(fslot < slotSpan());
|
||||
}
|
||||
|
||||
for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
|
||||
while (shape->parent) {
|
||||
MOZ_ASSERT_IF(lastProperty() != shape, !shape->hasTable());
|
||||
|
||||
ShapeTable::Entry& entry = table->search<MaybeAdding::NotAdding>(shape->propid(),
|
||||
nogc);
|
||||
MOZ_ASSERT(entry.shape() == shape);
|
||||
shape = shape->parent;
|
||||
}
|
||||
}
|
||||
|
||||
shape = lastProperty();
|
||||
for (int n = throttle; --n >= 0 && shape; shape = shape->parent) {
|
||||
MOZ_ASSERT_IF(shape->slot() != SHAPE_INVALID_SLOT, shape->slot() < slotSpan());
|
||||
while (shape) {
|
||||
MOZ_ASSERT_IF(!shape->isEmptyShape() && shape->isDataProperty(),
|
||||
shape->slot() < slotSpan());
|
||||
if (!prev) {
|
||||
MOZ_ASSERT(lastProperty() == shape);
|
||||
MOZ_ASSERT(shape->listp == &shape_);
|
||||
|
@ -172,9 +175,10 @@ js::NativeObject::checkShapeConsistency()
|
|||
MOZ_ASSERT(shape->listp == &prev->parent);
|
||||
}
|
||||
prev = shape;
|
||||
shape = shape->parent;
|
||||
}
|
||||
} else {
|
||||
for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
|
||||
while (shape->parent) {
|
||||
if (ShapeTable* table = shape->maybeTable(nogc)) {
|
||||
MOZ_ASSERT(shape->parent);
|
||||
for (Shape::Range<NoGC> r(shape); !r.empty(); r.popFront()) {
|
||||
|
@ -184,10 +188,11 @@ js::NativeObject::checkShapeConsistency()
|
|||
}
|
||||
}
|
||||
if (prev) {
|
||||
MOZ_ASSERT(prev->maybeSlot() >= shape->maybeSlot());
|
||||
MOZ_ASSERT_IF(shape->isDataProperty(), prev->maybeSlot() >= shape->maybeSlot());
|
||||
shape->kids.checkConsistency(prev);
|
||||
}
|
||||
prev = shape;
|
||||
shape = shape->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -550,6 +550,10 @@ class NativeObject : public ShapedObject
|
|||
static inline JS::Result<NativeObject*, JS::OOM&>
|
||||
createWithTemplate(JSContext* cx, js::gc::InitialHeap heap, HandleObject templateObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void enableShapeConsistencyChecks();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG
|
||||
friend class js::AutoCheckShapeConsistency;
|
||||
|
|
|
@ -5,13 +5,22 @@
|
|||
<body>
|
||||
|
||||
<!-- U+2024 is ONE DOT LEADER -->
|
||||
<p>abcdef․․․abcdef</p>
|
||||
<p>abcdef․․․<br>abcdef</p>
|
||||
<p>abcdef․<br>abcdef</p>
|
||||
<p>abcdef․ <br>abcdef</p>
|
||||
<p>abcdef <br>․abcdef</p>
|
||||
|
||||
<!-- U+2025 is TWO DOT LEADER -->
|
||||
<p>abcdef‥‥‥abcdef</p>
|
||||
<p>abcdef‥‥‥<br>abcdef</p>
|
||||
<p>abcdef‥<br>abcdef</p>
|
||||
<p>abcdef‥ <br>abcdef</p>
|
||||
<p>abcdef <br>‥abcdef</p>
|
||||
|
||||
<!-- U+2026 is HORIZONTAL ELLIPSIS -->
|
||||
<p>abcdef………abcdef</p>
|
||||
<p>abcdef………<br>abcdef</p>
|
||||
<p>abcdef…<br>abcdef</p>
|
||||
<p>abcdef… <br>abcdef</p>
|
||||
<p>abcdef <br>…abcdef</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,12 +6,21 @@
|
|||
|
||||
<!-- U+2024 is ONE DOT LEADER -->
|
||||
<p>abcdef․․․abcdef</p>
|
||||
<p>abcdef․abcdef</p>
|
||||
<p>abcdef․ abcdef</p>
|
||||
<p>abcdef ․abcdef</p> <!-- no break after the leader in this case -->
|
||||
|
||||
<!-- U+2025 is TWO DOT LEADER -->
|
||||
<p>abcdef‥‥‥abcdef</p>
|
||||
<p>abcdef‥abcdef</p>
|
||||
<p>abcdef‥ abcdef</p>
|
||||
<p>abcdef ‥abcdef</p> <!-- no break after the leader in this case -->
|
||||
|
||||
<!-- U+2026 is HORIZONTAL ELLIPSIS -->
|
||||
<p>abcdef………abcdef</p>
|
||||
<p>abcdef…abcdef</p>
|
||||
<p>abcdef… abcdef</p>
|
||||
<p>abcdef …abcdef</p> <!-- no break after the ellipsis in this case -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -851,7 +851,6 @@ pref("browser.tabs.showAudioPlayingIcon", true);
|
|||
|
||||
pref("dom.serviceWorkers.enabled", true);
|
||||
pref("dom.serviceWorkers.interception.enabled", true);
|
||||
pref("dom.serviceWorkers.openWindow.enabled", true);
|
||||
|
||||
// Allow service workers to open windows for a longer period after a notification
|
||||
// click on mobile. This is to account for some devices being quite slow.
|
||||
|
|
|
@ -293,6 +293,7 @@ NS_INTERFACE_MAP_BEGIN(nsBufferedInputStream)
|
|||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, IsIPCSerializable())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, IsAsyncInputStream())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, IsAsyncInputStream())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, IsCloneableInputStream())
|
||||
NS_IMPL_QUERY_CLASSINFO(nsBufferedInputStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsBufferedStream)
|
||||
|
||||
|
@ -641,6 +642,13 @@ nsBufferedInputStream::IsAsyncInputStream() const
|
|||
return !!stream;
|
||||
}
|
||||
|
||||
bool
|
||||
nsBufferedInputStream::IsCloneableInputStream() const
|
||||
{
|
||||
nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mStream);
|
||||
return !!stream;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBufferedInputStream::CloseWithStatus(nsresult aStatus)
|
||||
{
|
||||
|
@ -695,6 +703,50 @@ nsBufferedInputStream::GetData(nsIInputStream **aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsICloneableInputStream interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBufferedInputStream::GetCloneable(bool* aCloneable)
|
||||
{
|
||||
*aCloneable = false;
|
||||
|
||||
// If we don't have the buffer, the inputStream has been already closed.
|
||||
// If mBufferStartOffset is not 0, the stream has been seeked or read.
|
||||
// In both case the cloning is not supported.
|
||||
if (!mBuffer || mBufferStartOffset) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mStream);
|
||||
|
||||
// GetCloneable is infallible.
|
||||
NS_ENSURE_TRUE(stream, NS_OK);
|
||||
|
||||
return stream->GetCloneable(aCloneable);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBufferedInputStream::Clone(nsIInputStream** aResult)
|
||||
{
|
||||
if (!mBuffer || mBufferStartOffset) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mStream);
|
||||
NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIInputStream> clonedStream;
|
||||
nsresult rv = stream->Clone(getter_AddRefs(clonedStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIBufferedInputStream> bis = new nsBufferedInputStream();
|
||||
rv = bis->Init(clonedStream, mBufferSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bis.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsBufferedOutputStream
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsICloneableInputStream.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -65,7 +66,8 @@ class nsBufferedInputStream : public nsBufferedStream,
|
|||
public nsIStreamBufferAccess,
|
||||
public nsIIPCSerializableInputStream,
|
||||
public nsIAsyncInputStream,
|
||||
public nsIInputStreamCallback
|
||||
public nsIInputStreamCallback,
|
||||
public nsICloneableInputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -75,6 +77,7 @@ public:
|
|||
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
|
||||
NS_DECL_NSIASYNCINPUTSTREAM
|
||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||
NS_DECL_NSICLONEABLEINPUTSTREAM
|
||||
|
||||
nsBufferedInputStream() : nsBufferedStream() {}
|
||||
|
||||
|
@ -90,6 +93,7 @@ protected:
|
|||
|
||||
bool IsIPCSerializable() const;
|
||||
bool IsAsyncInputStream() const;
|
||||
bool IsCloneableInputStream() const;
|
||||
|
||||
NS_IMETHOD Fill() override;
|
||||
NS_IMETHOD Flush() override { return NS_OK; } // no-op for input streams
|
||||
|
|
|
@ -61,7 +61,9 @@ interface nsIUploadChannel2 : nsISupports
|
|||
* Clones the upload stream. May return failure if the upload stream
|
||||
* is not cloneable. If this is not acceptable, use the
|
||||
* ensureUploadStreamIsCloneable() method first.
|
||||
* aContentLength could be -1 in case the size of the stream is unknown,
|
||||
* otherwise it will contain the known size of the stream.
|
||||
*/
|
||||
[noscript]
|
||||
nsIInputStream cloneUploadStream();
|
||||
nsIInputStream cloneUploadStream(out long long aContentLength);
|
||||
};
|
||||
|
|
|
@ -995,8 +995,10 @@ HttpBaseChannel::EnsureUploadStreamIsCloneableComplete(nsresult aStatus)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::CloneUploadStream(nsIInputStream** aClonedStream)
|
||||
HttpBaseChannel::CloneUploadStream(int64_t* aContentLength,
|
||||
nsIInputStream** aClonedStream)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aContentLength);
|
||||
NS_ENSURE_ARG_POINTER(aClonedStream);
|
||||
*aClonedStream = nullptr;
|
||||
|
||||
|
@ -1010,6 +1012,12 @@ HttpBaseChannel::CloneUploadStream(nsIInputStream** aClonedStream)
|
|||
|
||||
clonedStream.forget(aClonedStream);
|
||||
|
||||
if (mReqContentLengthDetermined) {
|
||||
*aContentLength = mReqContentLength;
|
||||
} else {
|
||||
*aContentLength = -1;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -457,7 +457,6 @@ AS_BIN=$AS
|
|||
AR_EXTRACT='$(AR) x'
|
||||
AS='$(CC)'
|
||||
AS_DASH_C_FLAG='-c'
|
||||
DIRENT_INO=d_ino
|
||||
MOZ_USER_DIR=".mozilla"
|
||||
|
||||
MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin -Wl,-rpath-link,${prefix}/lib"
|
||||
|
@ -749,16 +748,6 @@ case "$host" in
|
|||
;;
|
||||
esac
|
||||
|
||||
dnl ==============================================================
|
||||
dnl Get mozilla version from central milestone file
|
||||
dnl ==============================================================
|
||||
MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir`
|
||||
MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion`
|
||||
MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion`
|
||||
if test -z "$MOZILLA_VERSION"; then
|
||||
AC_MSG_ERROR([failed to read version info from milestone file])
|
||||
fi
|
||||
|
||||
dnl Get version of various core apps from the version files.
|
||||
FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt`
|
||||
FIREFOX_VERSION_DISPLAY=`cat $_topsrcdir/browser/config/version_display.txt`
|
||||
|
@ -771,11 +760,6 @@ if test -z "$FIREFOX_VERSION_DISPLAY"; then
|
|||
AC_MSG_ERROR([FIREFOX_VERSION_DISPLAY is unexpectedly blank.])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION")
|
||||
AC_SUBST(MOZILLA_SYMBOLVERSION)
|
||||
|
||||
MOZ_DOING_LTO(lto_is_enabled)
|
||||
|
||||
dnl ========================================================
|
||||
|
@ -1151,10 +1135,6 @@ if test -n "$MOZ_LINKER"; then
|
|||
AC_CHECK_PROGS(XZ, xz)
|
||||
fi
|
||||
|
||||
dnl Only one oddball right now (QNX), but this gives us flexibility
|
||||
dnl if any other platforms need to override this in the future.
|
||||
AC_DEFINE_UNQUOTED(D_INO,$DIRENT_INO)
|
||||
|
||||
if test -z "$COMPILE_ENVIRONMENT"; then
|
||||
SKIP_COMPILER_CHECKS=1
|
||||
SKIP_LIBRARY_CHECKS=1
|
||||
|
@ -4848,8 +4828,6 @@ if test -n "$A11Y_LOG"; then
|
|||
AC_DEFINE(A11Y_LOG)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZILLA_VERSION)
|
||||
|
||||
dnl Spit out some output
|
||||
dnl ========================================================
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def get_milestone_ab_with_num(milestone):
|
||||
"""
|
||||
Returns the alpha and beta tag with its number (a1, a2, b3, ...).
|
||||
"""
|
||||
|
||||
match = re.search(r"([ab]\d+)", milestone)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def get_official_milestone(path):
|
||||
"""
|
||||
Returns the contents of the first line in `path` that starts with a digit.
|
||||
"""
|
||||
|
||||
with open(path) as fp:
|
||||
for line in fp:
|
||||
line = line.strip()
|
||||
if line[:1].isdigit():
|
||||
return line
|
||||
|
||||
raise Exception("Didn't find a line that starts with a digit.")
|
||||
|
||||
|
||||
def get_milestone_major(milestone):
|
||||
"""
|
||||
Returns the major (first) part of the milestone.
|
||||
"""
|
||||
|
||||
return milestone.split('.')[0]
|
||||
|
||||
|
||||
def main(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--uaversion', default=False, action='store_true')
|
||||
parser.add_argument('--symbolversion', default=False, action='store_true')
|
||||
parser.add_argument('--topsrcdir', metavar='TOPSRCDIR', required=True)
|
||||
options = parser.parse_args(args)
|
||||
|
||||
milestone_file = os.path.join(options.topsrcdir, 'config', 'milestone.txt')
|
||||
|
||||
milestone = get_official_milestone(milestone_file)
|
||||
|
||||
if options.uaversion:
|
||||
# Only expose the major milestone in the UA string, hide the patch
|
||||
# level (bugs 572659 and 870868).
|
||||
uaversion = "%s.0" % (get_milestone_major(milestone),)
|
||||
print(uaversion)
|
||||
|
||||
elif options.symbolversion:
|
||||
# Only expose major milestone and alpha version. Used for symbol
|
||||
# versioning on Linux.
|
||||
symbolversion = "%s%s" % (get_milestone_major(milestone),
|
||||
get_milestone_ab_with_num(milestone))
|
||||
print(symbolversion)
|
||||
else:
|
||||
print(milestone)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
|
@ -1,10 +0,0 @@
|
|||
[about-blank-replacement.https.html]
|
||||
[Initial about:blank is controlled, exposed to clients.matchAll(), and matches final Client.]
|
||||
expected: FAIL
|
||||
|
||||
[Initial about:blank modified by parent is controlled, exposed to clients.matchAll(), and matches final Client.]
|
||||
expected: FAIL
|
||||
|
||||
[Popup initial about:blank is controlled, exposed to clients.matchAll(), and matches final Client.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[clients-matchall-client-types.https.html]
|
||||
type: testharness
|
||||
[Verify matchAll() with window and sharedworker client types]
|
||||
expected: FAIL
|
||||
|
||||
[Verify matchAll() with {window, sharedworker, worker} client types]
|
||||
expected: FAIL
|
||||
|
|
@ -40,6 +40,54 @@ TEST(CloneInputStream, CloneableInput)
|
|||
testing::ConsumeAndValidateStream(clone, inputString);
|
||||
}
|
||||
|
||||
class NonCloneableInputStream final : public nsIInputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
explicit NonCloneableInputStream(already_AddRefed<nsIInputStream> aInputStream)
|
||||
: mStream(aInputStream)
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
Available(uint64_t* aLength) override
|
||||
{
|
||||
return mStream->Available(aLength);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override
|
||||
{
|
||||
return mStream->Read(aBuffer, aCount, aReadCount);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
|
||||
uint32_t aCount, uint32_t *aResult) override
|
||||
{
|
||||
return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Close() override
|
||||
{
|
||||
return mStream->Close();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
IsNonBlocking(bool* aNonBlocking) override
|
||||
{
|
||||
return mStream->IsNonBlocking(aNonBlocking);
|
||||
}
|
||||
|
||||
private:
|
||||
~NonCloneableInputStream() = default;
|
||||
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(NonCloneableInputStream, nsIInputStream)
|
||||
|
||||
TEST(CloneInputStream, NonCloneableInput_NoFallback)
|
||||
{
|
||||
nsTArray<char> inputData;
|
||||
|
@ -50,12 +98,7 @@ TEST(CloneInputStream, NonCloneableInput_NoFallback)
|
|||
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Take advantage of nsBufferedInputStream being non-cloneable right
|
||||
// now. If this changes in the future, then we need a different stream
|
||||
// type in this test.
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base.forget(), 4096);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
nsCOMPtr<nsIInputStream> stream = new NonCloneableInputStream(base.forget());
|
||||
|
||||
nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
|
||||
ASSERT_TRUE(cloneable == nullptr);
|
||||
|
@ -78,12 +121,7 @@ TEST(CloneInputStream, NonCloneableInput_Fallback)
|
|||
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Take advantage of nsBufferedInputStream being non-cloneable right
|
||||
// now. If this changes in the future, then we need a different stream
|
||||
// type in this test.
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base.forget(), 4096);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
nsCOMPtr<nsIInputStream> stream = new NonCloneableInputStream(base.forget());
|
||||
|
||||
nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
|
||||
ASSERT_TRUE(cloneable == nullptr);
|
||||
|
|
Загрузка…
Ссылка в новой задаче