Bug 1694662 - Remove OfflineCache update logic r=necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D106443
This commit is contained in:
Valentin Gosu 2021-04-30 07:20:19 +00:00
parent 8608b6c849
commit 5aa53ddea9
23 changed files with 7 additions and 5071 deletions

View file

@ -84,15 +84,6 @@ Classes = [
'headers': ['/uriloader/exthandler/nsExternalProtocolHandler.h'],
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
},
{
'name': 'OfflineCacheUpdate',
'cid': '{ec06f3fc-70db-4ecd-94e0-a6e91ca44d8a}',
'contract_ids': ['@mozilla.org/offlinecacheupdate-service;1'],
'singleton': True,
'type': 'nsOfflineCacheUpdateService',
'headers': ['/uriloader/prefetch/nsOfflineCacheUpdate.h'],
'constructor': 'nsOfflineCacheUpdateService::GetInstance',
},
{
'cid': '{95790842-75a0-430d-98bf-f5ce3788ea6d}',
'contract_ids': ['@mozilla.org/ospermissionrequest;1'],

View file

@ -297,7 +297,6 @@
#include "nsIObjectLoadingContent.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsIParser.h"
#include "nsIParserUtils.h"
#include "nsIPermissionManager.h"
@ -1844,29 +1843,11 @@ void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
}
/* static */
bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) {
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
components::OfflineCacheUpdate::Service();
if (!updateService) {
return false;
}
bool allowed;
nsresult rv = updateService->OfflineAppAllowedForURI(aURI, &allowed);
return NS_SUCCEEDED(rv) && allowed;
}
bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
/* static */
bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
components::OfflineCacheUpdate::Service();
if (!updateService) {
return false;
}
bool allowed;
nsresult rv = updateService->OfflineAppAllowed(aPrincipal, &allowed);
return NS_SUCCEEDED(rv) && allowed;
return false;
}
// Static
bool nsContentUtils::IsErrorPage(nsIURI* aURI) {

View file

@ -162,7 +162,6 @@ using namespace mozilla::dom::ipc;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::layout;
using namespace mozilla::docshell;
using namespace mozilla::widget;
using mozilla::layers::GeckoContentController;

View file

@ -49,7 +49,6 @@
#include "mozilla/Unused.h"
#include "mozilla/WebBrowserPersistDocumentChild.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/BrowserBridgeHost.h"
@ -296,7 +295,6 @@
extern mozilla::LazyLogModule gSHIPBFCacheLog;
using namespace mozilla;
using namespace mozilla::docshell;
using namespace mozilla::dom::ipc;
using namespace mozilla::media;
using namespace mozilla::embedding;

View file

@ -83,7 +83,6 @@
#include "mozilla/Unused.h"
#include "mozilla/WebBrowserPersistDocumentParent.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/BrowserHost.h"
#include "mozilla/dom/BrowsingContext.h"
@ -1798,14 +1797,6 @@ void ContentParent::ShutDownProcess(ShutDownMethod aMethod) {
Close();
}
const ManagedContainer<POfflineCacheUpdateParent>& ocuParents =
ManagedPOfflineCacheUpdateParent();
for (auto* key : ocuParents) {
RefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent =
static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(key);
ocuParent->StopSendingMessagesToChild();
}
// A ContentParent object might not get freed until after XPCOM shutdown has
// shut down the cycle collector. But by then it's too late to release any
// CC'ed objects, so we need to null them out here, while we still can. See
@ -5027,36 +5018,6 @@ void ContentParent::NotifyUpdatedFonts(bool aFullRebuild) {
}
}
already_AddRefed<mozilla::docshell::POfflineCacheUpdateParent>
ContentParent::AllocPOfflineCacheUpdateParent(
nsIURI* aManifestURI, nsIURI* aDocumentURI,
const PrincipalInfo& aLoadingPrincipalInfo, const bool& aStickDocument,
const CookieJarSettingsArgs& aCookieJarSettingsArgs) {
RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
new mozilla::docshell::OfflineCacheUpdateParent();
return update.forget();
}
mozilla::ipc::IPCResult ContentParent::RecvPOfflineCacheUpdateConstructor(
POfflineCacheUpdateParent* aActor, nsIURI* aManifestURI,
nsIURI* aDocumentURI, const PrincipalInfo& aLoadingPrincipal,
const bool& aStickDocument,
const CookieJarSettingsArgs& aCookieJarSettingsArgs) {
MOZ_ASSERT(aActor);
RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor);
nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aLoadingPrincipal,
aStickDocument, aCookieJarSettingsArgs);
if (NS_FAILED(rv) && IsAlive()) {
// Inform the child of failure.
Unused << update->SendFinish(false, false);
}
return IPC_OK();
}
PWebrtcGlobalParent* ContentParent::AllocPWebrtcGlobalParent() {
#ifdef MOZ_WEBRTC
return WebrtcGlobalParent::Alloc();
@ -5076,17 +5037,6 @@ bool ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent* aActor) {
mozilla::ipc::IPCResult ContentParent::RecvSetOfflinePermission(
const Principal& aPrincipal) {
if (!ValidatePrincipal(aPrincipal)) {
LogAndAssertFailedPrincipalValidationInfo(aPrincipal, __func__);
}
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
components::OfflineCacheUpdate::Service();
if (!updateService) {
return IPC_FAIL_NO_REASON(this);
}
nsresult rv = updateService->AllowOfflineApp(aPrincipal);
NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
return IPC_OK();
}

View file

@ -492,17 +492,6 @@ class ContentParent final
mozilla::ipc::IPCResult RecvNotifyTabDestroying(const TabId& aTabId,
const ContentParentId& aCpId);
already_AddRefed<POfflineCacheUpdateParent> AllocPOfflineCacheUpdateParent(
nsIURI* aManifestURI, nsIURI* aDocumentURI,
const PrincipalInfo& aLoadingPrincipalInfo, const bool& aStickDocument,
const CookieJarSettingsArgs& aCookieJarSettingsArgs);
virtual mozilla::ipc::IPCResult RecvPOfflineCacheUpdateConstructor(
POfflineCacheUpdateParent* aActor, nsIURI* aManifestURI,
nsIURI* aDocumentURI, const PrincipalInfo& aLoadingPrincipal,
const bool& stickDocument,
const CookieJarSettingsArgs& aCookieJarSettingsArgs) override;
mozilla::ipc::IPCResult RecvSetOfflinePermission(
const IPC::Principal& principal);

View file

@ -29,7 +29,6 @@ include protocol PGMP;
include protocol PPrinting;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol POfflineCacheUpdate;
#ifdef MOZ_WEBSPEECH
include protocol PSpeechSynthesis;
#endif
@ -414,7 +413,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PRemoteLazyInputStream;
manages PMedia;
manages PNecko;
manages POfflineCacheUpdate;
manages PPrinting;
manages PChildToParentStream;
manages PParentToChildStream;
@ -1171,36 +1169,6 @@ parent:
async RequestAnonymousTemporaryFile(uint64_t aID);
/**
* Starts an offline application cache update.
* @param manifestURI
* URI of the manifest to fetch, the application cache group ID
* @param documentURI
* URI of the document that referred the manifest
* @param loadingPrincipal
* Principal of the document that referred the manifest
* @param stickDocument
* True if the update was initiated by a document load that referred
* a manifest.
* False if the update was initiated by applicationCache.update() call.
*
* Tells the update to carry the documentURI to a potential separate
* update of implicit (master) items.
*
* Why this argument? If the document was not found in an offline cache
* before load and refers a manifest and this manifest itself has not
* been changed since the last fetch, we will not do the application
* cache group update. But we must cache the document (identified by the
* documentURI). This argument will ensure that a previously uncached
* document will get cached and that we don't re-cache a document that
* has already been cached (stickDocument=false).
* @param tabId
* To identify which tab owns the app.
*/
async POfflineCacheUpdate(nsIURI manifestURI, nsIURI documentURI,
PrincipalInfo loadingPrincipal, bool stickDocument,
CookieJarSettingsArgs cookieJarSettings);
/**
* Sets "offline-app" permission for the principal. Called when we hit
* a web app with the manifest attribute in <html>

View file

@ -19,7 +19,6 @@
#include "nsIObserverService.h"
#include "nsIScriptGlobalObject.h"
#include "nsIWebNavigation.h"
#include "nsOfflineCacheUpdate.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/OfflineResourceListBinding.h"

View file

@ -49,7 +49,6 @@
#include "nsIMIMEHeaderParam.h"
#include "nsINode.h"
#include "nsIObjectLoadingContent.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsPersistentProperties.h"
#include "nsIPrivateBrowsingChannel.h"
#include "nsIPropertyBag2.h"
@ -2127,23 +2126,7 @@ bool NS_IsSafeMethodNav(nsIChannel* aChannel) {
return requestHead->IsSafeMethod();
}
bool NS_ShouldCheckAppCache(nsIPrincipal* aPrincipal) {
uint32_t privateBrowsingId = 0;
nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
if (NS_SUCCEEDED(rv) && (privateBrowsingId > 0)) {
return false;
}
nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
do_GetService("@mozilla.org/offlinecacheupdate-service;1");
if (!offlineService) {
return false;
}
bool allowed;
rv = offlineService->OfflineAppAllowed(aPrincipal, &allowed);
return NS_SUCCEEDED(rv) && allowed;
}
bool NS_ShouldCheckAppCache(nsIPrincipal* aPrincipal) { return false; }
void NS_WrapAuthPrompt(nsIAuthPrompt* aAuthPrompt,
nsIAuthPrompt2** aAuthPrompt2) {

View file

@ -454,7 +454,6 @@ avoid-blacklist-and-whitelist:
- tools/profiler/core/platform.cpp
- tools/tryselect/selectors/chooser/__init__.py
- tools/tryselect/task_config.py
- uriloader/prefetch/nsOfflineCacheUpdate.cpp
- widget/android/GfxInfo.cpp
- widget/GfxInfoBase.cpp
- widget/gtk/IMContextWrapper.cpp

View file

@ -1,472 +0,0 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BackgroundUtils.h"
#include "OfflineCacheUpdateChild.h"
#include "nsOfflineCacheUpdate.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/OfflineResourceListBinding.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/net/NeckoCommon.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIDocShell.h"
#include "nsPIDOMWindow.h"
#include "mozilla/dom/Document.h"
#include "mozilla/net/CookieJarSettings.h"
#include "nsIObserverService.h"
#include "nsIBrowserChild.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "mozilla/Logging.h"
#include "nsApplicationCache.h"
using namespace mozilla::ipc;
using namespace mozilla::net;
using mozilla::dom::BrowserChild;
using mozilla::dom::ContentChild;
using mozilla::dom::Document;
//
// To enable logging (see mozilla/Logging.h for full details):
//
// set MOZ_LOG=nsOfflineCacheUpdate:5
// set MOZ_LOG_FILE=offlineupdate.log
//
// this enables LogLevel::Debug level information and places all output in
// the file offlineupdate.log
//
extern mozilla::LazyLogModule gOfflineCacheUpdateLog;
#undef LOG
#define LOG(args) \
MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
#undef LOG_ENABLED
#define LOG_ENABLED() \
MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild::nsISupports
//-----------------------------------------------------------------------------
NS_INTERFACE_MAP_BEGIN(OfflineCacheUpdateChild)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIOfflineCacheUpdate)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(OfflineCacheUpdateChild)
NS_IMPL_RELEASE(OfflineCacheUpdateChild)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateChild::OfflineCacheUpdateChild(nsPIDOMWindowInner* aWindow)
: mState(STATE_UNINITIALIZED),
mIsUpgrade(false),
mSucceeded(false),
mWindow(aWindow),
mByteProgress(0) {}
OfflineCacheUpdateChild::~OfflineCacheUpdateChild() {
LOG(("OfflineCacheUpdateChild::~OfflineCacheUpdateChild [%p]", this));
}
void OfflineCacheUpdateChild::GatherObservers(
nsCOMArray<nsIOfflineCacheUpdateObserver>& aObservers) {
for (int32_t i = 0; i < mWeakObservers.Count(); i++) {
nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
do_QueryReferent(mWeakObservers[i]);
if (observer)
aObservers.AppendObject(observer);
else
mWeakObservers.RemoveObjectAt(i--);
}
for (int32_t i = 0; i < mObservers.Count(); i++) {
aObservers.AppendObject(mObservers[i]);
}
}
void OfflineCacheUpdateChild::SetDocument(Document* aDocument) {
// The design is one document for one cache update on the content process.
NS_ASSERTION(
!mDocument,
"Setting more then a single document on a child offline cache update");
LOG(("Document %p added to update child %p", aDocument, this));
// Add document only if it was not loaded from an offline cache.
// If it were loaded from an offline cache then it has already
// been associated with it and must not be again cached as
// implicit (which are the reasons we collect documents here).
if (!aDocument) return;
mCookieJarSettings = aDocument->CookieJarSettings();
nsIChannel* channel = aDocument->GetChannel();
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (!appCacheChannel) return;
bool loadedFromAppCache;
appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
if (loadedFromAppCache) return;
mDocument = aDocument;
}
nsresult OfflineCacheUpdateChild::AssociateDocument(
Document* aDocument, nsIApplicationCache* aApplicationCache) {
// Check that the document that requested this update was
// previously associated with an application cache. If not, it
// should be associated with the new one.
nsCOMPtr<nsIApplicationCache> existingCache;
nsresult rv = aDocument->GetApplicationCache(getter_AddRefs(existingCache));
NS_ENSURE_SUCCESS(rv, rv);
if (!existingCache) {
if (LOG_ENABLED()) {
nsAutoCString clientID;
if (aApplicationCache) {
aApplicationCache->GetClientID(clientID);
}
LOG(("Update %p: associating app cache %s to document %p", this,
clientID.get(), aDocument));
}
rv = aDocument->SetApplicationCache(aApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild::nsIOfflineCacheUpdate
//-----------------------------------------------------------------------------
NS_IMETHODIMP
OfflineCacheUpdateChild::Init(nsIURI* aManifestURI, nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
Document* aDocument, nsIFile* aCustomProfileDir) {
nsresult rv;
// Make sure the service has been initialized
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (!service) return NS_ERROR_FAILURE;
if (aCustomProfileDir) {
NS_ERROR("Custom Offline Cache Update not supported on child process");
return NS_ERROR_NOT_IMPLEMENTED;
}
LOG(("OfflineCacheUpdateChild::Init [%p]", this));
// Only http and https applications are supported.
if (!aManifestURI->SchemeIs("http") && !aManifestURI->SchemeIs("https")) {
return NS_ERROR_ABORT;
}
mManifestURI = aManifestURI;
rv = mManifestURI->GetAsciiHost(mUpdateDomain);
NS_ENSURE_SUCCESS(rv, rv);
mDocumentURI = aDocumentURI;
mLoadingPrincipal = aLoadingPrincipal;
mState = STATE_INITIALIZED;
if (aDocument) SetDocument(aDocument);
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::InitPartial(nsIURI* aManifestURI,
const nsACString& clientID,
nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
nsICookieJarSettings* aCookieJarSettings) {
MOZ_ASSERT_UNREACHABLE(
"Not expected to do partial offline cache updates"
" on the child process");
// For now leaving this method, we may discover we need it.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::InitForUpdateCheck(nsIURI* aManifestURI,
nsIPrincipal* aLoadingPrincipal,
nsIObserver* aObserver) {
MOZ_ASSERT_UNREACHABLE(
"Not expected to do only update checks"
" from the child process");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetUpdateDomain(nsACString& aUpdateDomain) {
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
aUpdateDomain = mUpdateDomain;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetStatus(uint16_t* aStatus) {
switch (mState) {
case STATE_CHECKING:
*aStatus = mozilla::dom::OfflineResourceList_Binding::CHECKING;
return NS_OK;
case STATE_DOWNLOADING:
*aStatus = mozilla::dom::OfflineResourceList_Binding::DOWNLOADING;
return NS_OK;
default:
*aStatus = mozilla::dom::OfflineResourceList_Binding::IDLE;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetPartial(bool* aPartial) {
*aPartial = false;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) {
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
NS_IF_ADDREF(*aLoadingPrincipal = mLoadingPrincipal);
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetManifestURI(nsIURI** aManifestURI) {
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
NS_IF_ADDREF(*aManifestURI = mManifestURI);
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetSucceeded(bool* aSucceeded) {
NS_ENSURE_TRUE(mState == STATE_FINISHED, NS_ERROR_NOT_AVAILABLE);
*aSucceeded = mSucceeded;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetIsUpgrade(bool* aIsUpgrade) {
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
*aIsUpgrade = mIsUpgrade;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::AddDynamicURI(nsIURI* aURI) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::Cancel() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP
OfflineCacheUpdateChild::AddObserver(nsIOfflineCacheUpdateObserver* aObserver,
bool aHoldWeak) {
LOG(("OfflineCacheUpdateChild::AddObserver [%p]", this));
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
if (aHoldWeak) {
nsWeakPtr weakRef = do_GetWeakReference(aObserver);
mWeakObservers.AppendObject(weakRef);
} else {
mObservers.AppendObject(aObserver);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::RemoveObserver(
nsIOfflineCacheUpdateObserver* aObserver) {
LOG(("OfflineCacheUpdateChild::RemoveObserver [%p]", this));
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
for (int32_t i = 0; i < mWeakObservers.Count(); i++) {
nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
do_QueryReferent(mWeakObservers[i]);
if (observer == aObserver) {
mWeakObservers.RemoveObjectAt(i);
return NS_OK;
}
}
for (int32_t i = 0; i < mObservers.Count(); i++) {
if (mObservers[i] == aObserver) {
mObservers.RemoveObjectAt(i);
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetByteProgress(uint64_t* _result) {
NS_ENSURE_ARG(_result);
*_result = mByteProgress;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::Schedule() {
LOG(("OfflineCacheUpdateChild::Schedule [%p]", this));
NS_ASSERTION(mWindow,
"Window must be provided to the offline cache update child");
nsCOMPtr<nsPIDOMWindowInner> window = std::move(mWindow);
nsCOMPtr<nsIDocShell> docshell = window->GetDocShell();
if (!docshell) {
NS_WARNING("doc shell tree item is null");
return NS_ERROR_FAILURE;
}
nsresult rv = NS_OK;
PrincipalInfo loadingPrincipalInfo;
rv = PrincipalToPrincipalInfo(mLoadingPrincipal, &loadingPrincipalInfo);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-added"));
observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-added", nullptr);
LOG(("Done offline-cache-update-added"));
}
// mDocument is non-null if both:
// 1. this update was initiated by a document that referred a manifest
// 2. the document has not already been loaded from the application cache
// This tells the update to cache this document even in case the manifest
// has not been changed since the last fetch.
// See also nsOfflineCacheUpdate::ScheduleImplicit.
bool stickDocument = mDocument != nullptr;
CookieJarSettingsArgs csArgs;
if (mCookieJarSettings) {
CookieJarSettings::Cast(mCookieJarSettings)->Serialize(csArgs);
}
ContentChild::GetSingleton()->SendPOfflineCacheUpdateConstructor(
this, mManifestURI, mDocumentURI, loadingPrincipalInfo, stickDocument,
csArgs);
return NS_OK;
}
mozilla::ipc::IPCResult OfflineCacheUpdateChild::RecvAssociateDocuments(
const nsCString& cacheGroupId, const nsCString& cacheClientId) {
LOG(("OfflineCacheUpdateChild::RecvAssociateDocuments [%p, cache=%s]", this,
cacheClientId.get()));
nsCOMPtr<nsIApplicationCache> cache = new nsApplicationCache();
cache->InitAsHandle(cacheGroupId, cacheClientId);
if (mDocument) {
AssociateDocument(mDocument, cache);
}
nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
GatherObservers(observers);
for (int32_t i = 0; i < observers.Count(); i++)
observers[i]->ApplicationCacheAvailable(cache);
return IPC_OK();
}
mozilla::ipc::IPCResult OfflineCacheUpdateChild::RecvNotifyStateEvent(
const uint32_t& event, const uint64_t& byteProgress) {
LOG(("OfflineCacheUpdateChild::RecvNotifyStateEvent [%p]", this));
mByteProgress = byteProgress;
// Convert the public observer state to our internal state
switch (event) {
case nsIOfflineCacheUpdateObserver::STATE_CHECKING:
mState = STATE_CHECKING;
break;
case nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING:
mState = STATE_DOWNLOADING;
break;
default:
break;
}
nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
GatherObservers(observers);
for (int32_t i = 0; i < observers.Count(); i++)
observers[i]->UpdateStateChanged(this, event);
return IPC_OK();
}
mozilla::ipc::IPCResult OfflineCacheUpdateChild::RecvFinish(
const bool& succeeded, const bool& isUpgrade) {
LOG(("OfflineCacheUpdateChild::RecvFinish [%p]", this));
RefPtr<OfflineCacheUpdateChild> kungFuDeathGrip(this);
mState = STATE_FINISHED;
mSucceeded = succeeded;
mIsUpgrade = isUpgrade;
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-completed"));
observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-completed", nullptr);
LOG(("Done offline-cache-update-completed"));
}
// This is by contract the last notification from the parent, release
// us now. This is corresponding to AddRef in Schedule().
// BrowserChild::DeallocPOfflineCacheUpdate will call Release.
OfflineCacheUpdateChild::Send__delete__(this);
return IPC_OK();
}
} // namespace docshell
} // namespace mozilla

View file

@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsOfflineCacheUpdateChild_h
#define nsOfflineCacheUpdateChild_h
#include "mozilla/docshell/POfflineCacheUpdateChild.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIURI.h"
#include "nsIWeakReference.h"
#include "nsString.h"
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
class Document;
}
namespace docshell {
class OfflineCacheUpdateChild : public nsIOfflineCacheUpdate,
public POfflineCacheUpdateChild {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATE
mozilla::ipc::IPCResult RecvNotifyStateEvent(const uint32_t& stateEvent,
const uint64_t& byteProgress);
mozilla::ipc::IPCResult RecvAssociateDocuments(
const nsCString& cacheGroupId, const nsCString& cacheClientId);
mozilla::ipc::IPCResult RecvFinish(const bool& succeeded,
const bool& isUpgrade);
explicit OfflineCacheUpdateChild(nsPIDOMWindowInner* aWindow);
void SetDocument(dom::Document* aDocument);
private:
~OfflineCacheUpdateChild();
nsresult AssociateDocument(dom::Document* aDocument,
nsIApplicationCache* aApplicationCache);
void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver>& aObservers);
nsresult Finish();
enum {
STATE_UNINITIALIZED,
STATE_INITIALIZED,
STATE_CHECKING,
STATE_DOWNLOADING,
STATE_CANCELLED,
STATE_FINISHED
} mState;
bool mIsUpgrade;
bool mSucceeded;
nsCString mUpdateDomain;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
nsCOMPtr<nsIObserverService> mObserverService;
/* Clients watching this update for changes */
nsCOMArray<nsIWeakReference> mWeakObservers;
nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
/* Document that requested this update */
nsCOMPtr<dom::Document> mDocument;
/* Keep reference to the window that owns this update to call the
parent offline cache update construcor */
nsCOMPtr<nsPIDOMWindowInner> mWindow;
uint64_t mByteProgress;
};
} // namespace docshell
} // namespace mozilla
#endif

