mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 23:06:52 +00:00
29e855d998
- Bug 1176782 part 2 - [css-align] Implement the 'justify-self' property in the style system. r=SimonSapin (273ee9a0a1) - Bug 1194480: Only update overflow region (& trigger DLBI) for changes to CSS 'box-shadow' or 'text-shadow', instead of triggering a reflow. r=heycam (0af1ee160b) - Bug 1137889 part 1 - Update predefined counter style name table to match the spec. r=jfkthame (ff678af4a9) - Bug 1137889 part 2 - Move around definitions in counterstyles.css to match the order in spec for clarity. r=jfkthame (c1a95688d9) - Bug 1187649 - Free constructed widget path in nsLookAndFeel on GTK. r=karlt (fe80b73514) - Bug 1165513 - Translate GTK3 widgets with snapped pixel coordinates into identity space. r=jrmuizel (563c252255) - Bug 1113206 patch 2: Disable use of Cocoa and Gtk native-theme dropdown rendering that doesn't play well with vertical writing mode. r=roc (3b8134aced) - Bug 1187203 - Implement GtkInfoBar appearance style on GTK3. r=karlt (0500e6297a) - Bug 1168527 - Replay clips into the system cairo on GTK3. r=lsalzman (9f739f58cc) - Bug 1168527 - Variable was re-declared causing a bustage on gcc 5. r=lsalzman (4e7f5453f2) - Bug 1167239 - Make GTK button activity require hover. r=karlt (34cb428ed3) - Bug 1177024 - Fix clang warnings-as-errors in GTK3 build. r=karlt (d45119470b) - Bug 1179780 - Render opaque scrollbar troughs in the root viewport on GTK3. r=karlt (8f04f119b0) - Bug 1210560 - Part 1: Add an API specifically intended for users that just Push and Pop-Mask/Pop-Paint. r=jrmuizel (e08db740f9) - Bug 991249 - Ensure that we can check for OOMs when we run out of ballast space. r=jandem (0742c71158) - Bug 1219419 - Keep DefaultTracer simple for now; r=fitzgen (bb621675d5) - Bug 1220310 - Generalize GC container trace function dispatch as GCPolicy; r=sfink (314b3aa009) - Bug 1187782 (part 10) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. (1def283d70) - Bug 1187782 (part 11) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. (e9a71fae11) - Bug 1187782 (part 12) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. (44afb0d6f6) - Bug 1187782 (part 13) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. (4e253c8d18) - Bug 1187782 (part 14) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. (cf8ecf213a) - Bug 859042 - Show onload and DOMContentLoaded markers in the timeline, r=smaug, jsantell (8ff8c43a36) - Bug 1187801 part 2 - Put clearing fullscreen state on element into an independent function. r=smaug (c8a135fbc9) - Bug 1187801 part 3 - Add iframe fullscreen flag and stop auto-rollback when this flag presents. r=smaug (f0c928090a) - Bug 1187801 part 4 - Add test for iframe fullscreen flag. r=smaug (851d97d772) - Bug 1188028 - Use channel->ascynOpen2 in dom/security/nsCSPContext.cpp (r=sicking) (54c9e0017e) - Bug 1218315 - Replace NS_LITERAL_STRING(...).get() with MOZ_UTF16(...) on dom. r=nfroyd (4439f10159) - Bug 1188028 - Queue up CSP console messages till windowID is available (r=sicking) (b060ba7ea3) - Bug 1085293 - File renames for WebIDL Iterable Implementation; r=bz (5d61d3ae34) - Bug 1085293 - WebIDL Iterable Implementation and Tests; r=bz (720efc275f) - Bug 1215559. Create separate iterator native types for one-type and two-type iterators, so we don't force the one-type case to implement GetKeyAtIndex. r=qdot (649284e6fc) - Bug 1174915 - Allow changing meta referrer policy on the fly, tests (r=sstamm) (02b8482802) - Bug 1211624. document.all should be iterable, and so should be various other things that have an anonymous indexed getter. r=qdot (6620287943) - Bug 1052139 - Reorder CGCreateInterfaceObjectsMethod a bit to correspond to the ordering of generated code. r=bz (cc16b9c3b2) - Bug 1052139 - Perform proper failure handling in interfaces' CreateInterfaceObjects method, after dom::CreateInterfaceObjects has been called and possibly created the interface's constructor and prototype. r=bz (6690e2a9de) - Bug 1052139 - Make more parts of the global object's prototype chain immutable, when we flip that switch. r=bz (6f1878822b) - Bug 1210570 - Ensure that ToPrimitive(location) is not spoofable. r=bz. (48ac711b2e) - Bug 1220900 - Remove unused JSBindingFinalized, r=peterv (7f6cbd6483) - missing bit of Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T> (48a0a7b75a) - Bug 1052139 - Make the [[Prototype]] of various (but not all) objects on the window object's [[Prototype]] chain immutable. BUT, also disable the code that actually respects immutable-prototype handling -- it'll be a one-liner to revert this when we're ready to do so. Making the rest of the chain immutable will happen in separate patches. r=bz (091e4f4ad0) - Bug 1174915 - Allow changing meta referrer policy on the fly (r=baku,sstamm) (e8b6f30f88) - Bug 1211607, part 1 - Document JSAPI functions that call object internal methods: JS_GetPrototype through JS_PreventExtensions. r=jandem. (4ebe70f5ea) - Bug 1211607, part 2 - JS_GetOwnPropertyDescriptor and friends. r=jandem. (73de8f3e51) - Bug 1211607, part 3 - JS_DefineProperty and friends. r=jandem. (29da979627) - Bug 1211607, part 4 - JS_HasProperty and friends. r=jandem. (130aa265c8) - Bug 1211607, part 5 - JS_GetProperty and friends. r=jandem. (a19f9d5d1c) - Bug 1211607, part 6 - JS_SetProperty and friends. r=jandem. (75de9a5774) - Bug 1211607, part 7 - JS_DeleteProperty and friends. r=jandem. (fe88179d48) - Bug 1211607, part 8 - JS_Enumerate. r=jandem. (332a0cf1a9) - Bug 1211607, part 9 - JS::Call, JS::Construct, and friends. r=jandem. (a68585dfdb) - Bug 663570 - MetaCSP Part 1: CSP parser changes (r=sicking) (b6c5e80c44) - Bug 1220602 - Make the documentation for nsIPrincipal.domain useful. r=bholley IGNORE IDL (afa28df415) - Bug 1218039 - Add a nice interface for both C++ and JS to access the principal kind. r=gabor (4449599c4b) - Bug 663570 - MetaCSP Part 2: Principal changes (r=bz) (84fe26e407) - Bug 1201783 - Throw range error for too long array spread before updating length. r=Waldo, a=abillings (633b55a5f8) - Bug 1194052 - Update Clone() functionality of LoadInfo (r=sicking) (f3bb041849) - Bug 663570 - MetaCSP Part 3: Upgrade insecure requests changes (r=bz) (0c8e3f49e5) - fix misspatch of 1194052 (743dd0269b) - Bug 663570 - MetaCSP Part 4: Speculative parser changes (r=bz) (c94c58b160) - Bug 663570 - MetaCSP Part 5: HTMLMetaElement changes (r=bz) (f4b8bd8af1) - Bug 1215140 P3 Flush pending console reports on http channels. r=bz (32d2767b68) - Bug 1188545 - respondWith promise should extend the service worker's lifetime. r=nsm (5a8e02a500) - Bug 1179401 - Call stopImmediatePropagation() on the Event object in respondWith(); r=jdm (0e33f8d8fb) - Bug 1188545 - ServiceWorkerRegistrationInfo::Clear() should terminated workers. r=nsm (a35c5df80a) - Bug 1188545 - Cosmetic changes regarding workerPrivate properties shared between shared workers and service workers. r=nsm (516c70e34e) - Bug 1188545 - Terminate service workers that have been idle for some time. r=nsm (d7582cb1bb) - Bug 1182113 - Test XSLT serviceworker load. r=bkelly (797ca864a6) - Bug 1188545 - Cancel network interceptions when the service worker is being terminated with unresolved respondWith promises. r=nsm (6df3a8eda6) - Bug 1221308 Fix some service worker related warnings. r=baku (dd6f62379e) - Bug 1208559 - Do a CSP Check in ServiceWorkerManager::Register (r=ckerschb) (5cc2df68ab) - Bug 1221365 - Move "Is origin potentially trustworthy?" logic outside ServiceWorkerManager.cpp. r=ckerschb,bkelly (91c6f8e2b5) - Bug 1208559 - Hook up ServicerWorkers with CSP (r=sicking,bkelly,dveditz) (6a6f92e8c7) - Bug 1185558 - Send a "Service-Worker: script" header when downloading service worker scripts; r=bkelly (22162634a4) - Bug 1207727 - Rework updating service workers according to the latest spec. r=bkelly (475c185ee4)
1069 lines
26 KiB
C++
1069 lines
26 KiB
C++
/* -*- 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 "ServiceWorkerScriptCache.h"
|
|
#include "mozilla/unused.h"
|
|
#include "mozilla/dom/CacheBinding.h"
|
|
#include "mozilla/dom/cache/CacheStorage.h"
|
|
#include "mozilla/dom/cache/Cache.h"
|
|
#include "mozilla/dom/Promise.h"
|
|
#include "mozilla/dom/PromiseWorkerProxy.h"
|
|
#include "mozilla/ipc/BackgroundUtils.h"
|
|
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
|
#include "nsICacheInfoChannel.h"
|
|
#include "nsIHttpChannelInternal.h"
|
|
#include "nsIStreamLoader.h"
|
|
#include "nsIThreadRetargetableRequest.h"
|
|
|
|
#include "nsIPrincipal.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsScriptLoader.h"
|
|
#include "Workers.h"
|
|
#include "nsStringStream.h"
|
|
|
|
using mozilla::dom::cache::Cache;
|
|
using mozilla::dom::cache::CacheStorage;
|
|
|
|
BEGIN_WORKERS_NAMESPACE
|
|
|
|
namespace serviceWorkerScriptCache {
|
|
|
|
namespace {
|
|
|
|
// XXX A sandbox nsIGlobalObject does not preserve its reflector, so |aSandbox|
|
|
// must be kept alive as long as the CacheStorage if you want to ensure that
|
|
// the CacheStorage will continue to work. Failures will manifest as errors
|
|
// like "JavaScript error: , line 0: TypeError: The expression cannot be
|
|
// converted to return the specified type."
|
|
already_AddRefed<CacheStorage>
|
|
CreateCacheStorage(JSContext* aCx, nsIPrincipal* aPrincipal, ErrorResult& aRv,
|
|
JS::MutableHandle<JSObject*> aSandbox)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
|
MOZ_ASSERT(xpc, "This should never be null!");
|
|
aRv = xpc->CreateSandbox(aCx, aPrincipal, aSandbox.address());
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsIGlobalObject> sandboxGlobalObject = xpc::NativeGlobal(aSandbox);
|
|
if (!sandboxGlobalObject) {
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return nullptr;
|
|
}
|
|
|
|
// We assume private browsing is not enabled here. The ScriptLoader
|
|
// explicitly fails for private browsing so there should never be
|
|
// a service worker running in private browsing mode. Therefore if
|
|
// we are purging scripts or running a comparison algorithm we cannot
|
|
// be in private browing.
|
|
//
|
|
// Also, bypass the CacheStorage trusted origin checks. The ServiceWorker
|
|
// has validated the origin prior to this point. All the information
|
|
// to revalidate is not available now.
|
|
return CacheStorage::CreateOnMainThread(cache::CHROME_ONLY_NAMESPACE,
|
|
sandboxGlobalObject, aPrincipal,
|
|
false /* private browsing */,
|
|
true /* force trusted origin */,
|
|
aRv);
|
|
}
|
|
|
|
class CompareManager;
|
|
|
|
// This class downloads a URL from the network and then it calls
|
|
// NetworkFinished() in the CompareManager.
|
|
class CompareNetwork final : public nsIStreamLoaderObserver,
|
|
public nsIRequestObserver
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLOADEROBSERVER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
|
|
explicit CompareNetwork(CompareManager* aManager)
|
|
: mManager(aManager)
|
|
{
|
|
MOZ_ASSERT(aManager);
|
|
AssertIsOnMainThread();
|
|
}
|
|
|
|
nsresult
|
|
Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup);
|
|
|
|
void
|
|
Abort()
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
MOZ_ASSERT(mChannel);
|
|
mChannel->Cancel(NS_BINDING_ABORTED);
|
|
mChannel = nullptr;
|
|
}
|
|
|
|
const nsString& Buffer() const
|
|
{
|
|
AssertIsOnMainThread();
|
|
return mBuffer;
|
|
}
|
|
|
|
private:
|
|
~CompareNetwork()
|
|
{
|
|
AssertIsOnMainThread();
|
|
}
|
|
|
|
RefPtr<CompareManager> mManager;
|
|
nsCOMPtr<nsIChannel> mChannel;
|
|
nsString mBuffer;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS(CompareNetwork, nsIStreamLoaderObserver,
|
|
nsIRequestObserver)
|
|
|
|
// This class gets a cached Response from the CacheStorage and then it calls
|
|
// CacheFinished() in the CompareManager.
|
|
class CompareCache final : public PromiseNativeHandler
|
|
, public nsIStreamLoaderObserver
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLOADEROBSERVER
|
|
|
|
explicit CompareCache(CompareManager* aManager)
|
|
: mManager(aManager)
|
|
, mState(WaitingForCache)
|
|
, mAborted(false)
|
|
{
|
|
MOZ_ASSERT(aManager);
|
|
AssertIsOnMainThread();
|
|
}
|
|
|
|
nsresult
|
|
Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL,
|
|
const nsAString& aCacheName);
|
|
|
|
void
|
|
Abort()
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
MOZ_ASSERT(!mAborted);
|
|
mAborted = true;
|
|
|
|
if (mPump) {
|
|
mPump->Cancel(NS_BINDING_ABORTED);
|
|
mPump = nullptr;
|
|
}
|
|
}
|
|
|
|
// This class manages 2 promises: 1 is to retrieve cache object, and 2 is for
|
|
// the value from the cache. For this reason we have mState to know what
|
|
// reject/resolve callback we are handling.
|
|
|
|
virtual void
|
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
if (mAborted) {
|
|
return;
|
|
}
|
|
|
|
if (mState == WaitingForCache) {
|
|
ManageCacheResult(aCx, aValue);
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(mState == WaitingForValue);
|
|
ManageValueResult(aCx, aValue);
|
|
}
|
|
|
|
virtual void
|
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
|
|
|
const nsString& Buffer() const
|
|
{
|
|
AssertIsOnMainThread();
|
|
return mBuffer;
|
|
}
|
|
|
|
const nsString& URL() const
|
|
{
|
|
AssertIsOnMainThread();
|
|
return mURL;
|
|
}
|
|
|
|
private:
|
|
~CompareCache()
|
|
{
|
|
AssertIsOnMainThread();
|
|
}
|
|
|
|
void
|
|
ManageCacheResult(JSContext* aCx, JS::Handle<JS::Value> aValue);
|
|
|
|
void
|
|
ManageValueResult(JSContext* aCx, JS::Handle<JS::Value> aValue);
|
|
|
|
RefPtr<CompareManager> mManager;
|
|
nsCOMPtr<nsIInputStreamPump> mPump;
|
|
|
|
nsString mURL;
|
|
nsString mBuffer;
|
|
|
|
enum {
|
|
WaitingForCache,
|
|
WaitingForValue
|
|
} mState;
|
|
|
|
bool mAborted;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS(CompareCache, nsIStreamLoaderObserver)
|
|
|
|
class CompareManager final : public PromiseNativeHandler
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
|
|
explicit CompareManager(ServiceWorkerRegistrationInfo* aRegistration,
|
|
CompareCallback* aCallback)
|
|
: mRegistration(aRegistration)
|
|
, mCallback(aCallback)
|
|
, mState(WaitingForOpen)
|
|
, mNetworkFinished(false)
|
|
, mCacheFinished(false)
|
|
, mInCache(false)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aRegistration);
|
|
}
|
|
|
|
nsresult
|
|
Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL,
|
|
const nsAString& aCacheName, nsILoadGroup* aLoadGroup)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
mURL = aURL;
|
|
|
|
// Always create a CacheStorage since we want to write the network entry to
|
|
// the cache even if there isn't an existing one.
|
|
AutoJSAPI jsapi;
|
|
jsapi.Init();
|
|
ErrorResult result;
|
|
mSandbox.init(jsapi.cx());
|
|
mCacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, result, &mSandbox);
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
MOZ_ASSERT(!result.IsErrorWithMessage());
|
|
return result.StealNSResult();
|
|
}
|
|
|
|
mCN = new CompareNetwork(this);
|
|
nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
if (!aCacheName.IsEmpty()) {
|
|
mCC = new CompareCache(this);
|
|
rv = mCC->Initialize(aPrincipal, aURL, aCacheName);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mCN->Abort();
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
const nsAString&
|
|
URL() const
|
|
{
|
|
AssertIsOnMainThread();
|
|
return mURL;
|
|
}
|
|
|
|
void
|
|
SetMaxScope(const nsACString& aMaxScope)
|
|
{
|
|
MOZ_ASSERT(!mNetworkFinished);
|
|
mMaxScope = aMaxScope;
|
|
}
|
|
|
|
already_AddRefed<ServiceWorkerRegistrationInfo>
|
|
GetRegistration()
|
|
{
|
|
RefPtr<ServiceWorkerRegistrationInfo> copy = mRegistration.get();
|
|
return copy.forget();
|
|
}
|
|
|
|
void
|
|
NetworkFinished(nsresult aStatus)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
mNetworkFinished = true;
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
if (mCC) {
|
|
mCC->Abort();
|
|
}
|
|
|
|
ComparisonFinished(aStatus, false);
|
|
return;
|
|
}
|
|
|
|
MaybeCompare();
|
|
}
|
|
|
|
void
|
|
CacheFinished(nsresult aStatus, bool aInCache)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
mCacheFinished = true;
|
|
mInCache = aInCache;
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
if (mCN) {
|
|
mCN->Abort();
|
|
}
|
|
|
|
ComparisonFinished(aStatus, false);
|
|
return;
|
|
}
|
|
|
|
MaybeCompare();
|
|
}
|
|
|
|
void
|
|
MaybeCompare()
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
if (!mNetworkFinished || (mCC && !mCacheFinished)) {
|
|
return;
|
|
}
|
|
|
|
if (!mCC || !mInCache) {
|
|
ComparisonFinished(NS_OK, false);
|
|
return;
|
|
}
|
|
|
|
ComparisonFinished(NS_OK, mCC->Buffer().Equals(mCN->Buffer()));
|
|
}
|
|
|
|
// This class manages 2 promises: 1 is to retrieve Cache object, and 2 is to
|
|
// Put the value in the cache. For this reason we have mState to know what
|
|
// callback we are handling.
|
|
void
|
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mCallback);
|
|
|
|
if (mState == WaitingForOpen) {
|
|
if (NS_WARN_IF(!aValue.isObject())) {
|
|
Fail(NS_ERROR_FAILURE);
|
|
return;
|
|
}
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
|
if (NS_WARN_IF(!obj)) {
|
|
Fail(NS_ERROR_FAILURE);
|
|
return;
|
|
}
|
|
|
|
Cache* cache = nullptr;
|
|
nsresult rv = UNWRAP_OBJECT(Cache, obj, cache);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
Fail(rv);
|
|
return;
|
|
}
|
|
|
|
// Just to be safe.
|
|
RefPtr<Cache> kungfuDeathGrip = cache;
|
|
WriteToCache(cache);
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(mState == WaitingForPut);
|
|
mCallback->ComparisonResult(NS_OK, false /* aIsEqual */,
|
|
mNewCacheName, mMaxScope);
|
|
Cleanup();
|
|
}
|
|
|
|
void
|
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
{
|
|
AssertIsOnMainThread();
|
|
if (mState == WaitingForOpen) {
|
|
NS_WARNING("Could not open cache.");
|
|
} else {
|
|
NS_WARNING("Could not write to cache.");
|
|
}
|
|
Fail(NS_ERROR_FAILURE);
|
|
}
|
|
|
|
CacheStorage*
|
|
CacheStorage_()
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mCacheStorage);
|
|
return mCacheStorage;
|
|
}
|
|
|
|
void
|
|
InitChannelInfo(nsIChannel* aChannel)
|
|
{
|
|
mChannelInfo.InitFromChannel(aChannel);
|
|
}
|
|
|
|
nsresult
|
|
SetPrincipalInfo(nsIChannel* aChannel)
|
|
{
|
|
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
|
NS_ASSERTION(ssm, "Should never be null!");
|
|
|
|
nsCOMPtr<nsIPrincipal> channelPrincipal;
|
|
nsresult rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(channelPrincipal));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
UniquePtr<mozilla::ipc::PrincipalInfo> principalInfo(new mozilla::ipc::PrincipalInfo());
|
|
rv = PrincipalToPrincipalInfo(channelPrincipal, principalInfo.get());
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
mPrincipalInfo = Move(principalInfo);
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
~CompareManager()
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(!mCC);
|
|
MOZ_ASSERT(!mCN);
|
|
}
|
|
|
|
void
|
|
Fail(nsresult aStatus)
|
|
{
|
|
AssertIsOnMainThread();
|
|
mCallback->ComparisonResult(aStatus, false /* aIsEqual */,
|
|
EmptyString(), EmptyCString());
|
|
Cleanup();
|
|
}
|
|
|
|
void
|
|
Cleanup()
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mCallback);
|
|
mCallback = nullptr;
|
|
mCN = nullptr;
|
|
mCC = nullptr;
|
|
}
|
|
|
|
void
|
|
ComparisonFinished(nsresult aStatus, bool aIsEqual)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mCallback);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
Fail(aStatus);
|
|
return;
|
|
}
|
|
|
|
if (aIsEqual) {
|
|
mCallback->ComparisonResult(aStatus, aIsEqual, EmptyString(), mMaxScope);
|
|
Cleanup();
|
|
return;
|
|
}
|
|
|
|
// Write to Cache so ScriptLoader reads succeed.
|
|
WriteNetworkBufferToNewCache();
|
|
}
|
|
|
|
void
|
|
WriteNetworkBufferToNewCache()
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(mCN);
|
|
MOZ_ASSERT(mCacheStorage);
|
|
MOZ_ASSERT(mNewCacheName.IsEmpty());
|
|
|
|
ErrorResult result;
|
|
result = serviceWorkerScriptCache::GenerateCacheName(mNewCacheName);
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
MOZ_ASSERT(!result.IsErrorWithMessage());
|
|
Fail(result.StealNSResult());
|
|
return;
|
|
}
|
|
|
|
RefPtr<Promise> cacheOpenPromise = mCacheStorage->Open(mNewCacheName, result);
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
MOZ_ASSERT(!result.IsErrorWithMessage());
|
|
Fail(result.StealNSResult());
|
|
return;
|
|
}
|
|
|
|
cacheOpenPromise->AppendNativeHandler(this);
|
|
}
|
|
|
|
void
|
|
WriteToCache(Cache* aCache)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aCache);
|
|
MOZ_ASSERT(mState == WaitingForOpen);
|
|
|
|
ErrorResult result;
|
|
nsCOMPtr<nsIInputStream> body;
|
|
result = NS_NewStringInputStream(getter_AddRefs(body), mCN->Buffer());
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
MOZ_ASSERT(!result.IsErrorWithMessage());
|
|
Fail(result.StealNSResult());
|
|
return;
|
|
}
|
|
|
|
RefPtr<InternalResponse> ir =
|
|
new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
|
|
ir->SetBody(body);
|
|
|
|
ir->InitChannelInfo(mChannelInfo);
|
|
if (mPrincipalInfo) {
|
|
ir->SetPrincipalInfo(Move(mPrincipalInfo));
|
|
}
|
|
|
|
RefPtr<Response> response = new Response(aCache->GetGlobalObject(), ir);
|
|
|
|
RequestOrUSVString request;
|
|
request.SetAsUSVString().Rebind(URL().Data(), URL().Length());
|
|
|
|
// For now we have to wait until the Put Promise is fulfilled before we can
|
|
// continue since Cache does not yet support starting a read that is being
|
|
// written to.
|
|
RefPtr<Promise> cachePromise = aCache->Put(request, *response, result);
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
MOZ_ASSERT(!result.IsErrorWithMessage());
|
|
Fail(result.StealNSResult());
|
|
return;
|
|
}
|
|
|
|
mState = WaitingForPut;
|
|
cachePromise->AppendNativeHandler(this);
|
|
}
|
|
|
|
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
|
|
RefPtr<CompareCallback> mCallback;
|
|
JS::PersistentRooted<JSObject*> mSandbox;
|
|
RefPtr<CacheStorage> mCacheStorage;
|
|
|
|
RefPtr<CompareNetwork> mCN;
|
|
RefPtr<CompareCache> mCC;
|
|
|
|
nsString mURL;
|
|
// Only used if the network script has changed and needs to be cached.
|
|
nsString mNewCacheName;
|
|
|
|
ChannelInfo mChannelInfo;
|
|
|
|
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
|
|
|
nsCString mMaxScope;
|
|
|
|
enum {
|
|
WaitingForOpen,
|
|
WaitingForPut
|
|
} mState;
|
|
|
|
bool mNetworkFinished;
|
|
bool mCacheFinished;
|
|
bool mInCache;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS0(CompareManager)
|
|
|
|
nsresult
|
|
CompareNetwork::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup)
|
|
{
|
|
MOZ_ASSERT(aPrincipal);
|
|
AssertIsOnMainThread();
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), aPrincipal);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsLoadFlags flags = nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
|
|
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
mManager->GetRegistration();
|
|
if (registration->IsLastUpdateCheckTimeOverOneDay()) {
|
|
flags |= nsIRequest::LOAD_BYPASS_CACHE;
|
|
}
|
|
|
|
// Note that because there is no "serviceworker" RequestContext type, we can
|
|
// use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
|
|
// worker.
|
|
rv = NS_NewChannel(getter_AddRefs(mChannel),
|
|
uri, aPrincipal,
|
|
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
|
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
|
|
loadGroup,
|
|
nullptr, // aCallbacks
|
|
flags);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
|
|
if (httpChannel) {
|
|
// Spec says no redirects allowed for SW scripts.
|
|
httpChannel->SetRedirectionLimit(0);
|
|
|
|
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Service-Worker"),
|
|
NS_LITERAL_CSTRING("script"),
|
|
/* merge */ false);
|
|
}
|
|
|
|
nsCOMPtr<nsIStreamLoader> loader;
|
|
rv = NS_NewStreamLoader(getter_AddRefs(loader), this, this);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
rv = mChannel->AsyncOpen2(loader);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CompareNetwork::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
// If no channel, Abort() has been called.
|
|
if (!mChannel) {
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
|
MOZ_ASSERT(channel == mChannel);
|
|
#endif
|
|
|
|
mManager->InitChannelInfo(mChannel);
|
|
nsresult rv = mManager->SetPrincipalInfo(mChannel);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CompareNetwork::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
|
|
nsresult aStatusCode)
|
|
{
|
|
// Nothing to do here!
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext,
|
|
nsresult aStatus, uint32_t aLen,
|
|
const uint8_t* aString)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
// If no channel, Abort() has been called.
|
|
if (!mChannel) {
|
|
return NS_OK;
|
|
}
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
if (aStatus == NS_ERROR_REDIRECT_LOOP) {
|
|
mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
|
|
} else {
|
|
mManager->NetworkFinished(aStatus);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIRequest> request;
|
|
nsresult rv = aLoader->GetRequest(getter_AddRefs(request));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
|
if (httpChannel) {
|
|
bool requestSucceeded;
|
|
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (NS_WARN_IF(!requestSucceeded)) {
|
|
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString maxScope;
|
|
// Note: we explicitly don't check for the return value here, because the
|
|
// absence of the header is not an error condition.
|
|
unused << httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Service-Worker-Allowed"),
|
|
maxScope);
|
|
|
|
mManager->SetMaxScope(maxScope);
|
|
|
|
bool isFromCache = false;
|
|
nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(httpChannel));
|
|
if (cacheChannel) {
|
|
cacheChannel->IsFromCache(&isFromCache);
|
|
}
|
|
|
|
// [9.2 Update]4.13, If response's cache state is not "local",
|
|
// set registration's last update check time to the current time
|
|
if (!isFromCache) {
|
|
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
|
mManager->GetRegistration();
|
|
registration->RefreshLastUpdateCheckTime();
|
|
}
|
|
|
|
nsAutoCString mimeType;
|
|
rv = httpChannel->GetContentType(mimeType);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
|
|
return rv;
|
|
}
|
|
|
|
if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
|
|
!mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
|
|
!mimeType.LowerCaseEqualsLiteral("application/javascript")) {
|
|
mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
// The only supported request schemes are http, https, and app.
|
|
// Above, we check to ensure that the request is http or https
|
|
// based on the channel qi. Here we test the scheme to ensure
|
|
// that it is app. Otherwise, bail.
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
|
if (NS_WARN_IF(!channel)) {
|
|
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
nsCOMPtr<nsIURI> uri;
|
|
rv = channel->GetURI(getter_AddRefs(uri));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString scheme;
|
|
rv = uri->GetScheme(scheme);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (NS_WARN_IF(!scheme.LowerCaseEqualsLiteral("app"))) {
|
|
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
char16_t* buffer = nullptr;
|
|
size_t len = 0;
|
|
|
|
rv = nsScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
|
|
NS_LITERAL_STRING("UTF-8"), nullptr,
|
|
buffer, len);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->NetworkFinished(rv);
|
|
return rv;
|
|
}
|
|
|
|
mBuffer.Adopt(buffer, len);
|
|
|
|
mManager->NetworkFinished(NS_OK);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
CompareCache::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL,
|
|
const nsAString& aCacheName)
|
|
{
|
|
MOZ_ASSERT(aPrincipal);
|
|
AssertIsOnMainThread();
|
|
|
|
mURL = aURL;
|
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<Promise> promise = mManager->CacheStorage_()->Open(aCacheName, rv);
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
MOZ_ASSERT(!rv.IsErrorWithMessage());
|
|
return rv.StealNSResult();
|
|
}
|
|
|
|
promise->AppendNativeHandler(this);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CompareCache::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext,
|
|
nsresult aStatus, uint32_t aLen,
|
|
const uint8_t* aString)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
if (mAborted) {
|
|
return aStatus;
|
|
}
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
mManager->CacheFinished(aStatus, false);
|
|
return aStatus;
|
|
}
|
|
|
|
char16_t* buffer = nullptr;
|
|
size_t len = 0;
|
|
|
|
nsresult rv = nsScriptLoader::ConvertToUTF16(nullptr, aString, aLen,
|
|
NS_LITERAL_STRING("UTF-8"),
|
|
nullptr, buffer, len);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->CacheFinished(rv, false);
|
|
return rv;
|
|
}
|
|
|
|
mBuffer.Adopt(buffer, len);
|
|
|
|
mManager->CacheFinished(NS_OK, true);
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
CompareCache::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
if (mAborted) {
|
|
return;
|
|
}
|
|
|
|
mManager->CacheFinished(NS_ERROR_FAILURE, false);
|
|
}
|
|
|
|
void
|
|
CompareCache::ManageCacheResult(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
if (NS_WARN_IF(!aValue.isObject())) {
|
|
mManager->CacheFinished(NS_ERROR_FAILURE, false);
|
|
return;
|
|
}
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
|
if (NS_WARN_IF(!obj)) {
|
|
mManager->CacheFinished(NS_ERROR_FAILURE, false);
|
|
return;
|
|
}
|
|
|
|
Cache* cache = nullptr;
|
|
nsresult rv = UNWRAP_OBJECT(Cache, obj, cache);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
|
|
RequestOrUSVString request;
|
|
request.SetAsUSVString().Rebind(mURL.Data(), mURL.Length());
|
|
ErrorResult error;
|
|
CacheQueryOptions params;
|
|
RefPtr<Promise> promise = cache->Match(request, params, error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
mManager->CacheFinished(error.StealNSResult(), false);
|
|
return;
|
|
}
|
|
|
|
promise->AppendNativeHandler(this);
|
|
mState = WaitingForValue;
|
|
}
|
|
|
|
void
|
|
CompareCache::ManageValueResult(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
|
{
|
|
AssertIsOnMainThread();
|
|
|
|
// The cache returns undefined if the object is not stored.
|
|
if (aValue.isUndefined()) {
|
|
mManager->CacheFinished(NS_OK, false);
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(aValue.isObject());
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
|
if (NS_WARN_IF(!obj)) {
|
|
mManager->CacheFinished(NS_ERROR_FAILURE, false);
|
|
return;
|
|
}
|
|
|
|
Response* response = nullptr;
|
|
nsresult rv = UNWRAP_OBJECT(Response, obj, response);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(response->Ok());
|
|
|
|
nsCOMPtr<nsIInputStream> inputStream;
|
|
response->GetBody(getter_AddRefs(inputStream));
|
|
MOZ_ASSERT(inputStream);
|
|
|
|
MOZ_ASSERT(!mPump);
|
|
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), inputStream);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIStreamLoader> loader;
|
|
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
|
|
rv = mPump->AsyncRead(loader, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mPump = nullptr;
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(mPump);
|
|
if (rr) {
|
|
nsCOMPtr<nsIEventTarget> sts =
|
|
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
|
rv = rr->RetargetDeliveryTo(sts);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
mPump = nullptr;
|
|
mManager->CacheFinished(rv, false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
nsresult
|
|
PurgeCache(nsIPrincipal* aPrincipal, const nsAString& aCacheName)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
if (aCacheName.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
AutoJSAPI jsapi;
|
|
jsapi.Init();
|
|
ErrorResult rv;
|
|
JS::Rooted<JSObject*> sandboxObject(jsapi.cx());
|
|
RefPtr<CacheStorage> cacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, rv, &sandboxObject);
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
return rv.StealNSResult();
|
|
}
|
|
|
|
// We use the ServiceWorker scope as key for the cacheStorage.
|
|
RefPtr<Promise> promise =
|
|
cacheStorage->Delete(aCacheName, rv);
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
return rv.StealNSResult();
|
|
}
|
|
|
|
// We don't actually care about the result of the delete operation.
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
GenerateCacheName(nsAString& aName)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
|
|
do_GetService("@mozilla.org/uuid-generator;1", &rv);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsID id;
|
|
rv = uuidGenerator->GenerateUUIDInPlace(&id);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
char chars[NSID_LENGTH];
|
|
id.ToProvidedString(chars);
|
|
aName.AssignASCII(chars, NSID_LENGTH);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
Compare(ServiceWorkerRegistrationInfo* aRegistration,
|
|
nsIPrincipal* aPrincipal, const nsAString& aCacheName,
|
|
const nsAString& aURL, CompareCallback* aCallback,
|
|
nsILoadGroup* aLoadGroup)
|
|
{
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(aRegistration);
|
|
MOZ_ASSERT(aPrincipal);
|
|
MOZ_ASSERT(!aURL.IsEmpty());
|
|
MOZ_ASSERT(aCallback);
|
|
|
|
RefPtr<CompareManager> cm = new CompareManager(aRegistration, aCallback);
|
|
|
|
nsresult rv = cm->Initialize(aPrincipal, aURL, aCacheName, aLoadGroup);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace serviceWorkerScriptCache
|
|
|
|
END_WORKERS_NAMESPACE
|