2013-11-20 03:15:02 +04:00
/* 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 "ServiceWorkerManager.h"
2014-07-15 01:15:23 +04:00
# include "nsIDOMEventTarget.h"
2013-11-20 03:15:02 +04:00
# include "nsIDocument.h"
2014-07-03 04:48:50 +04:00
# include "nsIScriptSecurityManager.h"
2014-12-19 13:00:29 +03:00
# include "nsIStreamLoader.h"
# include "nsIHttpChannel.h"
# include "nsIHttpChannelInternal.h"
2013-11-20 03:15:02 +04:00
# include "nsPIDOMWindow.h"
# include "jsapi.h"
2014-12-12 19:06:00 +03:00
# include "mozilla/LoadContext.h"
2013-11-20 03:15:02 +04:00
# include "mozilla/dom/BindingUtils.h"
2014-06-11 20:12:56 +04:00
# include "mozilla/dom/DOMError.h"
2014-07-03 04:48:35 +04:00
# include "mozilla/dom/ErrorEvent.h"
2014-07-03 04:48:50 +04:00
# include "mozilla/dom/InstallEventBinding.h"
# include "mozilla/dom/PromiseNativeHandler.h"
2014-06-11 20:12:56 +04:00
2013-11-20 03:15:02 +04:00
# include "nsContentUtils.h"
# include "nsNetUtil.h"
2014-06-11 20:12:56 +04:00
# include "nsProxyRelease.h"
2013-11-20 03:15:02 +04:00
# include "nsTArray.h"
# include "RuntimeService.h"
# include "ServiceWorker.h"
2014-10-27 14:03:00 +03:00
# include "ServiceWorkerClient.h"
2014-08-19 17:56:00 +04:00
# include "ServiceWorkerRegistration.h"
2014-07-03 04:48:50 +04:00
# include "ServiceWorkerEvents.h"
2013-11-20 03:15:02 +04:00
# include "WorkerInlines.h"
2014-06-11 20:12:56 +04:00
# include "WorkerPrivate.h"
# include "WorkerRunnable.h"
2014-07-03 04:48:50 +04:00
# include "WorkerScope.h"
2013-11-20 03:15:02 +04:00
2014-12-12 19:06:00 +03:00
# ifdef PostMessage
# undef PostMessage
# endif
2013-11-20 03:15:02 +04:00
using namespace mozilla ;
using namespace mozilla : : dom ;
BEGIN_WORKERS_NAMESPACE
2014-12-19 13:00:29 +03:00
NS_IMPL_ISUPPORTS0 ( ServiceWorkerJob )
2014-08-19 17:56:00 +04:00
NS_IMPL_ISUPPORTS0 ( ServiceWorkerRegistrationInfo )
2014-06-11 20:12:56 +04:00
void
2014-12-19 13:00:29 +03:00
ServiceWorkerJob : : Done ( nsresult aStatus )
2014-06-11 20:12:56 +04:00
{
2014-12-19 13:00:29 +03:00
if ( NS_WARN_IF ( NS_FAILED ( aStatus ) ) ) {
// Windows builds complain if the return value of NS_WARN_IF isn't used.
2014-06-11 20:12:56 +04:00
}
2014-07-03 04:48:35 +04:00
2014-12-19 13:00:29 +03:00
if ( mQueue ) {
mQueue - > Done ( this ) ;
2014-07-03 04:48:35 +04:00
}
}
2014-07-14 21:33:44 +04:00
void
ServiceWorkerRegistrationInfo : : Clear ( )
{
if ( mInstallingWorker ) {
// FIXME(nsm): Terminate installing worker.
// Bug 1043701 Set state to redundant.
// Fire statechange.
mInstallingWorker = nullptr ;
// FIXME(nsm): Abort any inflight requests from installing worker.
}
if ( mWaitingWorker ) {
// FIXME(nsm): Bug 1043701 Set state to redundant.
// Fire statechange.
mWaitingWorker = nullptr ;
2014-12-19 13:00:29 +03:00
mWaitingToActivate = false ;
2014-07-14 21:33:44 +04:00
}
2014-12-19 13:00:29 +03:00
if ( mActiveWorker ) {
2014-07-14 21:33:44 +04:00
// FIXME(nsm): Bug 1043701 Set state to redundant.
2014-12-19 13:00:29 +03:00
mActiveWorker = nullptr ;
2014-07-14 21:33:44 +04:00
}
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
MOZ_ASSERT ( swm ) ;
swm - > InvalidateServiceWorkerRegistrationWorker ( this ,
WhichServiceWorker : : INSTALLING_WORKER |
WhichServiceWorker : : WAITING_WORKER |
WhichServiceWorker : : ACTIVE_WORKER ) ;
}
2014-12-19 13:00:29 +03:00
ServiceWorkerRegistrationInfo : : ServiceWorkerRegistrationInfo ( const nsACString & aScope )
: mControlledDocumentsCounter ( 0 ) ,
mScope ( aScope ) ,
mPendingUninstall ( false )
{ }
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
ServiceWorkerRegistrationInfo : : ~ ServiceWorkerRegistrationInfo ( )
2014-06-11 20:12:56 +04:00
{
2014-12-19 13:00:29 +03:00
if ( IsControllingDocuments ( ) ) {
NS_WARNING ( " ServiceWorkerRegistrationInfo is still controlling documents. This can be a bug or a leak in ServiceWorker API or in any other API that takes the document alive. " ) ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
}
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
class QueueFireUpdateFoundRunnable MOZ_FINAL : public nsRunnable
2014-06-11 20:12:56 +04:00
{
2014-09-10 19:21:32 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > mRegistration ;
2014-06-11 20:12:56 +04:00
public :
2014-12-19 13:00:29 +03:00
explicit QueueFireUpdateFoundRunnable ( ServiceWorkerRegistrationInfo * aReg )
: mRegistration ( aReg )
2014-06-11 20:12:56 +04:00
{
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( aReg ) ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
NS_IMETHOD
Run ( )
2014-06-11 20:12:56 +04:00
{
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-12-19 13:00:29 +03:00
swm - > FireEventOnServiceWorkerRegistrations ( mRegistration ,
NS_LITERAL_STRING ( " updatefound " ) ) ;
return NS_OK ;
2014-06-11 20:12:56 +04:00
}
} ;
2013-11-20 03:15:02 +04:00
//////////////////////////
// ServiceWorkerManager //
//////////////////////////
NS_IMPL_ADDREF ( ServiceWorkerManager )
NS_IMPL_RELEASE ( ServiceWorkerManager )
NS_INTERFACE_MAP_BEGIN ( ServiceWorkerManager )
NS_INTERFACE_MAP_ENTRY ( nsIServiceWorkerManager )
if ( aIID . Equals ( NS_GET_IID ( ServiceWorkerManager ) ) )
foundInterface = static_cast < nsIServiceWorkerManager * > ( this ) ;
else
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , nsIServiceWorkerManager )
NS_INTERFACE_MAP_END
ServiceWorkerManager : : ServiceWorkerManager ( )
{
}
ServiceWorkerManager : : ~ ServiceWorkerManager ( )
{
// The map will assert if it is not empty when destroyed.
mDomainMap . EnumerateRead ( CleanupServiceWorkerInformation , nullptr ) ;
mDomainMap . Clear ( ) ;
}
/* static */ PLDHashOperator
ServiceWorkerManager : : CleanupServiceWorkerInformation ( const nsACString & aDomain ,
ServiceWorkerDomainInfo * aDomainInfo ,
void * aUnused )
{
2014-08-19 17:56:00 +04:00
aDomainInfo - > mServiceWorkerRegistrationInfos . Clear ( ) ;
2013-11-20 03:15:02 +04:00
return PL_DHASH_NEXT ;
}
2014-12-19 13:00:29 +03:00
class ServiceWorkerRegisterJob ;
class FinishInstallRunnable MOZ_FINAL : public nsRunnable
{
nsMainThreadPtrHandle < nsISupports > mJob ;
bool mSuccess ;
bool mActivateImmediately ;
public :
explicit FinishInstallRunnable ( const nsMainThreadPtrHandle < nsISupports > & aJob ,
bool aSuccess ,
bool aActivateImmediately )
: mJob ( aJob )
, mSuccess ( aSuccess )
, mActivateImmediately ( aActivateImmediately )
{
MOZ_ASSERT ( ! NS_IsMainThread ( ) ) ;
}
NS_IMETHOD
Run ( ) MOZ_OVERRIDE ;
} ;
2013-11-20 03:15:02 +04:00
/*
2014-12-19 13:00:29 +03:00
* Fires ' install ' event on the ServiceWorkerGlobalScope . Modifies busy count
* since it fires the event . This is ok since there can ' t be nested
* ServiceWorkers , so the parent thread - > worker thread requirement for
* runnables is satisfied .
2013-11-20 03:15:02 +04:00
*/
2014-12-19 13:00:29 +03:00
class InstallEventRunnable MOZ_FINAL : public WorkerRunnable
2013-11-20 03:15:02 +04:00
{
2014-12-19 13:00:29 +03:00
nsMainThreadPtrHandle < nsISupports > mJob ;
nsCString mScope ;
2013-11-20 03:15:02 +04:00
public :
2014-12-19 13:00:29 +03:00
InstallEventRunnable ( WorkerPrivate * aWorkerPrivate ,
const nsMainThreadPtrHandle < nsISupports > & aJob ,
const nsCString & aScope )
: WorkerRunnable ( aWorkerPrivate , WorkerThreadModifyBusyCount ) ,
mJob ( aJob ) ,
mScope ( aScope )
{
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWorkerPrivate ) ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
bool
WorkerRun ( JSContext * aCx , WorkerPrivate * aWorkerPrivate )
2013-11-20 03:15:02 +04:00
{
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( aWorkerPrivate ) ;
return DispatchInstallEvent ( aCx , aWorkerPrivate ) ;
}
2014-07-21 10:25:44 +04:00
2014-12-19 13:00:29 +03:00
private :
bool
DispatchInstallEvent ( JSContext * aCx , WorkerPrivate * aWorkerPrivate ) ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
} ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
class ServiceWorkerUpdateFinishCallback
{
protected :
virtual ~ ServiceWorkerUpdateFinishCallback ( )
{ }
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
public :
NS_INLINE_DECL_REFCOUNTING ( ServiceWorkerUpdateFinishCallback )
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
virtual
void UpdateSucceeded ( ServiceWorkerRegistrationInfo * aInfo )
{ }
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
virtual
void UpdateFailed ( nsresult aStatus )
{ }
} ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
class ServiceWorkerResolveWindowPromiseOnUpdateCallback MOZ_FINAL : public ServiceWorkerUpdateFinishCallback
{
nsRefPtr < nsPIDOMWindow > mWindow ;
// The promise "returned" by the call to Update up to
// navigator.serviceWorker.register().
nsRefPtr < Promise > mPromise ;
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
~ ServiceWorkerResolveWindowPromiseOnUpdateCallback ( )
{ }
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
public :
ServiceWorkerResolveWindowPromiseOnUpdateCallback ( nsPIDOMWindow * aWindow , Promise * aPromise )
: mWindow ( aWindow )
, mPromise ( aPromise )
{
}
void
UpdateSucceeded ( ServiceWorkerRegistrationInfo * aInfo ) MOZ_OVERRIDE
{
nsRefPtr < ServiceWorkerRegistration > swr =
new ServiceWorkerRegistration ( mWindow ,
NS_ConvertUTF8toUTF16 ( aInfo - > mScope ) ) ;
mPromise - > MaybeResolve ( swr ) ;
}
void
UpdateFailed ( nsresult aStatus ) MOZ_OVERRIDE
{
mPromise - > MaybeReject ( aStatus ) ;
2013-11-20 03:15:02 +04:00
}
} ;
2014-12-19 13:00:29 +03:00
class ServiceWorkerRegisterJob MOZ_FINAL : public ServiceWorkerJob ,
public nsIStreamLoaderObserver
2013-11-20 03:15:02 +04:00
{
2014-12-19 13:00:29 +03:00
friend class FinishInstallRunnable ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
nsCString mScope ;
nsCString mScriptSpec ;
nsRefPtr < ServiceWorkerRegistrationInfo > mRegistration ;
nsRefPtr < ServiceWorkerUpdateFinishCallback > mCallback ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
~ ServiceWorkerRegisterJob ( )
{ }
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
enum
{
REGISTER_JOB = 0 ,
UPDATE_JOB = 1 ,
} mJobType ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
public :
NS_DECL_ISUPPORTS
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
// [[Register]]
ServiceWorkerRegisterJob ( ServiceWorkerJobQueue * aQueue ,
const nsCString & aScope ,
const nsCString & aScriptSpec ,
ServiceWorkerUpdateFinishCallback * aCallback )
: ServiceWorkerJob ( aQueue )
, mScope ( aScope )
, mScriptSpec ( aScriptSpec )
, mCallback ( aCallback )
, mJobType ( REGISTER_JOB )
{ }
2014-08-22 03:31:12 +04:00
2014-12-19 13:00:29 +03:00
// [[Update]]
ServiceWorkerRegisterJob ( ServiceWorkerJobQueue * aQueue ,
ServiceWorkerRegistrationInfo * aRegistration ,
ServiceWorkerUpdateFinishCallback * aCallback )
: ServiceWorkerJob ( aQueue )
, mRegistration ( aRegistration )
, mCallback ( aCallback )
, mJobType ( UPDATE_JOB )
{ }
2014-09-03 00:07:55 +04:00
2014-12-19 13:00:29 +03:00
void
Start ( ) MOZ_OVERRIDE
{
if ( mJobType = = REGISTER_JOB ) {
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
nsRefPtr < ServiceWorkerManager : : ServiceWorkerDomainInfo > domainInfo =
swm - > GetDomainInfo ( mScope ) ;
MOZ_ASSERT ( domainInfo ) ;
mRegistration = domainInfo - > GetRegistration ( mScope ) ;
if ( mRegistration ) {
nsRefPtr < ServiceWorkerInfo > newest = mRegistration - > Newest ( ) ;
if ( newest & & mScriptSpec . Equals ( newest - > GetScriptSpec ( ) ) & &
mScriptSpec . Equals ( mRegistration - > mScriptSpec ) ) {
mRegistration - > mPendingUninstall = false ;
Succeed ( ) ;
Done ( NS_OK ) ;
return ;
}
} else {
mRegistration = domainInfo - > CreateNewRegistration ( mScope ) ;
}
2014-09-03 00:07:55 +04:00
2014-12-19 13:00:29 +03:00
mRegistration - > mScriptSpec = mScriptSpec ;
} else {
MOZ_ASSERT ( mJobType = = UPDATE_JOB ) ;
2014-09-03 00:07:55 +04:00
}
2014-12-19 13:00:29 +03:00
Update ( ) ;
2014-09-03 00:07:55 +04:00
}
2014-12-19 13:00:29 +03:00
NS_IMETHOD
OnStreamComplete ( nsIStreamLoader * aLoader , nsISupports * aContext ,
nsresult aStatus , uint32_t aLen ,
const uint8_t * aString ) MOZ_OVERRIDE
{
if ( NS_WARN_IF ( NS_FAILED ( aStatus ) ) ) {
Fail ( NS_ERROR_DOM_NETWORK_ERR ) ;
return aStatus ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIRequest > request ;
nsresult rv = aLoader - > GetRequest ( getter_AddRefs ( request ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
Fail ( NS_ERROR_DOM_NETWORK_ERR ) ;
return rv ;
}
2014-08-22 03:31:12 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIHttpChannel > httpChannel = do_QueryInterface ( request ) ;
if ( ! httpChannel ) {
Fail ( NS_ERROR_DOM_NETWORK_ERR ) ;
return NS_ERROR_FAILURE ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
bool requestSucceeded ;
rv = httpChannel - > GetRequestSucceeded ( & requestSucceeded ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) | | ! requestSucceeded ) ) {
Fail ( NS_ERROR_DOM_NETWORK_ERR ) ;
return rv ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
// FIXME(nsm): "Extract mime type..."
// FIXME(nsm): Byte match to aString.
NS_WARNING ( " Byte wise check is disabled, just using new one " ) ;
ContinueInstall ( ) ;
return NS_OK ;
2014-08-22 03:31:12 +04:00
}
2014-12-19 13:00:29 +03:00
private :
void
Update ( )
{
MOZ_ASSERT ( mRegistration ) ;
nsCOMPtr < nsIRunnable > r =
NS_NewRunnableMethod ( this , & ServiceWorkerRegisterJob : : ContinueUpdate ) ;
NS_DispatchToMainThread ( r ) ;
2013-11-20 03:15:02 +04:00
}
2014-12-19 13:00:29 +03:00
// Aspects of (actually the whole algorithm) of [[Update]] after
// "Run the following steps in parallel."
void
ContinueUpdate ( )
2014-08-20 19:40:00 +04:00
{
2014-12-19 13:00:29 +03:00
AssertIsOnMainThread ( ) ;
if ( mRegistration - > mInstallingWorker ) {
// FIXME(nsm): "Terminate installing worker".
// "Run the update state"
mRegistration - > mInstallingWorker = nullptr ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Plug in FetchDriver when it is ready.
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , mRegistration - > mScriptSpec , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return Fail ( rv ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIPrincipal > principal ;
nsIScriptSecurityManager * ssm = nsContentUtils : : GetSecurityManager ( ) ;
rv = ssm - > GetNoAppCodebasePrincipal ( uri , getter_AddRefs ( principal ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return Fail ( rv ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIChannel > channel ;
rv = NS_NewChannel ( getter_AddRefs ( channel ) ,
uri ,
principal ,
nsILoadInfo : : SEC_NORMAL ,
nsIContentPolicy : : TYPE_SCRIPT ) ; // FIXME(nsm): TYPE_SERVICEWORKER
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return Fail ( rv ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Set redirect limit.
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
// Don't let serviceworker intercept.
nsCOMPtr < nsIHttpChannelInternal > internalChannel = do_QueryInterface ( channel ) ;
if ( internalChannel ) {
internalChannel - > ForceNoIntercept ( ) ;
}
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIStreamLoader > loader ;
rv = NS_NewStreamLoader ( getter_AddRefs ( loader ) , this ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return Fail ( rv ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
rv = channel - > AsyncOpen ( loader , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return Fail ( rv ) ;
}
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
void
Succeed ( )
{
MOZ_ASSERT ( mCallback ) ;
mCallback - > UpdateSucceeded ( mRegistration ) ;
mCallback = nullptr ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
// This MUST only be called when the job is still performing actions related
// to registration or update. After the spec resolves the update promise, use
// Done() with the failure code instead.
void
Fail ( nsresult rv )
{
MOZ_ASSERT ( mCallback ) ;
mCallback - > UpdateFailed ( rv ) ;
mCallback = nullptr ;
Done ( rv ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
void
ContinueInstall ( )
{
if ( mRegistration - > mInstallingWorker ) {
// FIXME(nsm): Terminate and stuff
}
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
swm - > InvalidateServiceWorkerRegistrationWorker ( mRegistration ,
WhichServiceWorker : : INSTALLING_WORKER ) ;
mRegistration - > mInstallingWorker = new ServiceWorkerInfo ( mRegistration - > mScriptSpec ) ;
mRegistration - > mInstallingWorker - > UpdateState ( ServiceWorkerState : : Installing ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
Succeed ( ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < QueueFireUpdateFoundRunnable > upr =
new QueueFireUpdateFoundRunnable ( mRegistration ) ;
NS_DispatchToMainThread ( upr ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
// XXXnsm this leads to double fetches right now, ideally we'll be able to
// use the persistent cache later.
nsRefPtr < ServiceWorkerJob > upcasted = this ;
nsMainThreadPtrHandle < nsISupports > handle (
new nsMainThreadPtrHolder < nsISupports > ( upcasted ) ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorker > serviceWorker ;
nsresult rv =
swm - > CreateServiceWorker ( mRegistration - > mInstallingWorker - > GetScriptSpec ( ) ,
mRegistration - > mScope ,
getter_AddRefs ( serviceWorker ) ) ;
2014-08-20 19:40:00 +04:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2014-12-19 13:00:29 +03:00
// FIXME(nsm):
MOZ_CRASH ( " Shouldn't happen yet " ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < InstallEventRunnable > r =
new InstallEventRunnable ( serviceWorker - > GetWorkerPrivate ( ) , handle , mRegistration - > mScope ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
AutoJSAPI jsapi ;
jsapi . Init ( ) ;
r - > Dispatch ( jsapi . cx ( ) ) ;
}
void
ContinueAfterInstallEvent ( bool aSuccess , bool aActivateImmediately )
{
// By this point the callback should've been notified about success or fail
// and nulled.
MOZ_ASSERT ( ! mCallback ) ;
if ( ! mRegistration - > mInstallingWorker ) {
NS_WARNING ( " mInstallingWorker was null. " ) ;
return Done ( NS_ERROR_DOM_ABORT_ERR ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
// "If installFailed is true"
if ( ! aSuccess ) {
mRegistration - > mInstallingWorker - > UpdateState ( ServiceWorkerState : : Redundant ) ;
mRegistration - > mInstallingWorker = nullptr ;
swm - > InvalidateServiceWorkerRegistrationWorker ( mRegistration ,
WhichServiceWorker : : INSTALLING_WORKER ) ;
return Done ( NS_ERROR_DOM_ABORT_ERR ) ;
2014-08-20 19:40:00 +04:00
}
2014-12-19 13:00:29 +03:00
// "If registration's waiting worker is not null"
if ( mRegistration - > mWaitingWorker ) {
// FIXME(nsm): Terminate
mRegistration - > mWaitingWorker - > UpdateState ( ServiceWorkerState : : Redundant ) ;
}
mRegistration - > mWaitingWorker = mRegistration - > mInstallingWorker . forget ( ) ;
mRegistration - > mWaitingToActivate = false ;
mRegistration - > mWaitingWorker - > UpdateState ( ServiceWorkerState : : Installed ) ;
swm - > InvalidateServiceWorkerRegistrationWorker ( mRegistration ,
WhichServiceWorker : : INSTALLING_WORKER | WhichServiceWorker : : WAITING_WORKER ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Bug 982711 Deal with activateImmediately.
NS_WARN_IF_FALSE ( ! aActivateImmediately , " Immediate activation using replace() is not supported yet " ) ;
mRegistration - > TryToActivate ( ) ;
Done ( NS_OK ) ;
2014-08-20 19:40:00 +04:00
}
} ;
2014-12-19 13:00:29 +03:00
NS_IMPL_ISUPPORTS_INHERITED ( ServiceWorkerRegisterJob , ServiceWorkerJob , nsIStreamLoaderObserver )
2014-08-20 19:40:00 +04:00
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
2014-12-19 13:00:29 +03:00
ServiceWorkerManager : : Register ( nsIDOMWindow * aWindow ,
const nsAString & aScope ,
const nsAString & aScriptURL ,
nsISupports * * aPromise )
2014-08-20 19:40:00 +04:00
{
AssertIsOnMainThread ( ) ;
// XXXnsm Don't allow chrome callers for now, we don't support chrome
// ServiceWorkers.
MOZ_ASSERT ( ! nsContentUtils : : IsCallerChrome ( ) ) ;
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIDocument > doc = window - > GetExtantDoc ( ) ;
if ( ! doc ) {
2014-08-20 19:40:00 +04:00
return NS_ERROR_FAILURE ;
}
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > documentURI = doc - > GetBaseURI ( ) ;
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
bool authenticatedOrigin = false ;
// FIXME(nsm): Bug 1003991. Disable check when devtools are open.
if ( Preferences : : GetBool ( " dom.serviceWorkers.testing.enabled " ) ) {
authenticatedOrigin = true ;
}
2014-08-20 19:40:00 +04:00
2014-12-19 13:00:29 +03:00
nsresult rv ;
if ( ! authenticatedOrigin ) {
nsAutoCString scheme ;
rv = documentURI - > GetScheme ( scheme ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
if ( scheme . EqualsLiteral ( " https " ) | |
scheme . EqualsLiteral ( " file " ) | |
scheme . EqualsLiteral ( " app " ) ) {
authenticatedOrigin = true ;
}
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
if ( ! authenticatedOrigin ) {
nsAutoCString host ;
rv = documentURI - > GetHost ( host ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
if ( host . Equals ( " 127.0.0.1 " ) | |
host . Equals ( " localhost " ) | |
host . Equals ( " ::1 " ) ) {
authenticatedOrigin = true ;
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
if ( ! authenticatedOrigin ) {
bool isFile ;
rv = documentURI - > SchemeIs ( " file " , & isFile ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
if ( ! isFile ) {
bool isHttps ;
rv = documentURI - > SchemeIs ( " https " , & isHttps ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) | | ! isHttps ) {
NS_WARNING ( " ServiceWorker registration from insecure websites is not allowed. " ) ;
return NS_ERROR_DOM_SECURITY_ERR ;
}
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > scriptURI ;
rv = NS_NewURI ( getter_AddRefs ( scriptURI ) , aScriptURL , nullptr , documentURI ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
// Data URLs are not allowed.
nsCOMPtr < nsIPrincipal > documentPrincipal = doc - > NodePrincipal ( ) ;
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
rv = documentPrincipal - > CheckMayLoad ( scriptURI , true /* report */ ,
false /* allowIfInheritsPrincipal */ ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > scopeURI ;
rv = NS_NewURI ( getter_AddRefs ( scopeURI ) , aScope , nullptr , documentURI ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
}
rv = documentPrincipal - > CheckMayLoad ( scopeURI , true /* report */ ,
false /* allowIfInheritsPrinciple */ ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
}
nsCString cleanedScope ;
rv = scopeURI - > GetSpecIgnoringRef ( cleanedScope ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2014-08-26 12:16:03 +04:00
return NS_ERROR_FAILURE ;
}
2014-12-19 13:00:29 +03:00
nsAutoCString spec ;
rv = scriptURI - > GetSpec ( spec ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
nsRefPtr < ServiceWorkerManager : : ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( cleanedScope ) ;
if ( ! domainInfo ) {
nsAutoCString domain ;
rv = scriptURI - > GetHost ( domain ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
domainInfo = new ServiceWorkerManager : : ServiceWorkerDomainInfo ;
mDomainMap . Put ( domain , domainInfo ) ;
}
2014-08-26 12:16:03 +04:00
nsCOMPtr < nsIGlobalObject > sgo = do_QueryInterface ( window ) ;
ErrorResult result ;
nsRefPtr < Promise > promise = Promise : : Create ( sgo , result ) ;
if ( result . Failed ( ) ) {
return result . ErrorCode ( ) ;
}
2014-12-19 13:00:29 +03:00
ServiceWorkerJobQueue * queue = domainInfo - > GetOrCreateJobQueue ( cleanedScope ) ;
MOZ_ASSERT ( queue ) ;
nsRefPtr < ServiceWorkerResolveWindowPromiseOnUpdateCallback > cb =
new ServiceWorkerResolveWindowPromiseOnUpdateCallback ( window , promise ) ;
nsRefPtr < ServiceWorkerRegisterJob > job =
new ServiceWorkerRegisterJob ( queue , cleanedScope , spec , cb ) ;
queue - > Append ( job ) ;
2014-08-26 12:16:03 +04:00
promise . forget ( aPromise ) ;
2014-12-19 13:00:29 +03:00
return NS_OK ;
2014-08-26 12:16:03 +04:00
}
NS_IMETHODIMP
2014-12-19 13:00:29 +03:00
FinishInstallRunnable : : Run ( )
2014-08-26 12:16:03 +04:00
{
AssertIsOnMainThread ( ) ;
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerJob > job = static_cast < ServiceWorkerJob * > ( mJob . get ( ) ) ;
nsRefPtr < ServiceWorkerRegisterJob > upjob = static_cast < ServiceWorkerRegisterJob * > ( job . get ( ) ) ;
MOZ_ASSERT ( upjob ) ;
upjob - > ContinueAfterInstallEvent ( mSuccess , mActivateImmediately ) ;
2014-08-26 12:16:03 +04:00
return NS_OK ;
}
2014-12-19 13:00:29 +03:00
/*
* Used to handle InstallEvent : : waitUntil ( ) and proceed with installation .
*/
class FinishInstallHandler MOZ_FINAL : public PromiseNativeHandler
2014-08-26 12:16:03 +04:00
{
2014-12-19 13:00:29 +03:00
nsMainThreadPtrHandle < nsISupports > mJob ;
bool mActivateImmediately ;
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
virtual
~ FinishInstallHandler ( )
{ }
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
public :
FinishInstallHandler ( const nsMainThreadPtrHandle < nsISupports > & aJob ,
bool aActivateImmediately )
: mJob ( aJob )
, mActivateImmediately ( aActivateImmediately )
{
MOZ_ASSERT ( ! NS_IsMainThread ( ) ) ;
}
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
void
ResolvedCallback ( JSContext * aCx , JS : : Handle < JS : : Value > aValue ) MOZ_OVERRIDE
{
WorkerPrivate * workerPrivate = GetCurrentThreadWorkerPrivate ( ) ;
MOZ_ASSERT ( workerPrivate ) ;
workerPrivate - > AssertIsOnWorkerThread ( ) ;
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < FinishInstallRunnable > r = new FinishInstallRunnable ( mJob , true , mActivateImmediately ) ;
NS_DispatchToMainThread ( r ) ;
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
void
RejectedCallback ( JSContext * aCx , JS : : Handle < JS : : Value > aValue ) MOZ_OVERRIDE
{
nsRefPtr < FinishInstallRunnable > r = new FinishInstallRunnable ( mJob , false , mActivateImmediately ) ;
NS_DispatchToMainThread ( r ) ;
}
} ;
2014-08-26 12:16:03 +04:00
bool
2014-12-19 13:00:29 +03:00
InstallEventRunnable : : DispatchInstallEvent ( JSContext * aCx , WorkerPrivate * aWorkerPrivate )
2014-08-26 12:16:03 +04:00
{
2014-12-19 13:00:29 +03:00
aWorkerPrivate - > AssertIsOnWorkerThread ( ) ;
MOZ_ASSERT ( aWorkerPrivate - > IsServiceWorker ( ) ) ;
InstallEventInit init ;
init . mBubbles = false ;
init . mCancelable = true ;
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Bug 982787 pass previous active worker.
// FIXME(nsm): Set error handler so we can grab handler errors.
nsRefPtr < EventTarget > target = aWorkerPrivate - > GlobalScope ( ) ;
nsRefPtr < InstallEvent > event =
InstallEvent : : Constructor ( target , NS_LITERAL_STRING ( " install " ) , init ) ;
event - > SetTrusted ( true ) ;
nsRefPtr < Promise > waitUntilPromise ;
ErrorResult result ;
result = target - > DispatchDOMEvent ( nullptr , event , nullptr , nullptr ) ;
nsCOMPtr < nsIGlobalObject > sgo = aWorkerPrivate - > GlobalScope ( ) ;
if ( ! result . Failed ( ) ) {
waitUntilPromise = event - > GetPromise ( ) ;
if ( ! waitUntilPromise ) {
ErrorResult result ;
waitUntilPromise =
Promise : : Resolve ( sgo , aCx , JS : : UndefinedHandleValue , result ) ;
}
} else {
// Continue with a canceled install.
waitUntilPromise = Promise : : Reject ( sgo , aCx ,
JS : : UndefinedHandleValue , result ) ;
2014-08-26 12:16:03 +04:00
}
2014-12-19 13:00:29 +03:00
if ( result . Failed ( ) ) {
return false ;
}
// FIXME(nsm): handle script errors.
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < FinishInstallHandler > handler =
new FinishInstallHandler ( mJob , event - > ActivateImmediately ( ) ) ;
waitUntilPromise - > AppendNativeHandler ( handler ) ;
return true ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
class FinishActivationRunnable MOZ_FINAL : public nsRunnable
2014-07-03 04:48:35 +04:00
{
2014-12-19 13:00:29 +03:00
bool mSuccess ;
nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > mRegistration ;
2014-07-03 04:48:35 +04:00
2014-12-19 13:00:29 +03:00
public :
FinishActivationRunnable ( bool aSuccess ,
const nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > & aRegistration )
: mSuccess ( aSuccess )
, mRegistration ( aRegistration )
{
MOZ_ASSERT ( ! NS_IsMainThread ( ) ) ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
Run ( )
{
AssertIsOnMainThread ( ) ;
mRegistration - > FinishActivate ( mSuccess ) ;
return NS_OK ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
} ;
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
class FinishActivateHandler MOZ_FINAL : public PromiseNativeHandler
{
nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > mRegistration ;
public :
explicit FinishActivateHandler ( const nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > & aRegistration )
: mRegistration ( aRegistration )
{
MOZ_ASSERT ( ! NS_IsMainThread ( ) ) ;
}
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
virtual
~ FinishActivateHandler ( )
{ }
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
void
ResolvedCallback ( JSContext * aCx , JS : : Handle < JS : : Value > aValue ) MOZ_OVERRIDE
{
nsRefPtr < FinishActivationRunnable > r = new FinishActivationRunnable ( true /* success */ , mRegistration ) ;
NS_DispatchToMainThread ( r ) ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
void
RejectedCallback ( JSContext * aCx , JS : : Handle < JS : : Value > aValue ) MOZ_OVERRIDE
{
nsRefPtr < FinishActivationRunnable > r = new FinishActivationRunnable ( false /* success */ , mRegistration ) ;
NS_DispatchToMainThread ( r ) ;
}
} ;
2014-07-14 21:33:44 +04:00
2014-12-19 13:00:29 +03:00
class ActivateEventRunnable : public WorkerRunnable
2013-11-20 03:15:02 +04:00
{
2014-12-19 13:00:29 +03:00
nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > mRegistration ;
2014-07-14 21:33:44 +04:00
2014-12-19 13:00:29 +03:00
public :
ActivateEventRunnable ( WorkerPrivate * aWorkerPrivate ,
const nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > & aRegistration )
: WorkerRunnable ( aWorkerPrivate , WorkerThreadModifyBusyCount ) ,
mRegistration ( aRegistration )
{
MOZ_ASSERT ( aWorkerPrivate ) ;
2014-07-14 21:33:44 +04:00
}
2014-12-19 13:00:29 +03:00
bool
WorkerRun ( JSContext * aCx , WorkerPrivate * aWorkerPrivate )
2014-09-25 18:12:06 +04:00
{
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( aWorkerPrivate ) ;
return DispatchActivateEvent ( aCx , aWorkerPrivate ) ;
}
2014-09-25 18:12:06 +04:00
2014-12-19 13:00:29 +03:00
private :
bool
DispatchActivateEvent ( JSContext * aCx , WorkerPrivate * aWorkerPrivate )
{
MOZ_ASSERT ( aWorkerPrivate - > IsServiceWorker ( ) ) ;
nsRefPtr < EventTarget > target = do_QueryObject ( aWorkerPrivate - > GlobalScope ( ) ) ;
2014-09-25 18:12:06 +04:00
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Set activeWorker to the correct thing.
EventInit init ;
init . mBubbles = false ;
init . mCancelable = true ;
nsRefPtr < InstallPhaseEvent > event =
InstallPhaseEvent : : Constructor ( target , NS_LITERAL_STRING ( " activate " ) , init ) ;
2014-09-25 18:12:06 +04:00
2014-12-19 13:00:29 +03:00
event - > SetTrusted ( true ) ;
2014-09-25 18:12:06 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < Promise > waitUntilPromise ;
2014-09-25 18:12:06 +04:00
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Install error handler for any listener errors.
ErrorResult result ;
result = target - > DispatchDOMEvent ( nullptr , event , nullptr , nullptr ) ;
if ( ! result . Failed ( ) ) {
waitUntilPromise = event - > GetPromise ( ) ;
if ( ! waitUntilPromise ) {
nsCOMPtr < nsIGlobalObject > global =
do_QueryObject ( aWorkerPrivate - > GlobalScope ( ) ) ;
waitUntilPromise =
Promise : : Resolve ( global ,
aCx , JS : : UndefinedHandleValue , result ) ;
2014-09-25 18:12:06 +04:00
}
2014-12-19 13:00:29 +03:00
} else {
nsCOMPtr < nsIGlobalObject > global =
do_QueryObject ( aWorkerPrivate - > GlobalScope ( ) ) ;
// Continue with a canceled install.
waitUntilPromise = Promise : : Reject ( global , aCx ,
JS : : UndefinedHandleValue , result ) ;
2014-09-25 18:12:06 +04:00
}
2014-12-19 13:00:29 +03:00
if ( result . Failed ( ) ) {
return false ;
}
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < FinishActivateHandler > handler = new FinishActivateHandler ( mRegistration ) ;
waitUntilPromise - > AppendNativeHandler ( handler ) ;
return true ;
}
} ;
2013-11-20 03:15:02 +04:00
2014-06-11 20:12:56 +04:00
void
2014-12-19 13:00:29 +03:00
ServiceWorkerRegistrationInfo : : TryToActivate ( )
2014-06-11 20:12:56 +04:00
{
2014-12-19 13:00:29 +03:00
mWaitingToActivate = true ;
if ( ! IsControllingDocuments ( ) ) {
Activate ( ) ;
2014-06-11 20:12:56 +04:00
}
}
void
2014-12-19 13:00:29 +03:00
ServiceWorkerRegistrationInfo : : Activate ( )
2014-06-11 20:12:56 +04:00
{
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( mWaitingToActivate ) ;
mWaitingToActivate = false ;
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerInfo > activatingWorker = mWaitingWorker ;
nsRefPtr < ServiceWorkerInfo > exitingWorker = mActiveWorker ;
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
swm - > InvalidateServiceWorkerRegistrationWorker ( this , WhichServiceWorker : : WAITING_WORKER | WhichServiceWorker : : ACTIVE_WORKER ) ;
if ( ! activatingWorker ) {
NS_WARNING ( " No activatingWorker! " ) ;
2014-06-11 20:12:56 +04:00
return ;
}
2014-12-19 13:00:29 +03:00
if ( exitingWorker ) {
// FIXME(nsm): Wait for worker.
// Terminate worker
exitingWorker - > UpdateState ( ServiceWorkerState : : Redundant ) ;
2014-06-11 20:12:56 +04:00
}
2014-12-19 13:00:29 +03:00
mActiveWorker = activatingWorker . forget ( ) ;
mWaitingWorker = nullptr ;
mActiveWorker - > UpdateState ( ServiceWorkerState : : Activating ) ;
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
swm - > CheckPendingReadyPromises ( ) ;
2014-06-11 20:12:56 +04:00
2014-12-19 13:00:29 +03:00
// "Queue a task to fire a simple event named controllerchange..."
nsCOMPtr < nsIRunnable > controllerChangeRunnable =
NS_NewRunnableMethodWithArg < ServiceWorkerRegistrationInfo * > ( swm , & ServiceWorkerManager : : FireControllerChange , this ) ;
NS_DispatchToMainThread ( controllerChangeRunnable ) ;
2014-07-03 04:48:35 +04:00
2014-12-19 13:00:29 +03:00
// XXXnsm I have my doubts about this. Leaving the main thread means that
// subsequent calls to Activate() not from a Register() call, i.e. due to all
// controlled documents going away, may lead to two or more calls being
// interleaved.
MOZ_ASSERT ( mActiveWorker ) ;
nsRefPtr < ServiceWorker > serviceWorker ;
nsresult rv =
swm - > CreateServiceWorker ( mActiveWorker - > GetScriptSpec ( ) ,
mScope ,
getter_AddRefs ( serviceWorker ) ) ;
2014-07-03 04:48:35 +04:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Do the same thing as when "activate" event failed to
// dispatch.
2014-07-03 04:48:35 +04:00
}
2014-12-19 13:00:29 +03:00
nsMainThreadPtrHandle < ServiceWorkerRegistrationInfo > handle (
new nsMainThreadPtrHolder < ServiceWorkerRegistrationInfo > ( this ) ) ;
2014-07-03 04:48:35 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ActivateEventRunnable > r =
new ActivateEventRunnable ( serviceWorker - > GetWorkerPrivate ( ) , handle ) ;
2014-07-03 04:48:35 +04:00
2014-12-19 13:00:29 +03:00
AutoJSAPI jsapi ;
jsapi . Init ( ) ;
r - > Dispatch ( jsapi . cx ( ) ) ;
2014-07-03 04:48:35 +04:00
}
2014-12-19 13:00:29 +03:00
/*
* Implements the async aspects of the getRegistrations algorithm .
*/
class GetRegistrationsRunnable : public nsRunnable
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsPIDOMWindow > mWindow ;
nsRefPtr < Promise > mPromise ;
2014-07-03 04:48:50 +04:00
public :
2014-12-19 13:00:29 +03:00
GetRegistrationsRunnable ( nsPIDOMWindow * aWindow , Promise * aPromise )
: mWindow ( aWindow ) , mPromise ( aPromise )
{ }
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
Run ( )
2014-07-03 04:48:50 +04:00
{
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-12-19 13:00:29 +03:00
nsIDocument * doc = mWindow - > GetExtantDoc ( ) ;
if ( ! doc ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > docURI = doc - > GetDocumentURI ( ) ;
if ( ! docURI ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIPrincipal > principal = doc - > NodePrincipal ( ) ;
if ( ! principal ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsTArray < nsRefPtr < ServiceWorkerRegistration > > array ;
nsRefPtr < ServiceWorkerManager : : ServiceWorkerDomainInfo > domainInfo =
swm - > GetDomainInfo ( docURI ) ;
if ( ! domainInfo ) {
mPromise - > MaybeResolve ( array ) ;
return NS_OK ;
}
for ( uint32_t i = 0 ; i < domainInfo - > mOrderedScopes . Length ( ) ; + + i ) {
NS_ConvertUTF8toUTF16 scope ( domainInfo - > mOrderedScopes [ i ] ) ;
nsRefPtr < ServiceWorkerRegistration > swr =
new ServiceWorkerRegistration ( mWindow , scope ) ;
array . AppendElement ( swr ) ;
}
mPromise - > MaybeResolve ( array ) ;
2014-07-12 00:07:59 +04:00
return NS_OK ;
}
} ;
2014-12-19 13:00:29 +03:00
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
ServiceWorkerManager : : GetRegistrations ( nsIDOMWindow * aWindow ,
nsISupports * * aPromise )
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWindow ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
// XXXnsm Don't allow chrome callers for now, we don't support chrome
// ServiceWorkers.
MOZ_ASSERT ( ! nsContentUtils : : IsCallerChrome ( ) ) ;
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
if ( ! window ) {
return NS_ERROR_FAILURE ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIGlobalObject > sgo = do_QueryInterface ( window ) ;
ErrorResult result ;
nsRefPtr < Promise > promise = Promise : : Create ( sgo , result ) ;
if ( result . Failed ( ) ) {
return result . ErrorCode ( ) ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < nsIRunnable > runnable =
new GetRegistrationsRunnable ( window , promise ) ;
promise . forget ( aPromise ) ;
return NS_DispatchToCurrentThread ( runnable ) ;
}
2014-07-03 04:48:50 +04:00
/*
2014-12-19 13:00:29 +03:00
* Implements the async aspects of the getRegistration algorithm .
2014-07-03 04:48:50 +04:00
*/
2014-12-19 13:00:29 +03:00
class GetRegistrationRunnable : public nsRunnable
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsPIDOMWindow > mWindow ;
nsRefPtr < Promise > mPromise ;
nsString mDocumentURL ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
public :
GetRegistrationRunnable ( nsPIDOMWindow * aWindow , Promise * aPromise ,
const nsAString & aDocumentURL )
: mWindow ( aWindow ) , mPromise ( aPromise ) , mDocumentURL ( aDocumentURL )
2014-07-03 04:48:50 +04:00
{ }
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
Run ( )
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsIDocument * doc = mWindow - > GetExtantDoc ( ) ;
if ( ! doc ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > docURI = doc - > GetDocumentURI ( ) ;
if ( ! docURI ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , mDocumentURL , nullptr , docURI ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
mPromise - > MaybeReject ( rv ) ;
return NS_OK ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIPrincipal > principal = doc - > NodePrincipal ( ) ;
if ( ! principal ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
rv = principal - > CheckMayLoad ( uri , true /* report */ ,
false /* allowIfInheritsPrinciple */ ) ;
if ( NS_FAILED ( rv ) ) {
mPromise - > MaybeReject ( NS_ERROR_DOM_SECURITY_ERR ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration =
swm - > GetServiceWorkerRegistrationInfo ( uri ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
if ( ! registration ) {
mPromise - > MaybeResolve ( JS : : UndefinedHandleValue ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
NS_ConvertUTF8toUTF16 scope ( registration - > mScope ) ;
nsRefPtr < ServiceWorkerRegistration > swr =
new ServiceWorkerRegistration ( mWindow , scope ) ;
mPromise - > MaybeResolve ( swr ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
return NS_OK ;
2014-07-12 00:07:59 +04:00
}
} ;
2014-12-19 13:00:29 +03:00
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
ServiceWorkerManager : : GetRegistration ( nsIDOMWindow * aWindow ,
const nsAString & aDocumentURL ,
nsISupports * * aPromise )
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWindow ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
// XXXnsm Don't allow chrome callers for now, we don't support chrome
// ServiceWorkers.
MOZ_ASSERT ( ! nsContentUtils : : IsCallerChrome ( ) ) ;
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
if ( ! window ) {
return NS_ERROR_FAILURE ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIGlobalObject > sgo = do_QueryInterface ( window ) ;
ErrorResult result ;
nsRefPtr < Promise > promise = Promise : : Create ( sgo , result ) ;
if ( result . Failed ( ) ) {
return result . ErrorCode ( ) ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < nsIRunnable > runnable =
new GetRegistrationRunnable ( window , promise , aDocumentURL ) ;
promise . forget ( aPromise ) ;
return NS_DispatchToCurrentThread ( runnable ) ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
class GetReadyPromiseRunnable : public nsRunnable
{
nsCOMPtr < nsPIDOMWindow > mWindow ;
nsRefPtr < Promise > mPromise ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
public :
GetReadyPromiseRunnable ( nsPIDOMWindow * aWindow , Promise * aPromise )
: mWindow ( aWindow ) , mPromise ( aPromise )
{ }
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
Run ( )
{
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsIDocument * doc = mWindow - > GetExtantDoc ( ) ;
if ( ! doc ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > docURI = doc - > GetDocumentURI ( ) ;
if ( ! docURI ) {
mPromise - > MaybeReject ( NS_ERROR_UNEXPECTED ) ;
return NS_OK ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
if ( ! swm - > CheckReadyPromise ( mWindow , docURI , mPromise ) ) {
swm - > StorePendingReadyPromise ( mWindow , docURI , mPromise ) ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
return NS_OK ;
}
} ;
NS_IMETHODIMP
ServiceWorkerManager : : GetReadyPromise ( nsIDOMWindow * aWindow ,
nsISupports * * aPromise )
{
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWindow ) ;
// XXXnsm Don't allow chrome callers for now, we don't support chrome
// ServiceWorkers.
MOZ_ASSERT ( ! nsContentUtils : : IsCallerChrome ( ) ) ;
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
if ( ! window ) {
return NS_ERROR_FAILURE ;
}
MOZ_ASSERT ( ! mPendingReadyPromises . Contains ( window ) ) ;
nsCOMPtr < nsIGlobalObject > sgo = do_QueryInterface ( window ) ;
ErrorResult result ;
nsRefPtr < Promise > promise = Promise : : Create ( sgo , result ) ;
if ( result . Failed ( ) ) {
return result . ErrorCode ( ) ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < nsIRunnable > runnable =
new GetReadyPromiseRunnable ( window , promise ) ;
promise . forget ( aPromise ) ;
return NS_DispatchToCurrentThread ( runnable ) ;
}
NS_IMETHODIMP
ServiceWorkerManager : : RemoveReadyPromise ( nsIDOMWindow * aWindow )
2014-07-12 00:07:59 +04:00
{
2014-12-19 13:00:29 +03:00
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWindow ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
if ( ! window ) {
return NS_ERROR_FAILURE ;
2014-07-12 00:07:59 +04:00
}
2014-12-19 13:00:29 +03:00
mPendingReadyPromises . Remove ( aWindow ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
void
ServiceWorkerManager : : StorePendingReadyPromise ( nsPIDOMWindow * aWindow ,
nsIURI * aURI ,
Promise * aPromise )
{
PendingReadyPromise * data ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
// We should not have 2 pending promises for the same window.
MOZ_ASSERT ( ! mPendingReadyPromises . Get ( aWindow , & data ) ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
data = new PendingReadyPromise ( aURI , aPromise ) ;
mPendingReadyPromises . Put ( aWindow , data ) ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
void
ServiceWorkerManager : : CheckPendingReadyPromises ( )
{
mPendingReadyPromises . Enumerate ( CheckPendingReadyPromisesEnumerator , this ) ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
PLDHashOperator
ServiceWorkerManager : : CheckPendingReadyPromisesEnumerator (
nsISupports * aSupports ,
nsAutoPtr < PendingReadyPromise > & aData ,
void * aPtr )
{
ServiceWorkerManager * aSwm = static_cast < ServiceWorkerManager * > ( aPtr ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aSupports ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
if ( aSwm - > CheckReadyPromise ( window , aData - > mURI , aData - > mPromise ) ) {
return PL_DHASH_REMOVE ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
return PL_DHASH_NEXT ;
}
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
bool
ServiceWorkerManager : : CheckReadyPromise ( nsPIDOMWindow * aWindow ,
nsIURI * aURI , Promise * aPromise )
{
nsRefPtr < ServiceWorkerRegistrationInfo > registration =
GetServiceWorkerRegistrationInfo ( aURI ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
if ( registration & & registration - > mActiveWorker ) {
NS_ConvertUTF8toUTF16 scope ( registration - > mScope ) ;
nsRefPtr < ServiceWorkerRegistration > swr =
new ServiceWorkerRegistration ( aWindow , scope ) ;
aPromise - > MaybeResolve ( swr ) ;
return true ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
return false ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
ServiceWorkerManager : : Unregister ( nsIServiceWorkerUnregisterCallback * aCallback ,
const nsAString & aScope )
2014-07-03 04:48:50 +04:00
{
2014-12-19 13:00:29 +03:00
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aCallback ) ;
nsCOMPtr < nsIURI > scopeURI ;
nsresult rv = NS_NewURI ( getter_AddRefs ( scopeURI ) , aScope , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
2014-07-12 00:07:59 +04:00
}
2014-12-19 13:00:29 +03:00
/*
* Implements the async aspects of the unregister algorithm .
*/
class UnregisterRunnable : public nsRunnable
2014-07-12 00:07:59 +04:00
{
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIServiceWorkerUnregisterCallback > mCallback ;
nsCOMPtr < nsIURI > mScopeURI ;
public :
UnregisterRunnable ( nsIServiceWorkerUnregisterCallback * aCallback ,
nsIURI * aScopeURI )
: mCallback ( aCallback ) , mScopeURI ( aScopeURI )
{
AssertIsOnMainThread ( ) ;
2014-07-12 00:07:59 +04:00
}
2014-12-19 13:00:29 +03:00
NS_IMETHODIMP
Run ( )
{
AssertIsOnMainThread ( ) ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerManager > swm = ServiceWorkerManager : : GetInstance ( ) ;
2014-07-24 01:05:08 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerManager : : ServiceWorkerDomainInfo > domainInfo =
swm - > GetDomainInfo ( mScopeURI ) ;
MOZ_ASSERT ( domainInfo ) ;
2014-08-26 12:16:03 +04:00
2014-12-19 13:00:29 +03:00
nsCString spec ;
nsresult rv = mScopeURI - > GetSpecIgnoringRef ( spec ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return mCallback - > UnregisterFailed ( ) ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration ;
if ( ! domainInfo - > mServiceWorkerRegistrationInfos . Get ( spec ,
getter_AddRefs ( registration ) ) ) {
return mCallback - > UnregisterSucceeded ( false ) ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( registration ) ;
registration - > mPendingUninstall = true ;
rv = mCallback - > UnregisterSucceeded ( true ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
// The "Wait until no document is using registration" can actually be
// handled by [[HandleDocumentUnload]] in Bug 1041340, so we simply check
// if the document is currently in use here.
if ( ! registration - > IsControllingDocuments ( ) ) {
if ( ! registration - > mPendingUninstall ) {
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
registration - > Clear ( ) ;
domainInfo - > RemoveRegistration ( registration ) ;
}
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
return NS_OK ;
2014-07-12 00:07:59 +04:00
}
2014-12-19 13:00:29 +03:00
} ;
2014-07-12 00:07:59 +04:00
2014-12-19 13:00:29 +03:00
nsRefPtr < nsIRunnable > unregisterRunnable =
new UnregisterRunnable ( aCallback , scopeURI ) ;
return NS_DispatchToCurrentThread ( unregisterRunnable ) ;
}
/* static */
already_AddRefed < ServiceWorkerManager >
ServiceWorkerManager : : GetInstance ( )
{
nsCOMPtr < nsIServiceWorkerManager > swm = mozilla : : services : : GetServiceWorkerManager ( ) ;
nsRefPtr < ServiceWorkerManager > concrete = do_QueryObject ( swm ) ;
return concrete . forget ( ) ;
}
void
ServiceWorkerManager : : FinishFetch ( ServiceWorkerRegistrationInfo * aRegistration )
{
}
2014-07-03 04:48:50 +04:00
void
2014-12-19 13:00:29 +03:00
ServiceWorkerManager : : HandleError ( JSContext * aCx ,
const nsACString & aScope ,
const nsAString & aWorkerURL ,
nsString aMessage ,
nsString aFilename ,
nsString aLine ,
uint32_t aLineNumber ,
uint32_t aColumnNumber ,
uint32_t aFlags )
2014-07-03 04:48:50 +04:00
{
AssertIsOnMainThread ( ) ;
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , aScope , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return ;
2014-07-03 04:48:50 +04:00
}
2014-12-19 13:00:29 +03:00
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( uri ) ;
if ( ! domainInfo ) {
2014-07-23 05:18:48 +04:00
return ;
}
2014-12-19 13:00:29 +03:00
nsCString scope ;
scope . Assign ( aScope ) ;
nsRefPtr < ServiceWorkerRegistrationInfo > registration = domainInfo - > GetRegistration ( scope ) ;
MOZ_ASSERT ( registration ) ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
RootedDictionary < ErrorEventInit > init ( aCx ) ;
init . mMessage = aMessage ;
init . mFilename = aFilename ;
init . mLineno = aLineNumber ;
init . mColno = aColumnNumber ;
2014-07-03 04:48:50 +04:00
2014-12-19 13:00:29 +03:00
MOZ_CRASH ( " FIX THIS " ) ;
2014-06-11 20:12:56 +04:00
}
2014-07-12 00:07:59 +04:00
void
2014-12-19 13:00:29 +03:00
ServiceWorkerRegistrationInfo : : FinishActivate ( bool aSuccess )
2014-07-12 00:07:59 +04:00
{
2014-12-19 13:00:29 +03:00
MOZ_ASSERT ( mActiveWorker ) ;
if ( aSuccess ) {
mActiveWorker - > UpdateState ( ServiceWorkerState : : Activated ) ;
} else {
mActiveWorker - > UpdateState ( ServiceWorkerState : : Redundant ) ;
mActiveWorker = nullptr ;
}
2014-07-12 00:07:59 +04:00
}
2013-11-20 03:15:02 +04:00
NS_IMETHODIMP
ServiceWorkerManager : : CreateServiceWorkerForWindow ( nsPIDOMWindow * aWindow ,
const nsACString & aScriptSpec ,
const nsACString & aScope ,
ServiceWorker * * aServiceWorker )
{
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aWindow ) ;
RuntimeService * rs = RuntimeService : : GetOrCreateService ( ) ;
nsRefPtr < ServiceWorker > serviceWorker ;
2014-12-19 13:00:29 +03:00
AutoJSAPI jsapi ;
jsapi . Init ( aWindow ) ;
JSContext * cx = jsapi . cx ( ) ;
2013-11-20 03:15:02 +04:00
2014-12-19 13:00:29 +03:00
nsCOMPtr < nsIGlobalObject > sgo = do_QueryInterface ( aWindow ) ;
2013-11-20 03:15:02 +04:00
JS : : Rooted < JSObject * > jsGlobal ( cx , sgo - > GetGlobalJSObject ( ) ) ;
GlobalObject global ( cx , jsGlobal ) ;
nsresult rv = rs - > CreateServiceWorker ( global ,
NS_ConvertUTF8toUTF16 ( aScriptSpec ) ,
aScope ,
getter_AddRefs ( serviceWorker ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
serviceWorker . forget ( aServiceWorker ) ;
return rv ;
}
2014-08-19 17:56:00 +04:00
already_AddRefed < ServiceWorkerRegistrationInfo >
ServiceWorkerManager : : GetServiceWorkerRegistrationInfo ( nsPIDOMWindow * aWindow )
2014-07-11 22:52:19 +04:00
{
2014-07-21 10:25:44 +04:00
nsCOMPtr < nsIDocument > document = aWindow - > GetExtantDoc ( ) ;
2014-08-19 17:56:00 +04:00
return GetServiceWorkerRegistrationInfo ( document ) ;
2014-07-11 22:52:19 +04:00
}
2014-08-19 17:56:00 +04:00
already_AddRefed < ServiceWorkerRegistrationInfo >
ServiceWorkerManager : : GetServiceWorkerRegistrationInfo ( nsIDocument * aDoc )
2014-07-11 22:52:19 +04:00
{
nsCOMPtr < nsIURI > documentURI = aDoc - > GetDocumentURI ( ) ;
2014-08-19 17:56:00 +04:00
return GetServiceWorkerRegistrationInfo ( documentURI ) ;
2014-07-11 22:52:19 +04:00
}
2014-08-19 17:56:00 +04:00
already_AddRefed < ServiceWorkerRegistrationInfo >
ServiceWorkerManager : : GetServiceWorkerRegistrationInfo ( nsIURI * aURI )
2014-07-11 22:52:19 +04:00
{
2014-07-15 01:15:23 +04:00
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( aURI ) ;
2014-07-11 22:52:19 +04:00
if ( ! domainInfo ) {
return nullptr ;
}
nsCString spec ;
2014-07-15 01:15:23 +04:00
nsresult rv = aURI - > GetSpec ( spec ) ;
2014-07-11 22:52:19 +04:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return nullptr ;
}
nsCString scope = FindScopeForPath ( domainInfo - > mOrderedScopes , spec ) ;
if ( scope . IsEmpty ( ) ) {
return nullptr ;
}
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration ;
domainInfo - > mServiceWorkerRegistrationInfos . Get ( scope , getter_AddRefs ( registration ) ) ;
2014-07-11 22:52:19 +04:00
// ordered scopes and registrations better be in sync.
MOZ_ASSERT ( registration ) ;
2014-07-14 21:33:44 +04:00
if ( registration - > mPendingUninstall ) {
return nullptr ;
}
2014-07-28 17:57:31 +04:00
return registration . forget ( ) ;
2014-07-11 22:52:19 +04:00
}
/* static */ void
ServiceWorkerManager : : AddScope ( nsTArray < nsCString > & aList , const nsACString & aScope )
{
for ( uint32_t i = 0 ; i < aList . Length ( ) ; + + i ) {
const nsCString & current = aList [ i ] ;
// Perfect match!
if ( aScope . Equals ( current ) ) {
return ;
}
2014-08-22 03:38:40 +04:00
// Sort by length, with longest match first.
// /foo/bar should be before /foo/
// Similarly /foo/b is between the two.
if ( StringBeginsWith ( aScope , current ) ) {
2014-07-11 22:52:19 +04:00
aList . InsertElementAt ( i , aScope ) ;
return ;
}
}
aList . AppendElement ( aScope ) ;
}
/* static */ nsCString
ServiceWorkerManager : : FindScopeForPath ( nsTArray < nsCString > & aList , const nsACString & aPath )
{
nsCString match ;
for ( uint32_t i = 0 ; i < aList . Length ( ) ; + + i ) {
const nsCString & current = aList [ i ] ;
2014-08-22 03:38:40 +04:00
if ( StringBeginsWith ( aPath , current ) ) {
match = current ;
break ;
2014-07-11 22:52:19 +04:00
}
}
return match ;
}
/* static */ void
ServiceWorkerManager : : RemoveScope ( nsTArray < nsCString > & aList , const nsACString & aScope )
{
aList . RemoveElement ( aScope ) ;
}
2014-07-15 01:15:23 +04:00
already_AddRefed < ServiceWorkerManager : : ServiceWorkerDomainInfo >
ServiceWorkerManager : : GetDomainInfo ( nsIDocument * aDoc )
{
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aDoc ) ;
nsCOMPtr < nsIURI > documentURI = aDoc - > GetDocumentURI ( ) ;
return GetDomainInfo ( documentURI ) ;
}
already_AddRefed < ServiceWorkerManager : : ServiceWorkerDomainInfo >
ServiceWorkerManager : : GetDomainInfo ( nsIURI * aURI )
{
AssertIsOnMainThread ( ) ;
MOZ_ASSERT ( aURI ) ;
2014-12-19 13:00:29 +03:00
nsAutoCString domain ;
2014-07-15 01:15:23 +04:00
nsresult rv = aURI - > GetHost ( domain ) ;
2014-12-19 13:00:29 +03:00
if ( NS_FAILED ( rv ) ) {
2014-07-15 01:15:23 +04:00
return nullptr ;
}
nsRefPtr < ServiceWorkerDomainInfo > domainInfo ;
mDomainMap . Get ( domain , getter_AddRefs ( domainInfo ) ) ;
return domainInfo . forget ( ) ;
}
already_AddRefed < ServiceWorkerManager : : ServiceWorkerDomainInfo >
ServiceWorkerManager : : GetDomainInfo ( const nsCString & aURL )
{
AssertIsOnMainThread ( ) ;
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , aURL , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return nullptr ;
}
return GetDomainInfo ( uri ) ;
}
2014-07-21 10:25:44 +04:00
void
ServiceWorkerManager : : MaybeStartControlling ( nsIDocument * aDoc )
{
AssertIsOnMainThread ( ) ;
if ( ! Preferences : : GetBool ( " dom.serviceWorkers.enabled " ) ) {
return ;
}
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( aDoc ) ;
if ( ! domainInfo ) {
return ;
}
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration =
GetServiceWorkerRegistrationInfo ( aDoc ) ;
2014-12-19 13:00:29 +03:00
if ( registration ) {
2014-07-21 10:25:44 +04:00
MOZ_ASSERT ( ! domainInfo - > mControlledDocuments . Contains ( aDoc ) ) ;
registration - > StartControllingADocument ( ) ;
// Use the already_AddRefed<> form of Put to avoid the addref-deref since
// we don't need the registration pointer in this function anymore.
domainInfo - > mControlledDocuments . Put ( aDoc , registration . forget ( ) ) ;
}
}
void
ServiceWorkerManager : : MaybeStopControlling ( nsIDocument * aDoc )
{
MOZ_ASSERT ( aDoc ) ;
if ( ! Preferences : : GetBool ( " dom.serviceWorkers.enabled " ) ) {
return ;
}
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( aDoc ) ;
if ( ! domainInfo ) {
return ;
}
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration ;
2014-07-21 10:25:44 +04:00
domainInfo - > mControlledDocuments . Remove ( aDoc , getter_AddRefs ( registration ) ) ;
// A document which was uncontrolled does not maintain that state itself, so
// it will always call MaybeStopControlling() even if there isn't an
// associated registration. So this check is required.
if ( registration ) {
registration - > StopControllingADocument ( ) ;
}
}
2014-07-11 22:52:19 +04:00
NS_IMETHODIMP
ServiceWorkerManager : : GetScopeForUrl ( const nsAString & aUrl , nsAString & aScope )
{
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , aUrl , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_FAILURE ;
}
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > r = GetServiceWorkerRegistrationInfo ( uri ) ;
2014-07-11 22:52:19 +04:00
if ( ! r ) {
return NS_ERROR_FAILURE ;
}
aScope = NS_ConvertUTF8toUTF16 ( r - > mScope ) ;
return NS_OK ;
}
2014-07-12 00:07:59 +04:00
2014-07-15 01:15:23 +04:00
NS_IMETHODIMP
2014-10-27 21:52:57 +03:00
ServiceWorkerManager : : AddRegistrationEventListener ( const nsAString & aScope , nsIDOMEventTarget * aListener )
2014-07-15 01:15:23 +04:00
{
2014-08-28 00:33:20 +04:00
AssertIsOnMainThread ( ) ;
2014-10-27 21:52:57 +03:00
nsAutoCString scope = NS_ConvertUTF16toUTF8 ( aScope ) ;
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( scope ) ;
2014-07-15 01:15:23 +04:00
if ( ! domainInfo ) {
2014-10-27 21:52:57 +03:00
nsCOMPtr < nsIURI > scopeAsURI ;
nsresult rv = NS_NewURI ( getter_AddRefs ( scopeAsURI ) , scope , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
2014-12-19 13:00:29 +03:00
nsAutoCString domain ;
2014-10-27 21:52:57 +03:00
rv = scopeAsURI - > GetHost ( domain ) ;
2014-07-15 01:15:23 +04:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
domainInfo = new ServiceWorkerDomainInfo ;
mDomainMap . Put ( domain , domainInfo ) ;
}
MOZ_ASSERT ( domainInfo ) ;
2014-08-19 17:56:00 +04:00
// TODO: this is very very bad:
ServiceWorkerRegistration * registration = static_cast < ServiceWorkerRegistration * > ( aListener ) ;
2014-08-20 21:30:00 +04:00
MOZ_ASSERT ( ! domainInfo - > mServiceWorkerRegistrations . Contains ( registration ) ) ;
2014-10-27 21:52:57 +03:00
# ifdef DEBUG
// Ensure a registration is only listening for it's own scope.
nsAutoString regScope ;
registration - > GetScope ( regScope ) ;
MOZ_ASSERT ( ! regScope . IsEmpty ( ) ) ;
MOZ_ASSERT ( scope . Equals ( NS_ConvertUTF16toUTF8 ( regScope ) ) ) ;
# endif
2014-08-19 17:56:00 +04:00
domainInfo - > mServiceWorkerRegistrations . AppendElement ( registration ) ;
2014-07-15 01:15:23 +04:00
return NS_OK ;
}
NS_IMETHODIMP
2014-10-27 21:52:57 +03:00
ServiceWorkerManager : : RemoveRegistrationEventListener ( const nsAString & aScope , nsIDOMEventTarget * aListener )
2014-07-15 01:15:23 +04:00
{
2014-08-28 00:33:20 +04:00
AssertIsOnMainThread ( ) ;
2014-10-27 21:52:57 +03:00
nsCString scope = NS_ConvertUTF16toUTF8 ( aScope ) ;
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( scope ) ;
2014-07-15 01:15:23 +04:00
if ( ! domainInfo ) {
return NS_OK ;
}
2014-08-19 17:56:00 +04:00
ServiceWorkerRegistration * registration = static_cast < ServiceWorkerRegistration * > ( aListener ) ;
2014-08-20 21:30:00 +04:00
MOZ_ASSERT ( domainInfo - > mServiceWorkerRegistrations . Contains ( registration ) ) ;
2014-10-27 21:52:57 +03:00
# ifdef DEBUG
// Ensure a registration is unregistering for it's own scope.
nsAutoString regScope ;
registration - > GetScope ( regScope ) ;
MOZ_ASSERT ( ! regScope . IsEmpty ( ) ) ;
MOZ_ASSERT ( scope . Equals ( NS_ConvertUTF16toUTF8 ( regScope ) ) ) ;
# endif
2014-08-19 17:56:00 +04:00
domainInfo - > mServiceWorkerRegistrations . RemoveElement ( registration ) ;
2014-07-15 01:15:23 +04:00
return NS_OK ;
}
void
2014-08-19 17:56:00 +04:00
ServiceWorkerManager : : FireEventOnServiceWorkerRegistrations (
ServiceWorkerRegistrationInfo * aRegistration ,
2014-07-15 01:15:23 +04:00
const nsAString & aName )
{
AssertIsOnMainThread ( ) ;
nsRefPtr < ServiceWorkerDomainInfo > domainInfo =
2014-10-27 21:52:57 +03:00
GetDomainInfo ( aRegistration - > mScope ) ;
2014-07-15 01:15:23 +04:00
if ( domainInfo ) {
2014-08-19 17:56:00 +04:00
nsTObserverArray < ServiceWorkerRegistration * > : : ForwardIterator it ( domainInfo - > mServiceWorkerRegistrations ) ;
2014-07-15 01:15:23 +04:00
while ( it . HasMore ( ) ) {
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistration > target = it . GetNext ( ) ;
2014-10-27 21:52:57 +03:00
nsAutoString regScope ;
target - > GetScope ( regScope ) ;
MOZ_ASSERT ( ! regScope . IsEmpty ( ) ) ;
NS_ConvertUTF16toUTF8 utf8Scope ( regScope ) ;
if ( utf8Scope . Equals ( aRegistration - > mScope ) ) {
nsresult rv = target - > DispatchTrustedEvent ( aName ) ;
2015-01-23 22:53:23 +03:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
// Warn only.
}
2014-07-15 01:15:23 +04:00
}
}
}
}
2014-07-24 01:05:08 +04:00
/*
2014-08-25 09:35:03 +04:00
* This is used for installing , waiting and active .
2014-07-24 01:05:08 +04:00
*/
NS_IMETHODIMP
2014-08-25 09:35:03 +04:00
ServiceWorkerManager : : GetServiceWorkerForScope ( nsIDOMWindow * aWindow ,
const nsAString & aScope ,
WhichServiceWorker aWhichWorker ,
nsISupports * * aServiceWorker )
2014-07-24 01:05:08 +04:00
{
2014-08-25 09:35:03 +04:00
AssertIsOnMainThread ( ) ;
2014-07-24 01:05:08 +04:00
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
2014-08-25 09:35:03 +04:00
if ( ! window ) {
return NS_ERROR_FAILURE ;
}
2014-07-24 01:05:08 +04:00
2014-08-25 09:35:03 +04:00
nsCOMPtr < nsIDocument > doc = window - > GetExtantDoc ( ) ;
MOZ_ASSERT ( doc ) ;
///////////////////////////////////////////
// Security check
2014-10-27 21:52:57 +03:00
nsAutoCString scope = NS_ConvertUTF16toUTF8 ( aScope ) ;
2014-08-25 09:35:03 +04:00
nsCOMPtr < nsIURI > scopeURI ;
// We pass nullptr as the base URI since scopes obtained from
// ServiceWorkerRegistrations MUST be fully qualified URIs.
nsresult rv = NS_NewURI ( getter_AddRefs ( scopeURI ) , scope , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
}
nsCOMPtr < nsIPrincipal > documentPrincipal = doc - > NodePrincipal ( ) ;
rv = documentPrincipal - > CheckMayLoad ( scopeURI , true /* report */ ,
false /* allowIfInheritsPrinciple */ ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return NS_ERROR_DOM_SECURITY_ERR ;
}
////////////////////////////////////////////
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( scope ) ;
if ( ! domainInfo ) {
return NS_ERROR_FAILURE ;
}
2014-07-24 01:05:08 +04:00
2014-08-25 09:35:03 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration =
domainInfo - > GetRegistration ( scope ) ;
2014-07-24 01:05:08 +04:00
if ( ! registration ) {
return NS_ERROR_FAILURE ;
}
nsRefPtr < ServiceWorkerInfo > info ;
if ( aWhichWorker = = WhichServiceWorker : : INSTALLING_WORKER ) {
info = registration - > mInstallingWorker ;
} else if ( aWhichWorker = = WhichServiceWorker : : WAITING_WORKER ) {
info = registration - > mWaitingWorker ;
} else if ( aWhichWorker = = WhichServiceWorker : : ACTIVE_WORKER ) {
2014-12-19 13:00:29 +03:00
info = registration - > mActiveWorker ;
2014-07-24 01:05:08 +04:00
} else {
MOZ_CRASH ( " Invalid worker type " ) ;
}
if ( ! info ) {
return NS_ERROR_DOM_NOT_FOUND_ERR ;
}
nsRefPtr < ServiceWorker > serviceWorker ;
2014-08-25 09:35:03 +04:00
rv = CreateServiceWorkerForWindow ( window ,
info - > GetScriptSpec ( ) ,
registration - > mScope ,
getter_AddRefs ( serviceWorker ) ) ;
2014-07-24 01:05:08 +04:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
serviceWorker . forget ( aServiceWorker ) ;
return NS_OK ;
}
/*
* The . controller is for the registration associated with the document when
* the document was loaded .
*/
NS_IMETHODIMP
ServiceWorkerManager : : GetDocumentController ( nsIDOMWindow * aWindow , nsISupports * * aServiceWorker )
{
nsCOMPtr < nsPIDOMWindow > window = do_QueryInterface ( aWindow ) ;
MOZ_ASSERT ( window ) ;
if ( ! window | | ! window - > GetExtantDoc ( ) ) {
return NS_ERROR_FAILURE ;
}
nsCOMPtr < nsIDocument > doc = window - > GetExtantDoc ( ) ;
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( doc ) ;
if ( ! domainInfo ) {
return NS_ERROR_FAILURE ;
}
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistrationInfo > registration ;
2014-07-24 01:05:08 +04:00
if ( ! domainInfo - > mControlledDocuments . Get ( doc , getter_AddRefs ( registration ) ) ) {
return NS_ERROR_FAILURE ;
}
// If the document is controlled, the current worker MUST be non-null.
2014-12-19 13:00:29 +03:00
if ( ! registration - > mActiveWorker ) {
return NS_ERROR_NOT_AVAILABLE ;
}
2014-07-24 01:05:08 +04:00
nsRefPtr < ServiceWorker > serviceWorker ;
nsresult rv = CreateServiceWorkerForWindow ( window ,
2014-12-19 13:00:29 +03:00
registration - > mActiveWorker - > GetScriptSpec ( ) ,
2014-07-24 01:05:08 +04:00
registration - > mScope ,
getter_AddRefs ( serviceWorker ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
serviceWorker . forget ( aServiceWorker ) ;
return NS_OK ;
}
NS_IMETHODIMP
ServiceWorkerManager : : GetInstalling ( nsIDOMWindow * aWindow ,
2014-08-25 09:35:03 +04:00
const nsAString & aScope ,
2014-07-24 01:05:08 +04:00
nsISupports * * aServiceWorker )
{
2014-08-25 09:35:03 +04:00
return GetServiceWorkerForScope ( aWindow , aScope ,
WhichServiceWorker : : INSTALLING_WORKER ,
aServiceWorker ) ;
2014-07-24 01:05:08 +04:00
}
NS_IMETHODIMP
ServiceWorkerManager : : GetWaiting ( nsIDOMWindow * aWindow ,
2014-08-25 09:35:03 +04:00
const nsAString & aScope ,
2014-07-24 01:05:08 +04:00
nsISupports * * aServiceWorker )
{
2014-08-25 09:35:03 +04:00
return GetServiceWorkerForScope ( aWindow , aScope ,
WhichServiceWorker : : WAITING_WORKER ,
aServiceWorker ) ;
2014-07-24 01:05:08 +04:00
}
NS_IMETHODIMP
2014-08-25 09:35:03 +04:00
ServiceWorkerManager : : GetActive ( nsIDOMWindow * aWindow ,
const nsAString & aScope ,
nsISupports * * aServiceWorker )
2014-07-24 01:05:08 +04:00
{
2014-08-25 09:35:03 +04:00
return GetServiceWorkerForScope ( aWindow , aScope ,
WhichServiceWorker : : ACTIVE_WORKER ,
aServiceWorker ) ;
2014-07-24 01:05:08 +04:00
}
2014-07-03 04:48:50 +04:00
NS_IMETHODIMP
ServiceWorkerManager : : CreateServiceWorker ( const nsACString & aScriptSpec ,
const nsACString & aScope ,
ServiceWorker * * aServiceWorker )
{
AssertIsOnMainThread ( ) ;
WorkerPrivate : : LoadInfo info ;
nsresult rv = NS_NewURI ( getter_AddRefs ( info . mBaseURI ) , aScriptSpec , nullptr , nullptr ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
info . mResolvedScriptURI = info . mBaseURI ;
rv = info . mBaseURI - > GetHost ( info . mDomain ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
// FIXME(nsm): Create correct principal based on app-ness.
// Would it make sense to store the nsIPrincipal of the first register() in
2014-08-19 17:56:00 +04:00
// the ServiceWorkerRegistrationInfo and use that?
2014-07-03 04:48:50 +04:00
nsIScriptSecurityManager * ssm = nsContentUtils : : GetSecurityManager ( ) ;
rv = ssm - > GetNoAppCodebasePrincipal ( info . mBaseURI , getter_AddRefs ( info . mPrincipal ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2014-12-12 19:06:00 +03:00
return rv ;
}
// NOTE: this defaults the SW load context to:
// - private browsing = false
// - content = true
// - use remote tabs = false
// Alternatively we could persist the original load group values and use
// them here.
rv = NS_NewLoadGroup ( getter_AddRefs ( info . mLoadGroup ) , info . mPrincipal ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2014-07-03 04:48:50 +04:00
return rv ;
}
nsRefPtr < ServiceWorker > serviceWorker ;
RuntimeService * rs = RuntimeService : : GetService ( ) ;
if ( ! rs ) {
return NS_ERROR_FAILURE ;
}
2014-12-19 13:00:29 +03:00
AutoJSAPI jsapi ;
jsapi . Init ( ) ;
rv = rs - > CreateServiceWorkerFromLoadInfo ( jsapi . cx ( ) , & info ,
NS_ConvertUTF8toUTF16 ( aScriptSpec ) ,
aScope ,
2014-07-03 04:48:50 +04:00
getter_AddRefs ( serviceWorker ) ) ;
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return rv ;
}
serviceWorker . forget ( aServiceWorker ) ;
return NS_OK ;
}
2014-07-24 01:05:08 +04:00
void
2014-08-19 17:56:00 +04:00
ServiceWorkerManager : : InvalidateServiceWorkerRegistrationWorker ( ServiceWorkerRegistrationInfo * aRegistration ,
WhichServiceWorker aWhichOnes )
2014-07-24 01:05:08 +04:00
{
AssertIsOnMainThread ( ) ;
nsRefPtr < ServiceWorkerDomainInfo > domainInfo =
GetDomainInfo ( aRegistration - > mScriptSpec ) ;
if ( domainInfo ) {
2014-08-19 17:56:00 +04:00
nsTObserverArray < ServiceWorkerRegistration * > : : ForwardIterator it ( domainInfo - > mServiceWorkerRegistrations ) ;
2014-07-24 01:05:08 +04:00
while ( it . HasMore ( ) ) {
2014-08-19 17:56:00 +04:00
nsRefPtr < ServiceWorkerRegistration > target = it . GetNext ( ) ;
2014-10-27 21:52:57 +03:00
nsAutoString regScope ;
target - > GetScope ( regScope ) ;
MOZ_ASSERT ( ! regScope . IsEmpty ( ) ) ;
2014-07-24 01:05:08 +04:00
2014-10-27 21:52:57 +03:00
NS_ConvertUTF16toUTF8 utf8Scope ( regScope ) ;
2014-07-24 01:05:08 +04:00
2014-10-27 21:52:57 +03:00
if ( utf8Scope . Equals ( aRegistration - > mScope ) ) {
target - > InvalidateWorkerReference ( aWhichOnes ) ;
2014-07-24 01:05:08 +04:00
}
}
}
}
2014-10-06 19:45:14 +04:00
NS_IMETHODIMP
ServiceWorkerManager : : Update ( const nsAString & aScope )
{
NS_ConvertUTF16toUTF8 scope ( aScope ) ;
nsRefPtr < ServiceWorkerManager : : ServiceWorkerDomainInfo > domainInfo =
GetDomainInfo ( scope ) ;
if ( NS_WARN_IF ( ! domainInfo ) ) {
return NS_OK ;
}
nsRefPtr < ServiceWorkerRegistrationInfo > registration ;
domainInfo - > mServiceWorkerRegistrationInfos . Get ( scope ,
getter_AddRefs ( registration ) ) ;
if ( NS_WARN_IF ( ! registration ) ) {
return NS_OK ;
}
2014-12-19 13:00:29 +03:00
// FIXME(nsm): Bug 1089889 Refactor this into SoftUpdate.
2014-10-06 19:45:14 +04:00
if ( registration - > mPendingUninstall ) {
return NS_OK ;
}
if ( registration - > mInstallingWorker ) {
return NS_OK ;
}
2014-12-19 13:00:29 +03:00
ServiceWorkerJobQueue * queue = domainInfo - > GetOrCreateJobQueue ( scope ) ;
MOZ_ASSERT ( queue ) ;
nsRefPtr < ServiceWorkerUpdateFinishCallback > cb =
new ServiceWorkerUpdateFinishCallback ( ) ;
nsRefPtr < ServiceWorkerRegisterJob > job
= new ServiceWorkerRegisterJob ( queue , registration , cb ) ;
queue - > Append ( job ) ;
2014-10-06 19:45:14 +04:00
return NS_OK ;
}
2014-10-27 14:03:00 +03:00
namespace {
class MOZ_STACK_CLASS FilterRegistrationData
{
public :
FilterRegistrationData ( nsTArray < uint64_t > * aDocuments ,
ServiceWorkerRegistrationInfo * aRegistration )
: mDocuments ( aDocuments ) ,
mRegistration ( aRegistration )
{
}
nsTArray < uint64_t > * mDocuments ;
nsRefPtr < ServiceWorkerRegistrationInfo > mRegistration ;
} ;
static PLDHashOperator
EnumControlledDocuments ( nsISupports * aKey ,
ServiceWorkerRegistrationInfo * aRegistration ,
void * aData )
{
FilterRegistrationData * data = static_cast < FilterRegistrationData * > ( aData ) ;
if ( data - > mRegistration ! = aRegistration ) {
return PL_DHASH_NEXT ;
}
nsCOMPtr < nsIDocument > document = do_QueryInterface ( aKey ) ;
if ( ! document | | ! document - > GetInnerWindow ( ) ) {
return PL_DHASH_NEXT ;
}
data - > mDocuments - > AppendElement ( document - > GetInnerWindow ( ) - > WindowID ( ) ) ;
return PL_DHASH_NEXT ;
}
} // anonymous namespace
void
ServiceWorkerManager : : GetServicedClients ( const nsCString & aScope ,
nsTArray < uint64_t > * aControlledDocuments )
{
nsRefPtr < ServiceWorkerDomainInfo > domainInfo = GetDomainInfo ( aScope ) ;
nsRefPtr < ServiceWorkerRegistrationInfo > registration =
domainInfo - > GetRegistration ( aScope ) ;
2014-11-04 15:04:00 +03:00
if ( ! registration ) {
// The registration was removed, leave the array empty.
return ;
}
2014-10-27 14:03:00 +03:00
FilterRegistrationData data ( aControlledDocuments , registration ) ;
domainInfo - > mControlledDocuments . EnumerateRead ( EnumControlledDocuments ,
& data ) ;
}
2014-12-19 13:00:29 +03:00
void
ServiceWorkerManager : : FireControllerChange ( ServiceWorkerRegistrationInfo * aRegistration )
{
// FIXME(nsm): Fill this out.
}
2013-11-20 03:15:02 +04:00
END_WORKERS_NAMESPACE