View file

@ -1,220 +0,0 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OfflineCacheUpdateGlue.h"
#include "nsOfflineCacheUpdate.h"
#include "mozilla/Services.h"
#include "nsIApplicationCache.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIChannel.h"
#include "mozilla/dom/Document.h"
#include "mozilla/Logging.h"
using mozilla::dom::Document;
//
// To enable logging (see mozilla/Logging.h for full details):
//
// set MOZ_LOG=nsOfflineCacheUpdate:5
// set MOZ_LOG_FILE=offlineupdate.log
//
// this enables LogLevel::Info level information and places all output in
// the file offlineupdate.log
//
extern mozilla::LazyLogModule gOfflineCacheUpdateLog;
#undef LOG
#define LOG(args) \
MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
#undef LOG_ENABLED
#define LOG_ENABLED() \
MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateGlue::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(OfflineCacheUpdateGlue, nsIOfflineCacheUpdate,
nsIOfflineCacheUpdateObserver, nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateGlue <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateGlue::OfflineCacheUpdateGlue() : mCoalesced(false) {
LOG(("OfflineCacheUpdateGlue::OfflineCacheUpdateGlue [%p]", this));
}
OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue() {
LOG(("OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue [%p]", this));
}
nsIOfflineCacheUpdate* OfflineCacheUpdateGlue::EnsureUpdate() {
if (!mUpdate) {
mUpdate = new nsOfflineCacheUpdate();
LOG(("OfflineCacheUpdateGlue [%p] is using update [%p]", this,
mUpdate.get()));
mUpdate->SetCookieJarSettings(mCookieJarSettings);
}
return mUpdate;
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::Schedule() {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-added"));
observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-added", nullptr);
LOG(("Done offline-cache-update-added"));
}
if (!EnsureUpdate()) return NS_ERROR_NULL_POINTER;
// Do not use weak reference, we must survive!
mUpdate->AddObserver(this, false);
if (mCoalesced) // already scheduled
return NS_OK;
return mUpdate->Schedule();
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::Init(nsIURI* aManifestURI, nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
Document* aDocument, nsIFile* aCustomProfileDir) {
nsresult rv;
nsAutoCString originSuffix;
rv = aLoadingPrincipal->GetOriginSuffix(originSuffix);
NS_ENSURE_SUCCESS(rv, rv);
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (service) {
service->FindUpdate(aManifestURI, originSuffix, aCustomProfileDir,
getter_AddRefs(mUpdate));
mCoalesced = !!mUpdate;
}
if (!EnsureUpdate()) return NS_ERROR_NULL_POINTER;
mDocumentURI = aDocumentURI;
mLoadingPrincipal = aLoadingPrincipal;
if (aDocument) SetDocument(aDocument);
if (mCoalesced) { // already initialized
LOG(("OfflineCacheUpdateGlue %p coalesced with update %p", this,
mUpdate.get()));
return NS_OK;
}
rv = mUpdate->Init(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
aCustomProfileDir);
mUpdate->SetCookieJarSettings(mCookieJarSettings);
return rv;
}
void OfflineCacheUpdateGlue::SetDocument(Document* aDocument) {
// The design is one document for one cache update on the content process.
NS_ASSERTION(!mDocument,
"Setting more then a single document on an instance of "
"OfflineCacheUpdateGlue");
LOG(("Document %p added to update glue %p", aDocument, this));
// Add document only if it was not loaded from an offline cache.
// If it were loaded from an offline cache then it has already
// been associated with it and must not be again cached as
// implicit (which are the reasons we collect documents here).
if (!aDocument) return;
mCookieJarSettings = aDocument->CookieJarSettings();
nsIChannel* channel = aDocument->GetChannel();
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (!appCacheChannel) return;
bool loadedFromAppCache;
appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
if (loadedFromAppCache) return;
if (EnsureUpdate()) {
mUpdate->StickDocument(mDocumentURI);
}
mDocument = aDocument;
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::UpdateStateChanged(nsIOfflineCacheUpdate* aUpdate,
uint32_t state) {
if (state == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
LOG(("OfflineCacheUpdateGlue got STATE_FINISHED [%p]", this));
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-completed"));
observerService->NotifyObservers(
static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-completed", nullptr);
LOG(("Done offline-cache-update-completed"));
}
aUpdate->RemoveObserver(this);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::ApplicationCacheAvailable(
nsIApplicationCache* aApplicationCache) {
NS_ENSURE_ARG(aApplicationCache);
// Check that the document that requested this update was
// previously associated with an application cache. If not, it
// should be associated with the new one.
if (!mDocument) {
return NS_OK;
}
nsCOMPtr<nsIApplicationCache> existingCache;
nsresult rv = mDocument->GetApplicationCache(getter_AddRefs(existingCache));
NS_ENSURE_SUCCESS(rv, rv);
if (!existingCache) {
if (LOG_ENABLED()) {
nsAutoCString clientID;
if (aApplicationCache) {
aApplicationCache->GetClientID(clientID);
}
LOG(("Update %p: associating app cache %s to document %p", this,
clientID.get(), mDocument.get()));
}
rv = mDocument->SetApplicationCache(aApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
} // namespace docshell
} // namespace mozilla

View file

@ -1,124 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsOfflineCacheUpdateGlue_h
#define nsOfflineCacheUpdateGlue_h
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsWeakReference.h"
#include "mozilla/Attributes.h"
class nsOfflineCacheUpdate;
namespace mozilla {
namespace dom {
class Document;
}
namespace docshell {
// Like FORWARD_SAFE except methods:
// Schedule
// Init
#define NS_ADJUSTED_FORWARD_NSIOFFLINECACHEUPDATE(_to) \
NS_IMETHOD GetStatus(uint16_t* aStatus) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetStatus(aStatus); \
} \
NS_IMETHOD GetPartial(bool* aPartial) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetPartial(aPartial); \
} \
NS_IMETHOD GetIsUpgrade(bool* aIsUpgrade) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsUpgrade(aIsUpgrade); \
} \
NS_IMETHOD GetUpdateDomain(nsACString& aUpdateDomain) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetUpdateDomain(aUpdateDomain); \
} \
NS_IMETHOD GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) override { \
return !_to ? NS_ERROR_NULL_POINTER \
: _to->GetLoadingPrincipal(aLoadingPrincipal); \
} \
NS_IMETHOD GetManifestURI(nsIURI** aManifestURI) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetManifestURI(aManifestURI); \
} \
NS_IMETHOD GetSucceeded(bool* aSucceeded) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetSucceeded(aSucceeded); \
} \
NS_IMETHOD InitPartial(nsIURI* aManifestURI, const nsACString& aClientID, \
nsIURI* aDocumentURI, \
nsIPrincipal* aLoadingPrincipal, \
nsICookieJarSettings* aCookieJarSettings) override { \
return !_to ? NS_ERROR_NULL_POINTER \
: _to->InitPartial(aManifestURI, aClientID, aDocumentURI, \
aLoadingPrincipal, aCookieJarSettings); \
} \
NS_IMETHOD InitForUpdateCheck(nsIURI* aManifestURI, \
nsIPrincipal* aLoadingPrincipal, \
nsIObserver* aObserver) override { \
return !_to ? NS_ERROR_NULL_POINTER \
: _to->InitForUpdateCheck(aManifestURI, aLoadingPrincipal, \
aObserver); \
} \
NS_IMETHOD AddDynamicURI(nsIURI* aURI) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->AddDynamicURI(aURI); \
} \
NS_IMETHOD AddObserver(nsIOfflineCacheUpdateObserver* aObserver, \
bool aHoldWeak) override { \
return !_to ? NS_ERROR_NULL_POINTER \
: _to->AddObserver(aObserver, aHoldWeak); \
} \
NS_IMETHOD RemoveObserver(nsIOfflineCacheUpdateObserver* aObserver) \
override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->RemoveObserver(aObserver); \
} \
NS_IMETHOD GetByteProgress(uint64_t* _result) override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->GetByteProgress(_result); \
} \
NS_IMETHOD Cancel() override { \
return !_to ? NS_ERROR_NULL_POINTER : _to->Cancel(); \
}
class OfflineCacheUpdateGlue final : public nsSupportsWeakReference,
public nsIOfflineCacheUpdate,
public nsIOfflineCacheUpdateObserver {
public:
NS_DECL_ISUPPORTS
private:
nsIOfflineCacheUpdate* EnsureUpdate();
public:
NS_ADJUSTED_FORWARD_NSIOFFLINECACHEUPDATE(EnsureUpdate())
NS_IMETHOD Schedule(void) override;
NS_IMETHOD Init(nsIURI* aManifestURI, nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
mozilla::dom::Document* aDocument,
nsIFile* aCustomProfileDir) override;
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
OfflineCacheUpdateGlue();
void SetDocument(mozilla::dom::Document* aDocument);
private:
~OfflineCacheUpdateGlue();
RefPtr<nsOfflineCacheUpdate> mUpdate;
bool mCoalesced;
/* Document that requested this update */
RefPtr<mozilla::dom::Document> mDocument;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
};
} // namespace docshell
} // namespace mozilla
#endif

View file

@ -1,287 +0,0 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OfflineCacheUpdateParent.h"
#include "BackgroundUtils.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsOfflineCacheUpdate.h"
#include "nsIApplicationCache.h"
#include "nsNetUtil.h"
using namespace mozilla::ipc;
using mozilla::BasePrincipal;
using mozilla::OriginAttributes;
using mozilla::dom::BrowserParent;
//
// To enable logging (see mozilla/Logging.h for full details):
//
// set MOZ_LOG=nsOfflineCacheUpdate:5
// set MOZ_LOG_FILE=offlineupdate.log
//
// this enables LogLevel::Debug level information and places all output in
// the file offlineupdate.log
//
extern mozilla::LazyLogModule gOfflineCacheUpdateLog;
#undef LOG
#define LOG(args) \
MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
#undef LOG_ENABLED
#define LOG_ENABLED() \
MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(OfflineCacheUpdateParent, nsIOfflineCacheUpdateObserver,
nsILoadContext)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateParent::OfflineCacheUpdateParent() : mIPCClosed(false) {
// Make sure the service has been initialized
nsOfflineCacheUpdateService::EnsureService();
LOG(("OfflineCacheUpdateParent::OfflineCacheUpdateParent [%p]", this));
}
OfflineCacheUpdateParent::~OfflineCacheUpdateParent() {
LOG(("OfflineCacheUpdateParent::~OfflineCacheUpdateParent [%p]", this));
}
void OfflineCacheUpdateParent::ActorDestroy(ActorDestroyReason why) {
mIPCClosed = true;
}
nsresult OfflineCacheUpdateParent::Schedule(
nsIURI* aManifestURI, nsIURI* aDocumentURI,
const PrincipalInfo& aLoadingPrincipalInfo, const bool& stickDocument,
const CookieJarSettingsArgs& aCookieJarSettingsArgs) {
LOG(("OfflineCacheUpdateParent::RecvSchedule [%p]", this));
RefPtr<nsOfflineCacheUpdate> update;
if (!aManifestURI) {
return NS_ERROR_FAILURE;
}
auto loadingPrincipalOrErr = PrincipalInfoToPrincipal(aLoadingPrincipalInfo);
if (NS_WARN_IF(loadingPrincipalOrErr.isErr())) {
return loadingPrincipalOrErr.unwrapErr();
}
mLoadingPrincipal = loadingPrincipalOrErr.unwrap();
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (!service) {
return NS_ERROR_FAILURE;
}
bool offlinePermissionAllowed = false;
nsresult rv =
service->OfflineAppAllowed(mLoadingPrincipal, &offlinePermissionAllowed);
NS_ENSURE_SUCCESS(rv, rv);
if (!offlinePermissionAllowed) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!aDocumentURI) {
return NS_ERROR_FAILURE;
}
if (!NS_SecurityCompareURIs(aManifestURI, aDocumentURI, false)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsAutoCString originSuffix;
rv = mLoadingPrincipal->GetOriginSuffix(originSuffix);
NS_ENSURE_SUCCESS(rv, rv);
service->FindUpdate(aManifestURI, originSuffix, nullptr,
getter_AddRefs(update));
if (!update) {
update = new nsOfflineCacheUpdate();
// Leave aDocument argument null. Only glues and children keep
// document instances.
rv = update->Init(aManifestURI, aDocumentURI, mLoadingPrincipal, nullptr,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
update->SetCookieJarSettingsArgs(aCookieJarSettingsArgs);
// Must add before Schedule() call otherwise we would miss
// oncheck event notification.
update->AddObserver(this, false);
rv = update->Schedule();
NS_ENSURE_SUCCESS(rv, rv);
} else {
update->AddObserver(this, false);
}
if (stickDocument) {
update->StickDocument(aDocumentURI);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::UpdateStateChanged(nsIOfflineCacheUpdate* aUpdate,
uint32_t state) {
if (mIPCClosed) {
return NS_ERROR_UNEXPECTED;
}
LOG(("OfflineCacheUpdateParent::StateEvent [%p]", this));
uint64_t byteProgress;
aUpdate->GetByteProgress(&byteProgress);
Unused << SendNotifyStateEvent(state, byteProgress);
if (state == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
// Tell the child the particulars after the update has finished.
// Sending the Finish event will release the child side of the protocol
// and notify "offline-cache-update-completed" on the child process.
bool isUpgrade;
aUpdate->GetIsUpgrade(&isUpgrade);
bool succeeded;
aUpdate->GetSucceeded(&succeeded);
Unused << SendFinish(succeeded, isUpgrade);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::ApplicationCacheAvailable(
nsIApplicationCache* aApplicationCache) {
if (mIPCClosed) {
return NS_ERROR_UNEXPECTED;
}
NS_ENSURE_ARG(aApplicationCache);
nsCString cacheClientId;
aApplicationCache->GetClientID(cacheClientId);
nsCString cacheGroupId;
aApplicationCache->GetGroupID(cacheGroupId);
Unused << SendAssociateDocuments(cacheGroupId, cacheClientId);
return NS_OK;
}
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent::nsILoadContext
//-----------------------------------------------------------------------------
NS_IMETHODIMP
OfflineCacheUpdateParent::GetAssociatedWindow(
mozIDOMWindowProxy** aAssociatedWindow) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetTopWindow(mozIDOMWindowProxy** aTopWindow) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetTopFrameElement(dom::Element** aElement) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetIsContent(bool* aIsContent) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUseRemoteTabs(bool* aUseRemoteTabs) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetRemoteTabs(bool aUseRemoteTabs) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetRemoteSubframes(bool aUseRemoteSubframes) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetScriptableOriginAttributes(
JSContext* aCx, JS::MutableHandleValue aAttrs) {
NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED);
nsresult rv = mLoadingPrincipal->GetOriginAttributes(aCx, aAttrs);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP_(void)
OfflineCacheUpdateParent::GetOriginAttributes(
mozilla::OriginAttributes& aAttrs) {
if (mLoadingPrincipal) {
aAttrs = mLoadingPrincipal->OriginAttributesRef();
}
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUseTrackingProtection(
bool* aUseTrackingProtection) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetUseTrackingProtection(
bool aUseTrackingProtection) {
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace docshell
} // namespace mozilla

View file

@ -1,64 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsOfflineCacheUpdateParent_h
#define nsOfflineCacheUpdateParent_h
#include "mozilla/docshell/POfflineCacheUpdateParent.h"
#include "mozilla/BasePrincipal.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsILoadContext.h"
class nsIPrincipal;
namespace mozilla {
namespace ipc {
class URIParams;
} // namespace ipc
namespace net {
class CookieJarSettingsArgs;
}
namespace docshell {
class OfflineCacheUpdateParent : public POfflineCacheUpdateParent,
public nsIOfflineCacheUpdateObserver,
public nsILoadContext {
typedef mozilla::ipc::URIParams URIParams;
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
NS_DECL_NSILOADCONTEXT
nsresult Schedule(nsIURI* manifestURI, nsIURI* documentURI,
const PrincipalInfo& loadingPrincipalInfo,
const bool& stickDocument,
const net::CookieJarSettingsArgs& aCookieJarSettingsArgs);
void StopSendingMessagesToChild() { mIPCClosed = true; }
explicit OfflineCacheUpdateParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
private:
~OfflineCacheUpdateParent();
bool mIPCClosed;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
};
} // namespace docshell
} // namespace mozilla
#endif

View file

@ -1,28 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
namespace mozilla {
namespace docshell {
//-------------------------------------------------------------------
refcounted protocol POfflineCacheUpdate
{
manager PContent;
parent:
async __delete__();
child:
async NotifyStateEvent(uint32_t stateEvent, uint64_t byteProgress);
async AssociateDocuments(nsCString cacheGroupId, nsCString cacheClientId);
async Finish(bool succeeded, bool isUpgrade);
};
}
}

View file

@ -8,28 +8,13 @@ with Files("**"):
BUG_COMPONENT = ("Core", "Networking: Cache")
XPIDL_SOURCES += [
"nsIOfflineCacheUpdate.idl",
"nsIPrefetchService.idl",
]
XPIDL_MODULE = "prefetch"
EXPORTS.mozilla.docshell += [
"OfflineCacheUpdateChild.h",
"OfflineCacheUpdateParent.h",
]
UNIFIED_SOURCES += [
"nsOfflineCacheUpdate.cpp",
"nsOfflineCacheUpdateService.cpp",
"nsPrefetchService.cpp",
"OfflineCacheUpdateChild.cpp",
"OfflineCacheUpdateGlue.cpp",
"OfflineCacheUpdateParent.cpp",
]
IPDL_SOURCES += [
"POfflineCacheUpdate.ipdl",
]
include("/ipc/chromium/chromium-config.mozbuild")

View file

@ -1,291 +0,0 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface mozIDOMWindow;
interface nsIURI;
interface nsIOfflineCacheUpdate;
interface nsIPrincipal;
interface nsIPrefBranch;
interface nsIApplicationCache;
interface nsIFile;
interface nsIObserver;
interface nsICookieJarSettings;
webidl Document;
[scriptable, uuid(47360d57-8ef4-4a5d-8865-1a27a739ad1a)]
interface nsIOfflineCacheUpdateObserver : nsISupports {
const unsigned long STATE_ERROR = 1;
const unsigned long STATE_CHECKING = 2;
const unsigned long STATE_NOUPDATE = 3;
const unsigned long STATE_OBSOLETE = 4;
const unsigned long STATE_DOWNLOADING = 5;
const unsigned long STATE_ITEMSTARTED = 6;
const unsigned long STATE_ITEMCOMPLETED = 7;
const unsigned long STATE_ITEMPROGRESS = 8;
const unsigned long STATE_FINISHED = 10;
/**
* aUpdate has changed its state.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
* @param event
* See enumeration above
*/
void updateStateChanged(in nsIOfflineCacheUpdate aUpdate, in uint32_t state);
/**
* Informs the observer about an application being available to associate.
*
* @param applicationCache
* The application cache instance that has been created or found by the
* update to associate with
*/
void applicationCacheAvailable(in nsIApplicationCache applicationCache);
};
/**
* An nsIOfflineCacheUpdate is used to update an application's offline
* resources.
*
* It can be used to perform partial or complete updates.
*
* One update object will be updating at a time. The active object will
* load its items one by one, sending itemCompleted() to any registered
* observers.
*/
[scriptable, uuid(6e3e26ea-45b2-4db7-9e4a-93b965679298)]
interface nsIOfflineCacheUpdate : nsISupports {
/**
* Fetch the status of the running update. This will return a value
* defined in OfflineResourceList.webidl.
*/
readonly attribute unsigned short status;
/**
* TRUE if the update is being used to add specific resources.
* FALSE if the complete cache update process is happening.
*/
readonly attribute boolean partial;
/**
* TRUE if this is an upgrade attempt, FALSE if it is a new cache
* attempt.
*/
readonly attribute boolean isUpgrade;
/**
* The domain being updated, and the domain that will own any URIs added
* with this update.
*/
readonly attribute ACString updateDomain;
/**
* The manifest for the offline application being updated.
*/
readonly attribute nsIURI manifestURI;
/**
* The principal of the page that is requesting the update.
*/
readonly attribute nsIPrincipal loadingPrincipal;
/**
* TRUE if the cache update completed successfully.
*/
readonly attribute boolean succeeded;
/**
* Initialize the update.
*
* @param aManifestURI
* The manifest URI to be checked.
* @param aDocumentURI
* The page that is requesting the update.
* @param aLoadingPrincipal
* The principal of the page that is requesting the update.
*/
void init(in nsIURI aManifestURI,
in nsIURI aDocumentURI,
in nsIPrincipal aLoadingPrincipal,
in Document aDocument,
[optional] in nsIFile aCustomProfileDir);
/**
* Initialize the update for partial processing.
*
* @param aManifestURI
* The manifest URI of the related cache.
* @param aClientID
* Client ID of the cache to store resource to. This ClientID
* must be ID of cache in the cache group identified by
* the manifest URI passed in the first parameter.
* @param aDocumentURI
* The page that is requesting the update. May be null
* when this information is unknown.
* @param aCookieJarSettings
* The cookie jar settings belonging to the page that is requesting
* the update.
*/
void initPartial(in nsIURI aManifestURI, in ACString aClientID,
in nsIURI aDocumentURI, in nsIPrincipal aPrincipal,
in nsICookieJarSettings aCookieJarSettings);
/**
* Initialize the update to only check whether there is an update
* to the manifest available (if it has actually changed on the server).
*
* @param aManifestURI
* The manifest URI of the related cache.
* @param aObserver
* nsIObserver implementation that receives the result.
* When aTopic == "offline-cache-update-available" there is an update to
* to download. Update of the app cache will lead to a new version
* download.
* When aTopic == "offline-cache-update-unavailable" then there is no
* update available (the manifest has not changed on the server).
*/
void initForUpdateCheck(in nsIURI aManifestURI,
in nsIPrincipal aLoadingPrincipal,
in nsIObserver aObserver);
/**
* Add a dynamic URI to the offline cache as part of the update.
*
* @param aURI
* The URI to add.
*/
void addDynamicURI(in nsIURI aURI);
/**
* Add the update to the offline update queue. An offline-cache-update-added
* event will be sent to the observer service.
*/
void schedule();
/**
* Observe loads that are added to the update.
*
* @param aObserver
* object that notifications will be sent to.
* @param aHoldWeak
* TRUE if you want the update to hold a weak reference to the
* observer, FALSE for a strong reference.
*/
void addObserver(in nsIOfflineCacheUpdateObserver aObserver,
[optional] in boolean aHoldWeak);
/**
* Remove an observer from the update.
*
* @param aObserver
* the observer to remove.
*/
void removeObserver(in nsIOfflineCacheUpdateObserver aObserver);
/**
* Cancel the update when still in progress. This stops all running resource
* downloads and discards the downloaded cache version. Throws when update
* has already finished and made the new cache version active.
*/
void cancel();
/**
* Return the number of bytes downloaded so far
*/
readonly attribute uint64_t byteProgress;
};
[scriptable, uuid(44971e74-37e4-4140-8677-a4cf213a3f4b)]
interface nsIOfflineCacheUpdateService : nsISupports {
/**
* Constants for the offline-app permission.
*
* XXX: This isn't a great place for this, but it's really the only
* private offline-app-related interface
*/
/**
* Allow the domain to use offline APIs, and don't warn about excessive
* usage.
*/
const unsigned long ALLOW_NO_WARN = 3;
/**
* Access to the list of cache updates that have been scheduled.
*/
readonly attribute unsigned long numUpdates;
nsIOfflineCacheUpdate getUpdate(in unsigned long index);
/**
* Schedule a cache update for a given offline manifest. If an
* existing update is scheduled or running, that update will be returned.
* Otherwise a new update will be scheduled.
*/
nsIOfflineCacheUpdate scheduleUpdate(in nsIURI aManifestURI,
in nsIURI aDocumentURI,
in nsIPrincipal aLoadingPrincipal,
in mozIDOMWindow aWindow);
/**
* Schedule a cache update for a given offline manifest using app cache
* bound to the given appID flag. If an existing update is scheduled or
* running, that update will be returned. Otherwise a new update will be
* scheduled.
*/
nsIOfflineCacheUpdate scheduleAppUpdate(in nsIURI aManifestURI,
in nsIURI aDocumentURI,
in nsIPrincipal aLoadingPrincipal,
in nsIFile aProfileDir);
/**
* Schedule a cache update for a manifest when the document finishes
* loading.
*/
void scheduleOnDocumentStop(in nsIURI aManifestURI,
in nsIURI aDocumentURI,
in nsIPrincipal aLoadingPrincipal,
in Document aDocument);
/**
* Schedule a check to see if an update is available.
*
* This will not update or make any changes to the appcache.
* It only notifies the observer to indicate whether the manifest has
* changed on the server (or not): a changed manifest means that an
* update is available.
*
* For arguments see nsIOfflineCacheUpdate.initForUpdateCheck() method
* description.
*/
void checkForUpdate(in nsIURI aManifestURI,
in nsIPrincipal aLoadingPrincipal,
in nsIObserver aObserver);
/**
* Checks whether a principal should have access to the offline
* cache.
* @param aPrincipal
* The principal to check.
*/
boolean offlineAppAllowed(in nsIPrincipal aPrincipal);
/**
* Checks whether a document at the given URI should have access
* to the offline cache.
* @param aURI
* The URI to check
*/
boolean offlineAppAllowedForURI(in nsIURI aURI);
/**
* Sets the "offline-app" permission for the principal.
* In the single process model calls directly on permission manager.
* In the multi process model dispatches to the parent process.
*/
void allowOfflineApp(in nsIPrincipal aPrincipal);
};

File diff suppressed because it is too large Load diff

View file

@ -1,369 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsOfflineCacheUpdate_h__
#define nsOfflineCacheUpdate_h__
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIMutableArray.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIApplicationCache.h"
#include "nsIRunnable.h"
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "nsClassHashtable.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsWeakReference.h"
#include "nsICryptoHash.h"
#include "mozilla/Attributes.h"
#include "mozilla/WeakPtr.h"
#include "nsTHashSet.h"
#include "nsHashKeys.h"
namespace mozilla {
namespace net {
class CookieJarSettingsArgs;
}
} // namespace mozilla
class nsOfflineCacheUpdate;
class nsOfflineCacheUpdateItem : public nsIStreamListener,
public nsIRunnable,
public nsIInterfaceRequestor,
public nsIChannelEventSink {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIRUNNABLE
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
nsOfflineCacheUpdateItem(nsIURI* aURI, nsIURI* aReferrerURI,
nsIPrincipal* aLoadingPrincipal,
nsIApplicationCache* aApplicationCache,
nsIApplicationCache* aPreviousApplicationCache,
uint32_t aType, uint32_t aLoadFlags);
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mReferrerURI;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsIApplicationCache> mApplicationCache;
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
nsCString mCacheKey;
uint32_t mItemType;
uint32_t mLoadFlags;
nsresult OpenChannel(nsOfflineCacheUpdate* aUpdate);
nsresult Cancel();
nsresult GetRequestSucceeded(bool* succeeded);
bool IsInProgress();
bool IsScheduled();
bool IsCompleted();
nsresult GetStatus(uint16_t* aStatus);
private:
enum LoadStatus : uint16_t {
UNINITIALIZED = 0U,
REQUESTED = 1U,
RECEIVING = 2U,
LOADED = 3U
};
RefPtr<nsOfflineCacheUpdate> mUpdate;
nsCOMPtr<nsIChannel> mChannel;
uint16_t mState;
protected:
virtual ~nsOfflineCacheUpdateItem();
int64_t mBytesRead;
};
class nsOfflineManifestItem : public nsOfflineCacheUpdateItem {
public:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
nsOfflineManifestItem(nsIURI* aURI, nsIURI* aReferrerURI,
nsIPrincipal* aLoadingPrincipal,
nsIApplicationCache* aApplicationCache,
nsIApplicationCache* aPreviousApplicationCache);
virtual ~nsOfflineManifestItem();
nsCOMArray<nsIURI>& GetExplicitURIs() { return mExplicitURIs; }
nsCOMArray<nsIURI>& GetAnonymousURIs() { return mAnonymousURIs; }
nsCOMArray<nsIURI>& GetFallbackURIs() { return mFallbackURIs; }
nsTArray<nsCString>& GetOpportunisticNamespaces() {
return mOpportunisticNamespaces;
}
nsIArray* GetNamespaces() { return mNamespaces.get(); }
bool ParseSucceeded() {
return (mParserState != PARSE_INIT && mParserState != PARSE_ERROR);
}
bool NeedsUpdate() { return mParserState != PARSE_INIT && mNeedsUpdate; }
void GetManifestHash(nsCString& aManifestHash) {
aManifestHash = mManifestHashValue;
}
private:
static nsresult ReadManifest(nsIInputStream* aInputStream, void* aClosure,
const char* aFromSegment, uint32_t aOffset,
uint32_t aCount, uint32_t* aBytesConsumed);
nsresult AddNamespace(uint32_t namespaceType, const nsCString& namespaceSpec,
const nsCString& data);
nsresult HandleManifestLine(const nsCString::const_iterator& aBegin,
const nsCString::const_iterator& aEnd);
/**
* Saves "offline-manifest-hash" meta data from the old offline cache
* token to mOldManifestHashValue member to be compared on
* successfull load.
*/
nsresult GetOldManifestContentHash(nsIRequest* aRequest);
/**
* This method setups the mNeedsUpdate to false when hash value
* of the just downloaded manifest file is the same as stored in cache's
* "offline-manifest-hash" meta data. Otherwise stores the new value
* to this meta data.
*/
nsresult CheckNewManifestContentHash(nsIRequest* aRequest);
void ReadStrictFileOriginPolicyPref();
enum {
PARSE_INIT,
PARSE_CACHE_ENTRIES,
PARSE_FALLBACK_ENTRIES,
PARSE_BYPASS_ENTRIES,
PARSE_UNKNOWN_SECTION,
PARSE_ERROR
} mParserState;
nsCString mReadBuf;
nsCOMArray<nsIURI> mExplicitURIs;
nsCOMArray<nsIURI> mAnonymousURIs;
nsCOMArray<nsIURI> mFallbackURIs;
// All opportunistic caching namespaces. Used to decide whether
// to include previously-opportunistically-cached entries.
nsTArray<nsCString> mOpportunisticNamespaces;
// Array of nsIApplicationCacheNamespace objects specified by the
// manifest.
nsCOMPtr<nsIMutableArray> mNamespaces;
bool mNeedsUpdate;
bool mStrictFileOriginPolicy;
// manifest hash data
nsCOMPtr<nsICryptoHash> mManifestHash;
bool mManifestHashInitialized;
nsCString mManifestHashValue;
nsCString mOldManifestHashValue;
};
class nsOfflineCacheUpdateOwner : public mozilla::SupportsWeakPtr {
public:
virtual ~nsOfflineCacheUpdateOwner() {}
virtual nsresult UpdateFinished(nsOfflineCacheUpdate* aUpdate) = 0;
};
class nsOfflineCacheUpdate final : public nsIOfflineCacheUpdate,
public nsIOfflineCacheUpdateObserver,
public nsIRunnable,
public nsOfflineCacheUpdateOwner {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATE
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
NS_DECL_NSIRUNNABLE
nsOfflineCacheUpdate();
static nsresult GetCacheKey(nsIURI* aURI, nsACString& aKey);
nsresult Init();
nsresult Begin();
void LoadCompleted(nsOfflineCacheUpdateItem* aItem);
void ManifestCheckCompleted(nsresult aStatus, const nsCString& aManifestHash);
void StickDocument(nsIURI* aDocumentURI);
void SetOwner(nsOfflineCacheUpdateOwner* aOwner);
bool IsForGroupID(const nsACString& groupID);
bool IsForProfile(nsIFile* aCustomProfileDir);
virtual nsresult UpdateFinished(nsOfflineCacheUpdate* aUpdate) override;
nsICookieJarSettings* CookieJarSettings() const { return mCookieJarSettings; }
void SetCookieJarSettings(nsICookieJarSettings* aCookieJarSettings);
void SetCookieJarSettingsArgs(
const mozilla::net::CookieJarSettingsArgs& aCookieJarSettingsArgs);
protected:
~nsOfflineCacheUpdate();
friend class nsOfflineCacheUpdateItem;
void OnByteProgress(uint64_t byteIncrement);
private:
nsresult InitInternal(nsIURI* aManifestURI, nsIPrincipal* aPrincipal);
nsresult HandleManifest(bool* aDoUpdate);
nsresult AddURI(nsIURI* aURI, uint32_t aItemType, uint32_t aLoadFlags = 0);
nsresult ProcessNextURI();
// Adds items from the previous cache witha type matching aType.
// If namespaceFilter is non-null, only items matching the
// specified namespaces will be added.
nsresult AddExistingItems(uint32_t aType,
nsTArray<nsCString>* namespaceFilter = nullptr);
nsresult ScheduleImplicit();
void AssociateDocuments(nsIApplicationCache* cache);
bool CheckUpdateAvailability();
void NotifyUpdateAvailability(bool updateAvailable);
void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver>& aObservers);
void NotifyState(uint32_t state);
nsresult Finish();
nsresult FinishNoNotify();
void AsyncFinishWithError();
// Find one non-pinned cache group and evict it.
nsresult EvictOneNonPinned();
enum {
STATE_UNINITIALIZED,
STATE_INITIALIZED,
STATE_CHECKING,
STATE_DOWNLOADING,
STATE_CANCELLED,
STATE_FINISHED
} mState;
mozilla::WeakPtr<nsOfflineCacheUpdateOwner> mOwner;
bool mAddedItems;
bool mPartialUpdate;
bool mOnlyCheckUpdate;
bool mSucceeded;
bool mObsolete;
nsCString mUpdateDomain;
nsCString mGroupID;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsIFile> mCustomProfileDir;
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
nsCOMPtr<nsIObserver> mUpdateAvailableObserver;
nsCOMPtr<nsIApplicationCache> mApplicationCache;
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
nsCOMPtr<nsIObserverService> mObserverService;
RefPtr<nsOfflineManifestItem> mManifestItem;
/* Items being updated */
uint32_t mItemsInProgress;
nsTArray<RefPtr<nsOfflineCacheUpdateItem> > mItems;
/* Clients watching this update for changes */
nsCOMArray<nsIWeakReference> mWeakObservers;
nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
/* Documents that requested this update */
nsCOMArray<nsIURI> mDocumentURIs;
/* Reschedule count. When an update is rescheduled due to
* mismatched manifests, the reschedule count will be increased. */
uint32_t mRescheduleCount;
/* Whena an entry for a pinned app is retried, retries count is
* increaded. */
uint32_t mPinnedEntryRetriesCount;
RefPtr<nsOfflineCacheUpdate> mImplicitUpdate;
bool mPinned;
uint64_t mByteProgress;
};
class nsOfflineCacheUpdateService final : public nsIOfflineCacheUpdateService,
public nsIObserver,
public nsOfflineCacheUpdateOwner,
public nsSupportsWeakReference {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATESERVICE
NS_DECL_NSIOBSERVER
nsOfflineCacheUpdateService();
nsresult Init();
nsresult ScheduleUpdate(nsOfflineCacheUpdate* aUpdate);
nsresult FindUpdate(nsIURI* aManifestURI, nsACString const& aOriginSuffix,
nsIFile* aCustomProfileDir,
nsOfflineCacheUpdate** aUpdate);
nsresult Schedule(nsIURI* aManifestURI, nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
mozilla::dom::Document* aDocument,
nsPIDOMWindowInner* aWindow, nsIFile* aCustomProfileDir,
nsIOfflineCacheUpdate** aUpdate);
virtual nsresult UpdateFinished(nsOfflineCacheUpdate* aUpdate) override;
/**
* Returns the singleton nsOfflineCacheUpdateService without an addref, or
* nullptr if the service couldn't be created.
*/
static nsOfflineCacheUpdateService* EnsureService();
static already_AddRefed<nsOfflineCacheUpdateService> GetInstance();
static nsresult OfflineAppPinnedForURI(nsIURI* aDocumentURI, bool* aPinned);
static nsTHashSet<nsCString>* AllowedDomains();
private:
~nsOfflineCacheUpdateService();
nsresult ProcessNextUpdate();
nsTArray<RefPtr<nsOfflineCacheUpdate> > mUpdates;
static nsTHashSet<nsCString>* mAllowedDomains;
bool mDisabled;
bool mUpdateRunning;
};
#endif

View file

@ -1,645 +0,0 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OfflineCacheUpdateChild.h"
#include "OfflineCacheUpdateParent.h"
#include "nsXULAppAPI.h"
#include "OfflineCacheUpdateGlue.h"
#include "nsOfflineCacheUpdate.h"
#include "nsCURILoader.h"
#include "nsIApplicationCacheService.h"
#include "nsIContent.h"
#include "mozilla/dom/Document.h"
#include "nsIObserverService.h"
#include "nsIWebProgress.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "mozilla/Logging.h"
#include "mozilla/Components.h"
#include "mozilla/Preferences.h"
#include "mozilla/Attributes.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "nsContentUtils.h"
#include "mozilla/Unused.h"
using namespace mozilla;
using namespace mozilla::dom;
static nsOfflineCacheUpdateService* gOfflineCacheUpdateService = nullptr;
nsTHashSet<nsCString>* nsOfflineCacheUpdateService::mAllowedDomains = nullptr;
nsTHashSet<nsCString>* nsOfflineCacheUpdateService::AllowedDomains() {
if (!mAllowedDomains) mAllowedDomains = new nsTHashSet<nsCString>();
return mAllowedDomains;
}
typedef mozilla::docshell::OfflineCacheUpdateParent OfflineCacheUpdateParent;
typedef mozilla::docshell::OfflineCacheUpdateChild OfflineCacheUpdateChild;
typedef mozilla::docshell::OfflineCacheUpdateGlue OfflineCacheUpdateGlue;
//
// To enable logging (see mozilla/Logging.h for full details):
//
// set MOZ_LOG=nsOfflineCacheUpdate:5
// set MOZ_LOG_FILE=offlineupdate.log
//
// this enables LogLevel::Debug level information and places all output in
// the file offlineupdate.log
//
LazyLogModule gOfflineCacheUpdateLog("nsOfflineCacheUpdate");
#undef LOG
#define LOG(args) \
MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
#undef LOG_ENABLED
#define LOG_ENABLED() \
MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
//-----------------------------------------------------------------------------
// nsOfflineCachePendingUpdate
//-----------------------------------------------------------------------------
class nsOfflineCachePendingUpdate final : public nsIWebProgressListener,
public nsSupportsWeakReference {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
nsOfflineCachePendingUpdate(nsOfflineCacheUpdateService* aService,
nsIURI* aManifestURI, nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
Document* aDocument)
: mService(aService),
mManifestURI(aManifestURI),
mDocumentURI(aDocumentURI),
mLoadingPrincipal(aLoadingPrincipal),
mDidReleaseThis(false) {
mDocument = do_GetWeakReference(aDocument);
}
private:
~nsOfflineCachePendingUpdate() {}
RefPtr<nsOfflineCacheUpdateService> mService;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsWeakPtr mDocument;
bool mDidReleaseThis;
};
NS_IMPL_ISUPPORTS(nsOfflineCachePendingUpdate, nsIWebProgressListener,
nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIWebProgressListener
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnProgressChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
int32_t curSelfProgress,
int32_t maxSelfProgress,
int32_t curTotalProgress,
int32_t maxTotalProgress) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t progressStateFlags,
nsresult aStatus) {
if (mDidReleaseThis) {
return NS_OK;
}
nsCOMPtr<Document> updateDoc = do_QueryReferent(mDocument);
if (!updateDoc) {
// The document that scheduled this update has gone away,
// we don't need to listen anymore.
aWebProgress->RemoveProgressListener(this);
MOZ_ASSERT(!mDidReleaseThis);
mDidReleaseThis = true;
NS_RELEASE_THIS();
return NS_OK;
}
if (!(progressStateFlags & STATE_STOP)) {
return NS_OK;
}
nsCOMPtr<mozIDOMWindowProxy> windowProxy;
aWebProgress->GetDOMWindow(getter_AddRefs(windowProxy));
if (!windowProxy) return NS_OK;
auto* outerWindow = nsPIDOMWindowOuter::From(windowProxy);
nsPIDOMWindowInner* innerWindow = outerWindow->GetCurrentInnerWindow();
nsCOMPtr<Document> progressDoc = outerWindow->GetDoc();
if (!progressDoc || progressDoc != updateDoc) {
return NS_OK;
}
LOG(("nsOfflineCachePendingUpdate::OnStateChange [%p, doc=%p]", this,
progressDoc.get()));
// Only schedule the update if the document loaded successfully
if (NS_SUCCEEDED(aStatus)) {
nsCOMPtr<nsIOfflineCacheUpdate> update;
mService->Schedule(mManifestURI, mDocumentURI, mLoadingPrincipal, updateDoc,
innerWindow, nullptr, getter_AddRefs(update));
if (mDidReleaseThis) {
return NS_OK;
}
}
aWebProgress->RemoveProgressListener(this);
MOZ_ASSERT(!mDidReleaseThis);
mDidReleaseThis = true;
NS_RELEASE_THIS();
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* location,
uint32_t aFlags) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnContentBlockingEvent(
nsIWebProgress* aWebProgress, nsIRequest* aRequest, uint32_t aEvent) {
MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(nsOfflineCacheUpdateService, nsIOfflineCacheUpdateService,
nsIObserver, nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService <public>
//-----------------------------------------------------------------------------
nsOfflineCacheUpdateService::nsOfflineCacheUpdateService()
: mDisabled(false), mUpdateRunning(false) {
MOZ_ASSERT(NS_IsMainThread());
}
nsOfflineCacheUpdateService::~nsOfflineCacheUpdateService() {
MOZ_ASSERT(gOfflineCacheUpdateService == this);
gOfflineCacheUpdateService = nullptr;
delete mAllowedDomains;
mAllowedDomains = nullptr;
}
nsresult nsOfflineCacheUpdateService::Init() {
// Observe xpcom-shutdown event
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (!observerService) return NS_ERROR_FAILURE;
nsresult rv =
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
NS_ENSURE_SUCCESS(rv, rv);
gOfflineCacheUpdateService = this;
return NS_OK;
}
/* static */
already_AddRefed<nsOfflineCacheUpdateService>
nsOfflineCacheUpdateService::GetInstance() {
if (!gOfflineCacheUpdateService) {
auto serv = MakeRefPtr<nsOfflineCacheUpdateService>();
if (NS_FAILED(serv->Init())) serv = nullptr;
MOZ_ASSERT(gOfflineCacheUpdateService == serv.get());
return serv.forget();
}
return do_AddRef(gOfflineCacheUpdateService);
}
/* static */
nsOfflineCacheUpdateService* nsOfflineCacheUpdateService::EnsureService() {
if (!gOfflineCacheUpdateService) {
// Make the service manager hold a long-lived reference to the service
nsCOMPtr<nsIOfflineCacheUpdateService> service =
components::OfflineCacheUpdate::Service();
Unused << service;
}
return gOfflineCacheUpdateService;
}
nsresult nsOfflineCacheUpdateService::ScheduleUpdate(
nsOfflineCacheUpdate* aUpdate) {
LOG(("nsOfflineCacheUpdateService::Schedule [%p, update=%p]", this, aUpdate));
aUpdate->SetOwner(this);
mUpdates.AppendElement(aUpdate);
ProcessNextUpdate();
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::ScheduleOnDocumentStop(
nsIURI* aManifestURI, nsIURI* aDocumentURI, nsIPrincipal* aLoadingPrincipal,
Document* aDocument) {
LOG(
("nsOfflineCacheUpdateService::ScheduleOnDocumentStop [%p, "
"manifestURI=%p, documentURI=%p doc=%p]",
this, aManifestURI, aDocumentURI, aDocument));
nsCOMPtr<nsIWebProgress> progress =
do_QueryInterface(aDocument->GetContainer());
NS_ENSURE_TRUE(progress, NS_ERROR_INVALID_ARG);
// Proceed with cache update
RefPtr<nsOfflineCachePendingUpdate> update = new nsOfflineCachePendingUpdate(
this, aManifestURI, aDocumentURI, aLoadingPrincipal, aDocument);
NS_ENSURE_TRUE(update, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = progress->AddProgressListener(
update, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
NS_ENSURE_SUCCESS(rv, rv);
// The update will release when it has scheduled itself.
Unused << update.forget();
return NS_OK;
}
nsresult nsOfflineCacheUpdateService::UpdateFinished(
nsOfflineCacheUpdate* aUpdate) {
LOG(("nsOfflineCacheUpdateService::UpdateFinished [%p, update=%p]", this,
aUpdate));
NS_ASSERTION(mUpdates.Length() > 0 && mUpdates[0] == aUpdate,
"Unknown update completed");
// keep this item alive until we're done notifying observers
RefPtr<nsOfflineCacheUpdate> update = mUpdates[0];
Unused << update;
mUpdates.RemoveElementAt(0);
mUpdateRunning = false;
ProcessNextUpdate();
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService <private>
//-----------------------------------------------------------------------------
nsresult nsOfflineCacheUpdateService::ProcessNextUpdate() {
LOG(("nsOfflineCacheUpdateService::ProcessNextUpdate [%p, num=%zu]", this,
mUpdates.Length()));
if (mDisabled) return NS_ERROR_ABORT;
if (mUpdateRunning) return NS_OK;
if (mUpdates.Length() > 0) {
mUpdateRunning = true;
return mUpdates[0]->Begin();
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateService::GetNumUpdates(uint32_t* aNumUpdates) {
LOG(("nsOfflineCacheUpdateService::GetNumUpdates [%p]", this));
*aNumUpdates = mUpdates.Length();
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::GetUpdate(uint32_t aIndex,
nsIOfflineCacheUpdate** aUpdate) {
LOG(("nsOfflineCacheUpdateService::GetUpdate [%p, %d]", this, aIndex));
if (aIndex < mUpdates.Length()) {
NS_ADDREF(*aUpdate = mUpdates[aIndex]);
} else {
*aUpdate = nullptr;
}
return NS_OK;
}
nsresult nsOfflineCacheUpdateService::FindUpdate(
nsIURI* aManifestURI, nsACString const& aOriginSuffix,
nsIFile* aCustomProfileDir, nsOfflineCacheUpdate** aUpdate) {
nsresult rv;
nsCOMPtr<nsIApplicationCacheService> cacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString groupID;
rv =
cacheService->BuildGroupIDForSuffix(aManifestURI, aOriginSuffix, groupID);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<nsOfflineCacheUpdate> update;
for (uint32_t i = 0; i < mUpdates.Length(); i++) {
update = mUpdates[i];
bool partial;
rv = update->GetPartial(&partial);
NS_ENSURE_SUCCESS(rv, rv);
if (partial) {
// Partial updates aren't considered
continue;
}
if (update->IsForGroupID(groupID) &&
update->IsForProfile(aCustomProfileDir)) {
update.swap(*aUpdate);
return NS_OK;
}
}
return NS_ERROR_NOT_AVAILABLE;
}
nsresult nsOfflineCacheUpdateService::Schedule(
nsIURI* aManifestURI, nsIURI* aDocumentURI, nsIPrincipal* aLoadingPrincipal,
Document* aDocument, nsPIDOMWindowInner* aWindow,
nsIFile* aCustomProfileDir, nsIOfflineCacheUpdate** aUpdate) {
nsCOMPtr<nsIOfflineCacheUpdate> update;
if (GeckoProcessType_Default != XRE_GetProcessType()) {
update = new OfflineCacheUpdateChild(aWindow);
} else {
update = new OfflineCacheUpdateGlue();
}
nsresult rv;
if (aWindow) {
// Ensure there is window.applicationCache object that is
// responsible for association of the new applicationCache
// with the corresponding document. Just ignore the result.
aWindow->GetApplicationCache();
}
rv = update->Init(aManifestURI, aDocumentURI, aLoadingPrincipal, aDocument,
aCustomProfileDir);
NS_ENSURE_SUCCESS(rv, rv);
rv = update->Schedule();
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aUpdate = update);
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::ScheduleUpdate(nsIURI* aManifestURI,
nsIURI* aDocumentURI,
nsIPrincipal* aLoadingPrincipal,
mozIDOMWindow* aWindow,
nsIOfflineCacheUpdate** aUpdate) {
return Schedule(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
nsPIDOMWindowInner::From(aWindow), nullptr, aUpdate);
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::ScheduleAppUpdate(
nsIURI* aManifestURI, nsIURI* aDocumentURI, nsIPrincipal* aLoadingPrincipal,
nsIFile* aProfileDir, nsIOfflineCacheUpdate** aUpdate) {
return Schedule(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
nullptr, aProfileDir, aUpdate);
}
NS_IMETHODIMP nsOfflineCacheUpdateService::CheckForUpdate(
nsIURI* aManifestURI, nsIPrincipal* aLoadingPrincipal,
nsIObserver* aObserver) {
if (GeckoProcessType_Default != XRE_GetProcessType()) {
// Not intended to support this on child processes
return NS_ERROR_NOT_IMPLEMENTED;
}
nsCOMPtr<nsIOfflineCacheUpdate> update = new OfflineCacheUpdateGlue();
nsresult rv;
rv = update->InitForUpdateCheck(aManifestURI, aLoadingPrincipal, aObserver);
NS_ENSURE_SUCCESS(rv, rv);
rv = update->Schedule();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIObserver
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
if (mUpdates.Length() > 0) mUpdates[0]->Cancel();
mDisabled = true;
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
//-----------------------------------------------------------------------------
static nsresult OfflineAppPermForPrincipal(nsIPrincipal* aPrincipal,
bool pinned, bool* aAllowed) {
*aAllowed = false;
if (!StaticPrefs::browser_cache_offline_enable()) {
return NS_OK;
}
if (!StaticPrefs::browser_cache_offline_storage_enable()) {
return NS_OK;
}
if (!aPrincipal) return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIURI> uri;
// Casting to BasePrincipal, as we can't get InnerMost URI otherwise
auto* basePrincipal = BasePrincipal::Cast(aPrincipal);
basePrincipal->GetURI(getter_AddRefs(uri));
if (!uri) return NS_OK;
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
if (!innerURI) return NS_OK;
// only https applications can use offline APIs.
if (!innerURI->SchemeIs("https")) {
return NS_OK;
}
nsAutoCString domain;
nsresult rv = innerURI->GetAsciiHost(domain);
NS_ENSURE_SUCCESS(rv, rv);
if (nsOfflineCacheUpdateService::AllowedDomains()->Contains(domain)) {
*aAllowed = true;
return NS_OK;
}
nsCOMPtr<nsIPermissionManager> permissionManager =
components::PermissionManager::Service();
if (!permissionManager) {
return NS_OK;
}
uint32_t perm;
const nsLiteralCString permName = pinned ? "pin-app"_ns : "offline-app"_ns;
permissionManager->TestExactPermissionFromPrincipal(aPrincipal, permName,
&perm);
if (perm == nsIPermissionManager::ALLOW_ACTION ||
perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) {
*aAllowed = true;
}
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::OfflineAppAllowed(nsIPrincipal* aPrincipal,
bool* aAllowed) {
return OfflineAppPermForPrincipal(aPrincipal, false, aAllowed);
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::OfflineAppAllowedForURI(nsIURI* aURI,
bool* aAllowed) {
OriginAttributes attrs;
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateContentPrincipal(aURI, attrs);
return OfflineAppPermForPrincipal(principal, false, aAllowed);
}
nsresult nsOfflineCacheUpdateService::OfflineAppPinnedForURI(
nsIURI* aDocumentURI, bool* aPinned) {
OriginAttributes attrs;
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateContentPrincipal(aDocumentURI, attrs);
return OfflineAppPermForPrincipal(principal, true, aPinned);
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::AllowOfflineApp(nsIPrincipal* aPrincipal) {
nsresult rv;
if (!StaticPrefs::browser_cache_offline_enable()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!StaticPrefs::browser_cache_offline_storage_enable()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIURI> uri;
// Casting to BasePrincipal, as we can't get InnerMost URI otherwise
auto* basePrincipal = BasePrincipal::Cast(aPrincipal);
basePrincipal->GetURI(getter_AddRefs(uri));
if (!uri) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
if (!innerURI) {
return NS_ERROR_NOT_AVAILABLE;
}
// if http then we should prevent this cache
if (innerURI->SchemeIs("http")) {
return NS_ERROR_NOT_AVAILABLE;
}
if (GeckoProcessType_Default != XRE_GetProcessType()) {
ContentChild* child = ContentChild::GetSingleton();
if (!child->SendSetOfflinePermission(IPC::Principal(aPrincipal))) {
return NS_ERROR_FAILURE;
}
nsAutoCString domain;
rv = aPrincipal->GetBaseDomain(domain);
NS_ENSURE_SUCCESS(rv, rv);
nsOfflineCacheUpdateService::AllowedDomains()->Insert(domain);
} else {
nsCOMPtr<nsIPermissionManager> permissionManager =
components::PermissionManager::Service();
if (!permissionManager) return NS_ERROR_NOT_AVAILABLE;
rv = permissionManager->AddFromPrincipal(
aPrincipal, "offline-app"_ns, nsIPermissionManager::ALLOW_ACTION,
nsIPermissionManager::EXPIRE_NEVER, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}

View file

@ -33,8 +33,11 @@
#include "mozilla/dom/Document.h"
#include "nsContentUtils.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "nsICachingChannel.h"
#include "nsHttp.h"
using namespace mozilla;
using namespace mozilla::dom;
//
// To enable logging (see mozilla/Logging.h for full details):
@ -207,7 +210,7 @@ nsPrefetchNode::OnStartRequest(nsIRequest* aRequest) {
//
uint32_t expTime;
if (NS_SUCCEEDED(cacheInfoChannel->GetCacheTokenExpirationTime(&expTime))) {
if (NowInSeconds() >= expTime) {
if (mozilla::net::NowInSeconds() >= expTime) {
LOG(
("document cannot be reused from cache; "
"canceling prefetch\n"));