summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2022-04-18 19:26:18 -0500
committerMatt A. Tobin <email@mattatobin.com>2022-04-18 19:26:18 -0500
commit5970ab8b55d3bf835bcf67d04352a0b3cfa3581d (patch)
tree948face04d19eb885b07dd3a961e2252a7990215 /system
parent320e5c434e26a8fa167292cc471f5c63c39daf77 (diff)
downloadaura-central-5970ab8b55d3bf835bcf67d04352a0b3cfa3581d.tar.gz
Issue #10 - Move prefetch to components/
Diffstat (limited to 'system')
-rw-r--r--system/docshell/build/moz.build2
-rw-r--r--system/docshell/moz.build1
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateChild.cpp528
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateChild.h94
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateGlue.cpp228
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateGlue.h80
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateParent.cpp294
-rw-r--r--system/docshell/prefetch/OfflineCacheUpdateParent.h65
-rw-r--r--system/docshell/prefetch/POfflineCacheUpdate.ipdl27
-rw-r--r--system/docshell/prefetch/moz.build44
-rw-r--r--system/docshell/prefetch/nsCPrefetchService.h52
-rw-r--r--system/docshell/prefetch/nsIOfflineCacheUpdate.idl292
-rw-r--r--system/docshell/prefetch/nsIPrefetchService.idl37
-rw-r--r--system/docshell/prefetch/nsOfflineCacheUpdate.cpp2479
-rw-r--r--system/docshell/prefetch/nsOfflineCacheUpdate.h380
-rw-r--r--system/docshell/prefetch/nsOfflineCacheUpdateService.cpp706
-rw-r--r--system/docshell/prefetch/nsPrefetchService.cpp931
-rw-r--r--system/docshell/prefetch/nsPrefetchService.h121
18 files changed, 1 insertions, 6360 deletions
diff --git a/system/docshell/build/moz.build b/system/docshell/build/moz.build
index 82cef31a5..c5acdb900 100644
--- a/system/docshell/build/moz.build
+++ b/system/docshell/build/moz.build
@@ -13,7 +13,7 @@ SOURCES += [
LOCAL_INCLUDES += [
'../base',
- '../prefetch',
+ '/components/prefetch',
'/components/shistory/src',
'/components/uriloader',
'/system/network/exthandler',
diff --git a/system/docshell/moz.build b/system/docshell/moz.build
index 37e00e4ae..69f1c8be1 100644
--- a/system/docshell/moz.build
+++ b/system/docshell/moz.build
@@ -6,7 +6,6 @@
DIRS += [
'base',
'build',
- 'prefetch',
'resources/content',
]
diff --git a/system/docshell/prefetch/OfflineCacheUpdateChild.cpp b/system/docshell/prefetch/OfflineCacheUpdateChild.cpp
deleted file mode 100644
index 555508c37..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateChild.cpp
+++ /dev/null
@@ -1,528 +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 "BackgroundUtils.h"
-#include "OfflineCacheUpdateChild.h"
-#include "nsOfflineCacheUpdate.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/TabChild.h"
-#include "mozilla/ipc/URIUtils.h"
-#include "mozilla/net/NeckoCommon.h"
-
-#include "nsIApplicationCacheContainer.h"
-#include "nsIApplicationCacheChannel.h"
-#include "nsIApplicationCacheService.h"
-#include "nsIDocShell.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeOwner.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDOMOfflineResourceList.h"
-#include "nsIDocument.h"
-#include "nsIObserverService.h"
-#include "nsIURL.h"
-#include "nsITabChild.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStreamUtils.h"
-#include "nsThreadUtils.h"
-#include "nsProxyRelease.h"
-#include "mozilla/Logging.h"
-#include "nsIAsyncVerifyRedirectCallback.h"
-
-using namespace mozilla::ipc;
-using namespace mozilla::net;
-using mozilla::dom::TabChild;
-using mozilla::dom::ContentChild;
-
-//
-// 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(nsIDOMDocument *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).
- nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
- if (!document)
- return;
-
- nsIChannel* channel = document->GetChannel();
- nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
- do_QueryInterface(channel);
- if (!appCacheChannel)
- return;
-
- bool loadedFromAppCache;
- appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
- if (loadedFromAppCache)
- return;
-
- mDocument = aDocument;
-}
-
-nsresult
-OfflineCacheUpdateChild::AssociateDocument(nsIDOMDocument *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<nsIApplicationCacheContainer> container =
- do_QueryInterface(aDocument);
- if (!container)
- return NS_OK;
-
- nsCOMPtr<nsIApplicationCache> existingCache;
- nsresult rv = container->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 = container->SetApplicationCache(aApplicationCache);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// OfflineCacheUpdateChild::nsIOfflineCacheUpdate
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-OfflineCacheUpdateChild::Init(nsIURI *aManifestURI,
- nsIURI *aDocumentURI,
- nsIPrincipal *aLoadingPrincipal,
- nsIDOMDocument *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.
- bool match;
- rv = aManifestURI->SchemeIs("http", &match);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!match) {
- rv = aManifestURI->SchemeIs("https", &match);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!match)
- 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)
-{
- NS_NOTREACHED("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)
-{
- NS_NOTREACHED("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 = nsIDOMOfflineResourceList::CHECKING;
- return NS_OK;
- case STATE_DOWNLOADING :
- *aStatus = nsIDOMOfflineResourceList::DOWNLOADING;
- return NS_OK;
- default :
- *aStatus = nsIDOMOfflineResourceList::IDLE;
- return NS_OK;
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-OfflineCacheUpdateChild::GetPartial(bool *aPartial)
-{
- *aPartial = false;
- 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) {
- nsCOMPtr<nsIWeakReference> 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 = mWindow.forget();
- nsCOMPtr<nsIDocShell >docshell = window->GetDocShell();
- if (!docshell) {
- NS_WARNING("doc shell tree item is null");
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsITabChild> tabchild = docshell->GetTabChild();
- // because owner implements nsITabChild, we can assume that it is
- // the one and only TabChild.
- TabChild* child = tabchild ? static_cast<TabChild*>(tabchild.get()) : nullptr;
-
- if (MissingRequiredTabChild(child, "offlinecacheupdate")) {
- return NS_ERROR_FAILURE;
- }
-
- URIParams manifestURI, documentURI;
- SerializeURI(mManifestURI, manifestURI);
- SerializeURI(mDocumentURI, documentURI);
-
- 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;
-
- // Need to addref ourself here, because the IPC stack doesn't hold
- // a reference to us. Will be released in RecvFinish() that identifies
- // the work has been done.
- ContentChild::GetSingleton()->SendPOfflineCacheUpdateConstructor(
- this, manifestURI, documentURI, loadingPrincipalInfo,
- stickDocument);
-
- // ContentChild::DeallocPOfflineCacheUpdate will release this.
- NS_ADDREF_THIS();
-
- return NS_OK;
-}
-
-bool
-OfflineCacheUpdateChild::RecvAssociateDocuments(const nsCString &cacheGroupId,
- const nsCString &cacheClientId)
-{
- LOG(("OfflineCacheUpdateChild::RecvAssociateDocuments [%p, cache=%s]", this, cacheClientId.get()));
-
- nsresult rv;
-
- nsCOMPtr<nsIApplicationCache> cache =
- do_CreateInstance(NS_APPLICATIONCACHE_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return true;
-
- 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 true;
-}
-
-bool
-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 true;
-}
-
-bool
-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().
- // TabChild::DeallocPOfflineCacheUpdate will call Release.
- OfflineCacheUpdateChild::Send__delete__(this);
-
- return true;
-}
-
-} // namespace docshell
-} // namespace mozilla
diff --git a/system/docshell/prefetch/OfflineCacheUpdateChild.h b/system/docshell/prefetch/OfflineCacheUpdateChild.h
deleted file mode 100644
index 89d1e6f1f..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateChild.h
+++ /dev/null
@@ -1,94 +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/. */
-
-#ifndef nsOfflineCacheUpdateChild_h
-#define nsOfflineCacheUpdateChild_h
-
-#include "mozilla/docshell/POfflineCacheUpdateChild.h"
-#include "nsIOfflineCacheUpdate.h"
-
-#include "nsCOMArray.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMDocument.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsIURI.h"
-#include "nsString.h"
-#include "nsWeakReference.h"
-
-class nsPIDOMWindowInner;
-
-namespace mozilla {
-namespace docshell {
-
-class OfflineCacheUpdateChild : public nsIOfflineCacheUpdate
- , public POfflineCacheUpdateChild
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOFFLINECACHEUPDATE
-
- virtual bool
- RecvNotifyStateEvent(const uint32_t& stateEvent,
- const uint64_t& byteProgress) override;
-
- virtual bool
- RecvAssociateDocuments(
- const nsCString& cacheGroupId,
- const nsCString& cacheClientId) override;
-
- virtual bool
- RecvFinish(const bool& succeeded,
- const bool& isUpgrade) override;
-
- explicit OfflineCacheUpdateChild(nsPIDOMWindowInner* aWindow);
-
- void SetDocument(nsIDOMDocument *aDocument);
-
-private:
- ~OfflineCacheUpdateChild();
-
- nsresult AssociateDocument(nsIDOMDocument *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<nsIObserverService> mObserverService;
-
- /* Clients watching this update for changes */
- nsCOMArray<nsIWeakReference> mWeakObservers;
- nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
-
- /* Document that requested this update */
- nsCOMPtr<nsIDOMDocument> 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
diff --git a/system/docshell/prefetch/OfflineCacheUpdateGlue.cpp b/system/docshell/prefetch/OfflineCacheUpdateGlue.cpp
deleted file mode 100644
index 71ca986ff..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateGlue.cpp
+++ /dev/null
@@ -1,228 +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 "OfflineCacheUpdateGlue.h"
-#include "nsOfflineCacheUpdate.h"
-#include "mozilla/Services.h"
-
-#include "nsIApplicationCache.h"
-#include "nsIApplicationCacheChannel.h"
-#include "nsIApplicationCacheContainer.h"
-#include "nsIChannel.h"
-#include "nsIDocument.h"
-#include "mozilla/Logging.h"
-
-//
-// 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()));
- }
-
- 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,
- nsIDOMDocument *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;
- }
-
- return mUpdate->Init(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
- aCustomProfileDir);
-}
-
-void
-OfflineCacheUpdateGlue::SetDocument(nsIDOMDocument *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).
- nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
- if (!document)
- return;
-
- nsIChannel* channel = document->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.
- nsCOMPtr<nsIApplicationCacheContainer> container =
- do_QueryInterface(mDocument);
- if (!container)
- return NS_OK;
-
- nsCOMPtr<nsIApplicationCache> existingCache;
- nsresult rv = container->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 = container->SetApplicationCache(aApplicationCache);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-} // namespace docshell
-} // namespace mozilla
diff --git a/system/docshell/prefetch/OfflineCacheUpdateGlue.h b/system/docshell/prefetch/OfflineCacheUpdateGlue.h
deleted file mode 100644
index 92201ec82..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateGlue.h
+++ /dev/null
@@ -1,80 +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/. */
-
-#ifndef nsOfflineCacheUpdateGlue_h
-#define nsOfflineCacheUpdateGlue_h
-
-#include "nsIOfflineCacheUpdate.h"
-
-#include "nsCOMPtr.h"
-#include "nsAutoPtr.h"
-#include "nsString.h"
-#include "nsWeakReference.h"
-#include "mozilla/Attributes.h"
-
-class nsOfflineCacheUpdate;
-
-namespace mozilla {
-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 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) override { return !_to ? NS_ERROR_NULL_POINTER : _to->InitPartial(aManifestURI, aClientID, aDocumentURI, aLoadingPrincipal); } \
- 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,
- nsIDOMDocument *aDocument,
- nsIFile *aCustomProfileDir) override;
-
- NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
-
- OfflineCacheUpdateGlue();
-
- void SetDocument(nsIDOMDocument *aDocument);
-
-private:
- ~OfflineCacheUpdateGlue();
-
- RefPtr<nsOfflineCacheUpdate> mUpdate;
- bool mCoalesced;
-
- /* Document that requested this update */
- nsCOMPtr<nsIDOMDocument> mDocument;
- nsCOMPtr<nsIURI> mDocumentURI;
- nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
-};
-
-} // namespace docshell
-} // namespace mozilla
-
-#endif
diff --git a/system/docshell/prefetch/OfflineCacheUpdateParent.cpp b/system/docshell/prefetch/OfflineCacheUpdateParent.cpp
deleted file mode 100644
index 0381ec3f6..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateParent.cpp
+++ /dev/null
@@ -1,294 +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 "OfflineCacheUpdateParent.h"
-
-#include "BackgroundUtils.h"
-#include "mozilla/BasePrincipal.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/ipc/URIUtils.h"
-#include "mozilla/Unused.h"
-#include "nsContentUtils.h"
-#include "nsOfflineCacheUpdate.h"
-#include "nsIApplicationCache.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsNetUtil.h"
-
-using namespace mozilla::ipc;
-using mozilla::BasePrincipal;
-using mozilla::DocShellOriginAttributes;
-using mozilla::PrincipalOriginAttributes;
-using mozilla::dom::TabParent;
-
-//
-// 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(const URIParams& aManifestURI,
- const URIParams& aDocumentURI,
- const PrincipalInfo& aLoadingPrincipalInfo,
- const bool& stickDocument)
-{
- LOG(("OfflineCacheUpdateParent::RecvSchedule [%p]", this));
-
- nsresult rv;
-
- RefPtr<nsOfflineCacheUpdate> update;
- nsCOMPtr<nsIURI> manifestURI = DeserializeURI(aManifestURI);
- if (!manifestURI)
- return NS_ERROR_FAILURE;
-
- mLoadingPrincipal = PrincipalInfoToPrincipal(aLoadingPrincipalInfo, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsOfflineCacheUpdateService* service =
- nsOfflineCacheUpdateService::EnsureService();
- if (!service)
- return NS_ERROR_FAILURE;
-
- bool offlinePermissionAllowed = false;
-
- rv = service->OfflineAppAllowed(
- mLoadingPrincipal, nullptr, &offlinePermissionAllowed);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!offlinePermissionAllowed)
- return NS_ERROR_DOM_SECURITY_ERR;
-
- nsCOMPtr<nsIURI> documentURI = DeserializeURI(aDocumentURI);
- if (!documentURI)
- return NS_ERROR_FAILURE;
-
- if (!NS_SecurityCompareURIs(manifestURI, documentURI, false))
- return NS_ERROR_DOM_SECURITY_ERR;
-
- nsAutoCString originSuffix;
- rv = mLoadingPrincipal->GetOriginSuffix(originSuffix);
- NS_ENSURE_SUCCESS(rv, rv);
-
- service->FindUpdate(manifestURI,
- originSuffix,
- nullptr,
- getter_AddRefs(update));
- if (!update) {
- update = new nsOfflineCacheUpdate();
-
- // Leave aDocument argument null. Only glues and children keep
- // document instances.
- rv = update->Init(manifestURI, documentURI, mLoadingPrincipal, nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // 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) {
- nsCOMPtr<nsIURI> stickURI;
- documentURI->Clone(getter_AddRefs(stickURI));
- update->StickDocument(stickURI);
- }
-
- 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(nsIDOMElement** aElement)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-OfflineCacheUpdateParent::GetNestedFrameId(uint64_t* aId)
-{
- 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::GetIsInIsolatedMozBrowserElement(bool *aIsInIsolatedMozBrowserElement)
-{
- NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED);
- return mLoadingPrincipal->GetIsInIsolatedMozBrowserElement(aIsInIsolatedMozBrowserElement);
-}
-
-NS_IMETHODIMP
-OfflineCacheUpdateParent::GetAppId(uint32_t *aAppId)
-{
- NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED);
- return mLoadingPrincipal->GetAppId(aAppId);
-}
-
-NS_IMETHODIMP
-OfflineCacheUpdateParent::GetOriginAttributes(JS::MutableHandleValue aAttrs)
-{
- NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED);
-
- JSContext* cx = nsContentUtils::GetCurrentJSContext();
- MOZ_ASSERT(cx);
-
- nsresult rv = mLoadingPrincipal->GetOriginAttributes(cx, aAttrs);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-OfflineCacheUpdateParent::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-} // namespace docshell
-} // namespace mozilla
diff --git a/system/docshell/prefetch/OfflineCacheUpdateParent.h b/system/docshell/prefetch/OfflineCacheUpdateParent.h
deleted file mode 100644
index f6dbc1cb2..000000000
--- a/system/docshell/prefetch/OfflineCacheUpdateParent.h
+++ /dev/null
@@ -1,65 +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/. */
-
-#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 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(const URIParams& manifestURI,
- const URIParams& documentURI,
- const PrincipalInfo& loadingPrincipalInfo,
- const bool& stickDocument);
-
- void
- StopSendingMessagesToChild()
- {
- mIPCClosed = true;
- }
-
- explicit OfflineCacheUpdateParent();
-
- virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-private:
- ~OfflineCacheUpdateParent();
-
- bool mIPCClosed;
-
- nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
-};
-
-} // namespace docshell
-} // namespace mozilla
-
-#endif
diff --git a/system/docshell/prefetch/POfflineCacheUpdate.ipdl b/system/docshell/prefetch/POfflineCacheUpdate.ipdl
deleted file mode 100644
index 7f1614d81..000000000
--- a/system/docshell/prefetch/POfflineCacheUpdate.ipdl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; 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 protocol PContent;
-
-namespace mozilla {
-namespace docshell {
-
-//-------------------------------------------------------------------
-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);
-};
-
-}
-}
diff --git a/system/docshell/prefetch/moz.build b/system/docshell/prefetch/moz.build
deleted file mode 100644
index d60197953..000000000
--- a/system/docshell/prefetch/moz.build
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# 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/.
-
-XPIDL_SOURCES += [
- 'nsIOfflineCacheUpdate.idl',
- 'nsIPrefetchService.idl',
-]
-
-XPIDL_MODULE = 'prefetch'
-
-EXPORTS += [
- 'nsCPrefetchService.h',
-]
-
-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')
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '/dom/base',
-]
-
-if CONFIG['GNU_CXX']:
- CXXFLAGS += ['-Wno-error=shadow']
diff --git a/system/docshell/prefetch/nsCPrefetchService.h b/system/docshell/prefetch/nsCPrefetchService.h
deleted file mode 100644
index d74d89fe7..000000000
--- a/system/docshell/prefetch/nsCPrefetchService.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsCPrefetchService_h__
-#define nsCPrefetchService_h__
-
-#include "nsIPrefetchService.h"
-
-/**
- * nsPrefetchService : nsIPrefetchService
- */
-#define NS_PREFETCHSERVICE_CONTRACTID \
- "@mozilla.org/prefetch-service;1"
-#define NS_PREFETCHSERVICE_CID \
-{ /* 6b8bdffc-3394-417d-be83-a81b7c0f63bf */ \
- 0x6b8bdffc, \
- 0x3394, \
- 0x417d, \
- {0xbe, 0x83, 0xa8, 0x1b, 0x7c, 0x0f, 0x63, 0xbf} \
-}
-
-/**
- * nsOfflineCacheUpdateService : nsIOfflineCacheUpdateService
- */
-
-#define NS_OFFLINECACHEUPDATESERVICE_CONTRACTID \
- "@mozilla.org/offlinecacheupdate-service;1"
-#define NS_OFFLINECACHEUPDATESERVICE_CID \
-{ /* ec06f3fc-70db-4ecd-94e0-a6e91ca44d8a */ \
- 0xec06f3fc, \
- 0x70db, \
- 0x4ecd , \
- {0x94, 0xe0, 0xa6, 0xe9, 0x1c, 0xa4, 0x4d, 0x8a} \
-}
-
-/**
- * nsOfflineCacheUpdate : nsIOfflineCacheUpdate
- */
-
-#define NS_OFFLINECACHEUPDATE_CONTRACTID \
- "@mozilla.org/offlinecacheupdate;1"
-#define NS_OFFLINECACHEUPDATE_CID \
-{ /* e56f5e01-c7cc-4675-a9d7-b8f1e4127295 */ \
- 0xe56f5e01, \
- 0xc7cc, \
- 0x4675, \
- {0xa9, 0xd7, 0xb8, 0xf1, 0xe4, 0x12, 0x72, 0x95} \
-}
-
-
-#endif // !nsCPrefetchService_h__
diff --git a/system/docshell/prefetch/nsIOfflineCacheUpdate.idl b/system/docshell/prefetch/nsIOfflineCacheUpdate.idl
deleted file mode 100644
index 1308a8de2..000000000
--- a/system/docshell/prefetch/nsIOfflineCacheUpdate.idl
+++ /dev/null
@@ -1,292 +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 nsIDOMNode;
-interface nsIDOMDocument;
-interface nsIOfflineCacheUpdate;
-interface nsIPrincipal;
-interface nsIPrefBranch;
-interface nsIApplicationCache;
-interface nsIFile;
-interface nsIObserver;
-
-[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 nsIDOMOfflineResourceList.
- */
- 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;
-
- /**
- * 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 nsIDOMDocument 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.
- */
- void initPartial(in nsIURI aManifestURI, in ACString aClientID,
- in nsIURI aDocumentURI, in nsIPrincipal aPrincipal);
-
- /**
- * 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,
- 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+inIsolatedMozBrowser 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 nsIDOMDocument 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.
- * @param aPrefBranch
- * The pref branch to use to check the
- * offline-apps.allow_by_default pref. If not specified,
- * the pref service will be used.
- */
- boolean offlineAppAllowed(in nsIPrincipal aPrincipal,
- in nsIPrefBranch aPrefBranch);
-
- /**
- * Checks whether a document at the given URI should have access
- * to the offline cache.
- * @param aURI
- * The URI to check
- * @param aPrefBranch
- * The pref branch to use to check the
- * offline-apps.allow_by_default pref. If not specified,
- * the pref service will be used.
- */
- boolean offlineAppAllowedForURI(in nsIURI aURI,
- in nsIPrefBranch aPrefBranch);
-
- /**
- * 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);
-};
diff --git a/system/docshell/prefetch/nsIPrefetchService.idl b/system/docshell/prefetch/nsIPrefetchService.idl
deleted file mode 100644
index 198320dd2..000000000
--- a/system/docshell/prefetch/nsIPrefetchService.idl
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIURI;
-interface nsIDOMNode;
-interface nsISimpleEnumerator;
-
-[scriptable, uuid(422a1807-4e7f-463d-b8d7-ca2ceb9b5d53)]
-interface nsIPrefetchService : nsISupports
-{
- /**
- * Enqueue a request to prefetch the specified URI.
- *
- * @param aURI the URI of the document to prefetch
- * @param aReferrerURI the URI of the referring page
- * @param aSource the DOM node (such as a <link> tag) that requested this
- * fetch, or null if the prefetch was not requested by a DOM node.
- * @param aExplicit the link element has an explicit prefetch link type
- */
- void prefetchURI(in nsIURI aURI,
- in nsIURI aReferrerURI,
- in nsIDOMNode aSource,
- in boolean aExplicit);
-
- /**
- * Find out if there are any prefetches running or queued
- */
- boolean hasMoreElements();
-
- /**
- * Cancel prefetch
- */
- void cancelPrefetchURI(in nsIURI aURI, in nsIDOMNode aSource);
-};
diff --git a/system/docshell/prefetch/nsOfflineCacheUpdate.cpp b/system/docshell/prefetch/nsOfflineCacheUpdate.cpp
deleted file mode 100644
index 8a4183429..000000000
--- a/system/docshell/prefetch/nsOfflineCacheUpdate.cpp
+++ /dev/null
@@ -1,2479 +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 "nsOfflineCacheUpdate.h"
-
-#include "nsCPrefetchService.h"
-#include "nsCURILoader.h"
-#include "nsIApplicationCacheContainer.h"
-#include "nsIApplicationCacheChannel.h"
-#include "nsIApplicationCacheService.h"
-#include "nsICachingChannel.h"
-#include "nsIContent.h"
-#include "mozilla/dom/Element.h"
-#include "nsIDocumentLoader.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMWindow.h"
-#include "nsIDOMOfflineResourceList.h"
-#include "nsIDocument.h"
-#include "nsIObserverService.h"
-#include "nsIURL.h"
-#include "nsIWebProgress.h"
-#include "nsICryptoHash.h"
-#include "nsICacheEntry.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 "nsIConsoleService.h"
-#include "mozilla/Logging.h"
-#include "nsIAsyncVerifyRedirectCallback.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Attributes.h"
-#include "nsContentUtils.h"
-#include "nsIPrincipal.h"
-
-#include "nsXULAppAPI.h"
-
-using namespace mozilla;
-
-static const uint32_t kRescheduleLimit = 3;
-// Max number of retries for every entry of pinned app.
-static const uint32_t kPinnedEntryRetriesLimit = 3;
-// Maximum number of parallel items loads
-static const uint32_t kParallelLoadLimit = 15;
-
-// Quota for offline apps when preloading
-static const int32_t kCustomProfileQuota = 512000;
-
-//
-// 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 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)
-
-class AutoFreeArray {
-public:
- AutoFreeArray(uint32_t count, char **values)
- : mCount(count), mValues(values) {};
- ~AutoFreeArray() { NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mValues); }
-private:
- uint32_t mCount;
- char **mValues;
-};
-
-namespace {
-
-nsresult
-DropReferenceFromURL(nsIURI * aURI)
-{
- // XXXdholbert If this SetRef fails, callers of this method probably
- // want to call aURI->CloneIgnoringRef() and use the result of that.
- return aURI->SetRef(EmptyCString());
-}
-
-void
-LogToConsole(const char * message, nsOfflineCacheUpdateItem * item = nullptr)
-{
- nsCOMPtr<nsIConsoleService> consoleService =
- do_GetService(NS_CONSOLESERVICE_CONTRACTID);
- if (consoleService)
- {
- nsAutoString messageUTF16 = NS_ConvertUTF8toUTF16(message);
- if (item && item->mURI) {
- messageUTF16.AppendLiteral(", URL=");
- messageUTF16.Append(
- NS_ConvertUTF8toUTF16(item->mURI->GetSpecOrDefault()));
- }
- consoleService->LogStringMessage(messageUTF16.get());
- }
-}
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck
-//-----------------------------------------------------------------------------
-
-class nsManifestCheck final : public nsIStreamListener
- , public nsIChannelEventSink
- , public nsIInterfaceRequestor
-{
-public:
- nsManifestCheck(nsOfflineCacheUpdate *aUpdate,
- nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIPrincipal* aLoadingPrincipal)
- : mUpdate(aUpdate)
- , mURI(aURI)
- , mReferrerURI(aReferrerURI)
- , mLoadingPrincipal(aLoadingPrincipal)
- {}
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIREQUESTOBSERVER
- NS_DECL_NSISTREAMLISTENER
- NS_DECL_NSICHANNELEVENTSINK
- NS_DECL_NSIINTERFACEREQUESTOR
-
- nsresult Begin();
-
-private:
-
- ~nsManifestCheck() {}
-
- static nsresult ReadManifest(nsIInputStream *aInputStream,
- void *aClosure,
- const char *aFromSegment,
- uint32_t aOffset,
- uint32_t aCount,
- uint32_t *aBytesConsumed);
-
- RefPtr<nsOfflineCacheUpdate> mUpdate;
- nsCOMPtr<nsIURI> mURI;
- nsCOMPtr<nsIURI> mReferrerURI;
- nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
- nsCOMPtr<nsICryptoHash> mManifestHash;
- nsCOMPtr<nsIChannel> mChannel;
-};
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck::nsISupports
-//-----------------------------------------------------------------------------
-NS_IMPL_ISUPPORTS(nsManifestCheck,
- nsIRequestObserver,
- nsIStreamListener,
- nsIChannelEventSink,
- nsIInterfaceRequestor)
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck <public>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsManifestCheck::Begin()
-{
- nsresult rv;
- mManifestHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = mManifestHash->Init(nsICryptoHash::MD5);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = NS_NewChannel(getter_AddRefs(mChannel),
- mURI,
- mLoadingPrincipal,
- nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
- nsIContentPolicy::TYPE_OTHER,
- nullptr, // loadGroup
- nullptr, // aCallbacks
- nsIRequest::LOAD_BYPASS_CACHE);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // configure HTTP specific stuff
- nsCOMPtr<nsIHttpChannel> httpChannel =
- do_QueryInterface(mChannel);
- if (httpChannel) {
- httpChannel->SetReferrer(mReferrerURI);
- httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
- NS_LITERAL_CSTRING("offline-resource"),
- false);
- }
-
- return mChannel->AsyncOpen2(this);
-}
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck <public>
-//-----------------------------------------------------------------------------
-
-/* static */ nsresult
-nsManifestCheck::ReadManifest(nsIInputStream *aInputStream,
- void *aClosure,
- const char *aFromSegment,
- uint32_t aOffset,
- uint32_t aCount,
- uint32_t *aBytesConsumed)
-{
- nsManifestCheck *manifestCheck =
- static_cast<nsManifestCheck*>(aClosure);
-
- nsresult rv;
- *aBytesConsumed = aCount;
-
- rv = manifestCheck->mManifestHash->Update(
- reinterpret_cast<const uint8_t *>(aFromSegment), aCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck::nsIStreamListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsManifestCheck::OnStartRequest(nsIRequest *aRequest,
- nsISupports *aContext)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsManifestCheck::OnDataAvailable(nsIRequest *aRequest,
- nsISupports *aContext,
- nsIInputStream *aStream,
- uint64_t aOffset,
- uint32_t aCount)
-{
- uint32_t bytesRead;
- aStream->ReadSegments(ReadManifest, this, aCount, &bytesRead);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsManifestCheck::OnStopRequest(nsIRequest *aRequest,
- nsISupports *aContext,
- nsresult aStatus)
-{
- nsAutoCString manifestHash;
- if (NS_SUCCEEDED(aStatus)) {
- mManifestHash->Finish(true, manifestHash);
- }
-
- mUpdate->ManifestCheckCompleted(aStatus, manifestHash);
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck::nsIInterfaceRequestor
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsManifestCheck::GetInterface(const nsIID &aIID, void **aResult)
-{
- if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
- NS_ADDREF_THIS();
- *aResult = static_cast<nsIChannelEventSink *>(this);
- return NS_OK;
- }
-
- return NS_ERROR_NO_INTERFACE;
-}
-
-//-----------------------------------------------------------------------------
-// nsManifestCheck::nsIChannelEventSink
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsManifestCheck::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
- nsIChannel *aNewChannel,
- uint32_t aFlags,
- nsIAsyncVerifyRedirectCallback *callback)
-{
- // Redirects should cause the load (and therefore the update) to fail.
- if (aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
- callback->OnRedirectVerifyCallback(NS_OK);
- return NS_OK;
- }
-
- LogToConsole("Manifest check failed because its response is a redirect");
-
- aOldChannel->Cancel(NS_ERROR_ABORT);
- return NS_ERROR_ABORT;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ISUPPORTS(nsOfflineCacheUpdateItem,
- nsIRequestObserver,
- nsIStreamListener,
- nsIRunnable,
- nsIInterfaceRequestor,
- nsIChannelEventSink)
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem <public>
-//-----------------------------------------------------------------------------
-
-nsOfflineCacheUpdateItem::nsOfflineCacheUpdateItem(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIPrincipal* aLoadingPrincipal,
- nsIApplicationCache *aApplicationCache,
- nsIApplicationCache *aPreviousApplicationCache,
- uint32_t type,
- uint32_t loadFlags)
- : mURI(aURI)
- , mReferrerURI(aReferrerURI)
- , mLoadingPrincipal(aLoadingPrincipal)
- , mApplicationCache(aApplicationCache)
- , mPreviousApplicationCache(aPreviousApplicationCache)
- , mItemType(type)
- , mLoadFlags(loadFlags)
- , mChannel(nullptr)
- , mState(LoadStatus::UNINITIALIZED)
- , mBytesRead(0)
-{
-}
-
-nsOfflineCacheUpdateItem::~nsOfflineCacheUpdateItem()
-{
-}
-
-nsresult
-nsOfflineCacheUpdateItem::OpenChannel(nsOfflineCacheUpdate *aUpdate)
-{
- if (LOG_ENABLED()) {
- LOG(("%p: Opening channel for %s", this,
- mURI->GetSpecOrDefault().get()));
- }
-
- if (mUpdate) {
- // Holding a reference to the update means this item is already
- // in progress (has a channel, or is just in between OnStopRequest()
- // and its Run() call. We must never open channel on this item again.
- LOG((" %p is already running! ignoring", this));
- return NS_ERROR_ALREADY_OPENED;
- }
-
- nsresult rv = nsOfflineCacheUpdate::GetCacheKey(mURI, mCacheKey);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t flags = nsIRequest::LOAD_BACKGROUND |
- nsICachingChannel::LOAD_ONLY_IF_MODIFIED;
-
- if (mApplicationCache == mPreviousApplicationCache) {
- // Same app cache to read from and to write to is used during
- // an only-update-check procedure. Here we protect the existing
- // cache from being modified.
- flags |= nsIRequest::INHIBIT_CACHING;
- }
-
- flags |= mLoadFlags;
-
- rv = NS_NewChannel(getter_AddRefs(mChannel),
- mURI,
- mLoadingPrincipal,
- nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
- nsIContentPolicy::TYPE_OTHER,
- nullptr, // aLoadGroup
- this, // aCallbacks
- flags);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
- do_QueryInterface(mChannel, &rv);
-
- // Support for nsIApplicationCacheChannel is required.
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Use the existing application cache as the cache to check.
- rv = appCacheChannel->SetApplicationCache(mPreviousApplicationCache);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Set the new application cache as the target for write.
- rv = appCacheChannel->SetApplicationCacheForWrite(mApplicationCache);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // configure HTTP specific stuff
- nsCOMPtr<nsIHttpChannel> httpChannel =
- do_QueryInterface(mChannel);
- if (httpChannel) {
- httpChannel->SetReferrer(mReferrerURI);
- httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
- NS_LITERAL_CSTRING("offline-resource"),
- false);
- }
-
- rv = mChannel->AsyncOpen2(this);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mUpdate = aUpdate;
-
- mState = LoadStatus::REQUESTED;
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdateItem::Cancel()
-{
- if (mChannel) {
- mChannel->Cancel(NS_ERROR_ABORT);
- mChannel = nullptr;
- }
-
- mState = LoadStatus::UNINITIALIZED;
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem::nsIStreamListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::OnStartRequest(nsIRequest *aRequest,
- nsISupports *aContext)
-{
- mState = LoadStatus::RECEIVING;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::OnDataAvailable(nsIRequest *aRequest,
- nsISupports *aContext,
- nsIInputStream *aStream,
- uint64_t aOffset,
- uint32_t aCount)
-{
- uint32_t bytesRead = 0;
- aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &bytesRead);
- mBytesRead += bytesRead;
- LOG(("loaded %u bytes into offline cache [offset=%llu]\n",
- bytesRead, aOffset));
-
- mUpdate->OnByteProgress(bytesRead);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::OnStopRequest(nsIRequest *aRequest,
- nsISupports *aContext,
- nsresult aStatus)
-{
- if (LOG_ENABLED()) {
- LOG(("%p: Done fetching offline item %s [status=%x]\n",
- this, mURI->GetSpecOrDefault().get(), aStatus));
- }
-
- if (mBytesRead == 0 && aStatus == NS_OK) {
- // we didn't need to read (because LOAD_ONLY_IF_MODIFIED was
- // specified), but the object should report loadedSize as if it
- // did.
- mChannel->GetContentLength(&mBytesRead);
- mUpdate->OnByteProgress(mBytesRead);
- }
-
- if (NS_FAILED(aStatus)) {
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
- if (httpChannel) {
- bool isNoStore;
- if (NS_SUCCEEDED(httpChannel->IsNoStoreResponse(&isNoStore))
- && isNoStore) {
- LogToConsole("Offline cache manifest item has Cache-control: no-store header",
- this);
- }
- }
- }
-
- // We need to notify the update that the load is complete, but we
- // want to give the channel a chance to close the cache entries.
- NS_DispatchToCurrentThread(this);
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem::nsIRunnable
-//-----------------------------------------------------------------------------
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::Run()
-{
- // Set mState to LOADED here rather than in OnStopRequest to prevent
- // race condition when checking state of all mItems in ProcessNextURI().
- // If state would have been set in OnStopRequest we could mistakenly
- // take this item as already finished and finish the update process too
- // early when ProcessNextURI() would get called between OnStopRequest()
- // and Run() of this item. Finish() would then have been called twice.
- mState = LoadStatus::LOADED;
-
- RefPtr<nsOfflineCacheUpdate> update;
- update.swap(mUpdate);
- update->LoadCompleted(this);
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem::nsIInterfaceRequestor
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::GetInterface(const nsIID &aIID, void **aResult)
-{
- if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
- NS_ADDREF_THIS();
- *aResult = static_cast<nsIChannelEventSink *>(this);
- return NS_OK;
- }
-
- return NS_ERROR_NO_INTERFACE;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdateItem::nsIChannelEventSink
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateItem::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
- nsIChannel *aNewChannel,
- uint32_t aFlags,
- nsIAsyncVerifyRedirectCallback *cb)
-{
- if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
- // Don't allow redirect in case of non-internal redirect and cancel
- // the channel to clean the cache entry.
- LogToConsole("Offline cache manifest failed because an item redirects", this);
-
- aOldChannel->Cancel(NS_ERROR_ABORT);
- return NS_ERROR_ABORT;
- }
-
- nsCOMPtr<nsIURI> newURI;
- nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI));
- if (NS_FAILED(rv))
- return rv;
-
- nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
- do_QueryInterface(aNewChannel);
- if (appCacheChannel) {
- rv = appCacheChannel->SetApplicationCacheForWrite(mApplicationCache);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsAutoCString oldScheme;
- mURI->GetScheme(oldScheme);
-
- bool match;
- if (NS_FAILED(newURI->SchemeIs(oldScheme.get(), &match)) || !match) {
- LOG(("rejected: redirected to a different scheme\n"));
- return NS_ERROR_ABORT;
- }
-
- // HTTP request headers are not automatically forwarded to the new channel.
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aNewChannel);
- NS_ENSURE_STATE(httpChannel);
-
- httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
- NS_LITERAL_CSTRING("offline-resource"),
- false);
-
- mChannel = aNewChannel;
-
- cb->OnRedirectVerifyCallback(NS_OK);
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdateItem::GetRequestSucceeded(bool * succeeded)
-{
- *succeeded = false;
-
- if (!mChannel)
- return NS_OK;
-
- nsresult rv;
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool reqSucceeded;
- rv = httpChannel->GetRequestSucceeded(&reqSucceeded);
- if (NS_ERROR_NOT_AVAILABLE == rv)
- return NS_OK;
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!reqSucceeded) {
- LOG(("Request failed"));
- return NS_OK;
- }
-
- nsresult channelStatus;
- rv = httpChannel->GetStatus(&channelStatus);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (NS_FAILED(channelStatus)) {
- LOG(("Channel status=0x%08x", channelStatus));
- return NS_OK;
- }
-
- *succeeded = true;
- return NS_OK;
-}
-
-bool
-nsOfflineCacheUpdateItem::IsScheduled()
-{
- return mState == LoadStatus::UNINITIALIZED;
-}
-
-bool
-nsOfflineCacheUpdateItem::IsInProgress()
-{
- return mState == LoadStatus::REQUESTED ||
- mState == LoadStatus::RECEIVING;
-}
-
-bool
-nsOfflineCacheUpdateItem::IsCompleted()
-{
- return mState == LoadStatus::LOADED;
-}
-
-nsresult
-nsOfflineCacheUpdateItem::GetStatus(uint16_t *aStatus)
-{
- if (!mChannel) {
- *aStatus = 0;
- return NS_OK;
- }
-
- nsresult rv;
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t httpStatus;
- rv = httpChannel->GetResponseStatus(&httpStatus);
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- *aStatus = 0;
- return NS_OK;
- }
-
- NS_ENSURE_SUCCESS(rv, rv);
- *aStatus = uint16_t(httpStatus);
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineManifestItem
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// nsOfflineManifestItem <public>
-//-----------------------------------------------------------------------------
-
-nsOfflineManifestItem::nsOfflineManifestItem(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIPrincipal* aLoadingPrincipal,
- nsIApplicationCache *aApplicationCache,
- nsIApplicationCache *aPreviousApplicationCache)
- : nsOfflineCacheUpdateItem(aURI, aReferrerURI, aLoadingPrincipal,
- aApplicationCache, aPreviousApplicationCache,
- nsIApplicationCache::ITEM_MANIFEST, 0)
- , mParserState(PARSE_INIT)
- , mNeedsUpdate(true)
- , mStrictFileOriginPolicy(false)
- , mManifestHashInitialized(false)
-{
- ReadStrictFileOriginPolicyPref();
-}
-
-nsOfflineManifestItem::~nsOfflineManifestItem()
-{
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineManifestItem <private>
-//-----------------------------------------------------------------------------
-
-/* static */
-nsresult
-nsOfflineManifestItem::ReadManifest(nsIInputStream *aInputStream,
- void *aClosure,
- const char *aFromSegment,
- uint32_t aOffset,
- uint32_t aCount,
- uint32_t *aBytesConsumed)
-{
- nsOfflineManifestItem *manifest =
- static_cast<nsOfflineManifestItem*>(aClosure);
-
- nsresult rv;
-
- *aBytesConsumed = aCount;
-
- if (manifest->mParserState == PARSE_ERROR) {
- // parse already failed, ignore this
- return NS_OK;
- }
-
- if (!manifest->mManifestHashInitialized) {
- // Avoid re-creation of crypto hash when it fails from some reason the first time
- manifest->mManifestHashInitialized = true;
-
- manifest->mManifestHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
- if (NS_SUCCEEDED(rv)) {
- rv = manifest->mManifestHash->Init(nsICryptoHash::MD5);
- if (NS_FAILED(rv)) {
- manifest->mManifestHash = nullptr;
- LOG(("Could not initialize manifest hash for byte-to-byte check, rv=%08x", rv));
- }
- }
- }
-
- if (manifest->mManifestHash) {
- rv = manifest->mManifestHash->Update(reinterpret_cast<const uint8_t *>(aFromSegment), aCount);
- if (NS_FAILED(rv)) {
- manifest->mManifestHash = nullptr;
- LOG(("Could not update manifest hash, rv=%08x", rv));
- }
- }
-
- manifest->mReadBuf.Append(aFromSegment, aCount);
-
- nsCString::const_iterator begin, iter, end;
- manifest->mReadBuf.BeginReading(begin);
- manifest->mReadBuf.EndReading(end);
-
- for (iter = begin; iter != end; iter++) {
- if (*iter == '\r' || *iter == '\n') {
- rv = manifest->HandleManifestLine(begin, iter);
-
- if (NS_FAILED(rv)) {
- LOG(("HandleManifestLine failed with 0x%08x", rv));
- *aBytesConsumed = 0; // Avoid assertion failure in stream tee
- return NS_ERROR_ABORT;
- }
-
- begin = iter;
- begin++;
- }
- }
-
- // any leftovers are saved for next time
- manifest->mReadBuf = Substring(begin, end);
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineManifestItem::AddNamespace(uint32_t namespaceType,
- const nsCString &namespaceSpec,
- const nsCString &data)
-
-{
- nsresult rv;
- if (!mNamespaces) {
- mNamespaces = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIApplicationCacheNamespace> ns =
- do_CreateInstance(NS_APPLICATIONCACHENAMESPACE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = ns->Init(namespaceType, namespaceSpec, data);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = mNamespaces->AppendElement(ns, false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegin,
- const nsCString::const_iterator &aEnd)
-{
- nsCString::const_iterator begin = aBegin;
- nsCString::const_iterator end = aEnd;
-
- // all lines ignore trailing spaces and tabs
- nsCString::const_iterator last = end;
- --last;
- while (end != begin && (*last == ' ' || *last == '\t')) {
- --end;
- --last;
- }
-
- if (mParserState == PARSE_INIT) {
- // Allow a UTF-8 BOM
- if (begin != end && static_cast<unsigned char>(*begin) == 0xef) {
- if (++begin == end || static_cast<unsigned char>(*begin) != 0xbb ||
- ++begin == end || static_cast<unsigned char>(*begin) != 0xbf) {
- mParserState = PARSE_ERROR;
- LogToConsole("Offline cache manifest BOM error", this);
- return NS_OK;
- }
- ++begin;
- }
-
- const nsCSubstring &magic = Substring(begin, end);
-
- if (!magic.EqualsLiteral("CACHE MANIFEST")) {
- mParserState = PARSE_ERROR;
- LogToConsole("Offline cache manifest magic incorrect", this);
- return NS_OK;
- }
-
- mParserState = PARSE_CACHE_ENTRIES;
- return NS_OK;
- }
-
- // lines other than the first ignore leading spaces and tabs
- while (begin != end && (*begin == ' ' || *begin == '\t'))
- begin++;
-
- // ignore blank lines and comments
- if (begin == end || *begin == '#')
- return NS_OK;
-
- const nsCSubstring &line = Substring(begin, end);
-
- if (line.EqualsLiteral("CACHE:")) {
- mParserState = PARSE_CACHE_ENTRIES;
- return NS_OK;
- }
-
- if (line.EqualsLiteral("FALLBACK:")) {
- mParserState = PARSE_FALLBACK_ENTRIES;
- return NS_OK;
- }
-
- if (line.EqualsLiteral("NETWORK:")) {
- mParserState = PARSE_BYPASS_ENTRIES;
- return NS_OK;
- }
-
- // Every other section type we don't know must be silently ignored.
- nsCString::const_iterator lastChar = end;
- if (*(--lastChar) == ':') {
- mParserState = PARSE_UNKNOWN_SECTION;
- return NS_OK;
- }
-
- nsresult rv;
-
- switch(mParserState) {
- case PARSE_INIT:
- case PARSE_ERROR: {
- // this should have been dealt with earlier
- return NS_ERROR_FAILURE;
- }
-
- case PARSE_UNKNOWN_SECTION: {
- // just jump over
- return NS_OK;
- }
-
- case PARSE_CACHE_ENTRIES: {
- nsCOMPtr<nsIURI> uri;
- rv = NS_NewURI(getter_AddRefs(uri), line, nullptr, mURI);
- if (NS_FAILED(rv))
- break;
- if (NS_FAILED(DropReferenceFromURL(uri)))
- break;
-
- nsAutoCString scheme;
- uri->GetScheme(scheme);
-
- // Manifest URIs must have the same scheme as the manifest.
- bool match;
- if (NS_FAILED(mURI->SchemeIs(scheme.get(), &match)) || !match)
- break;
-
- mExplicitURIs.AppendObject(uri);
-
- if (!NS_SecurityCompareURIs(mURI, uri,
- mStrictFileOriginPolicy)) {
- mAnonymousURIs.AppendObject(uri);
- }
-
- break;
- }
-
- case PARSE_FALLBACK_ENTRIES: {
- int32_t separator = line.FindChar(' ');
- if (separator == kNotFound) {
- separator = line.FindChar('\t');
- if (separator == kNotFound)
- break;
- }
-
- nsCString namespaceSpec(Substring(line, 0, separator));
- nsCString fallbackSpec(Substring(line, separator + 1));
- namespaceSpec.CompressWhitespace();
- fallbackSpec.CompressWhitespace();
-
- nsCOMPtr<nsIURI> namespaceURI;
- rv = NS_NewURI(getter_AddRefs(namespaceURI), namespaceSpec, nullptr, mURI);
- if (NS_FAILED(rv))
- break;
- if (NS_FAILED(DropReferenceFromURL(namespaceURI)))
- break;
- rv = namespaceURI->GetAsciiSpec(namespaceSpec);
- if (NS_FAILED(rv))
- break;
-
- nsCOMPtr<nsIURI> fallbackURI;
- rv = NS_NewURI(getter_AddRefs(fallbackURI), fallbackSpec, nullptr, mURI);
- if (NS_FAILED(rv))
- break;
- if (NS_FAILED(DropReferenceFromURL(fallbackURI)))
- break;
- rv = fallbackURI->GetAsciiSpec(fallbackSpec);
- if (NS_FAILED(rv))
- break;
-
- // Manifest and namespace must be same origin
- if (!NS_SecurityCompareURIs(mURI, namespaceURI,
- mStrictFileOriginPolicy))
- break;
-
- // Fallback and namespace must be same origin
- if (!NS_SecurityCompareURIs(namespaceURI, fallbackURI,
- mStrictFileOriginPolicy))
- break;
-
- // Check fallback path for disallowed encoded path separators
- nsAutoCString path;
- fallbackURI->GetFilePath(path);
- if (path.Find("%2f") != kNotFound || path.Find("%2F") != kNotFound) {
- LogToConsole("Offline cache manifest bad fallback path", this);
- break;
- }
-
- mFallbackURIs.AppendObject(fallbackURI);
-
- AddNamespace(nsIApplicationCacheNamespace::NAMESPACE_FALLBACK,
- namespaceSpec, fallbackSpec);
- break;
- }
-
- case PARSE_BYPASS_ENTRIES: {
- if (line[0] == '*' && (line.Length() == 1 || line[1] == ' ' || line[1] == '\t'))
- {
- // '*' indicates to make the online whitelist wildcard flag open,
- // i.e. do allow load of resources not present in the offline cache
- // or not conforming any namespace.
- // We achive that simply by adding an 'empty' - i.e. universal
- // namespace of BYPASS type into the cache.
- AddNamespace(nsIApplicationCacheNamespace::NAMESPACE_BYPASS,
- EmptyCString(), EmptyCString());
- break;
- }
-
- nsCOMPtr<nsIURI> bypassURI;
- rv = NS_NewURI(getter_AddRefs(bypassURI), line, nullptr, mURI);
- if (NS_FAILED(rv))
- break;
-
- nsAutoCString scheme;
- bypassURI->GetScheme(scheme);
- bool equals;
- if (NS_FAILED(mURI->SchemeIs(scheme.get(), &equals)) || !equals)
- break;
- if (NS_FAILED(DropReferenceFromURL(bypassURI)))
- break;
- nsCString spec;
- if (NS_FAILED(bypassURI->GetAsciiSpec(spec)))
- break;
-
- AddNamespace(nsIApplicationCacheNamespace::NAMESPACE_BYPASS,
- spec, EmptyCString());
- break;
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineManifestItem::GetOldManifestContentHash(nsIRequest *aRequest)
-{
- nsresult rv;
-
- nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aRequest, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // load the main cache token that is actually the old offline cache token and
- // read previous manifest content hash value
- nsCOMPtr<nsISupports> cacheToken;
- cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
- if (cacheToken) {
- nsCOMPtr<nsICacheEntry> cacheDescriptor(do_QueryInterface(cacheToken, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheDescriptor->GetMetaDataElement("offline-manifest-hash", getter_Copies(mOldManifestHashValue));
- if (NS_FAILED(rv))
- mOldManifestHashValue.Truncate();
- }
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineManifestItem::CheckNewManifestContentHash(nsIRequest *aRequest)
-{
- nsresult rv;
-
- if (!mManifestHash) {
- // Nothing to compare against...
- return NS_OK;
- }
-
- nsCString newManifestHashValue;
- rv = mManifestHash->Finish(true, mManifestHashValue);
- mManifestHash = nullptr;
-
- if (NS_FAILED(rv)) {
- LOG(("Could not finish manifest hash, rv=%08x", rv));
- // This is not critical error
- return NS_OK;
- }
-
- if (!ParseSucceeded()) {
- // Parsing failed, the hash is not valid
- return NS_OK;
- }
-
- if (mOldManifestHashValue == mManifestHashValue) {
- LOG(("Update not needed, downloaded manifest content is byte-for-byte identical"));
- mNeedsUpdate = false;
- }
-
- // Store the manifest content hash value to the new
- // offline cache token
- nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aRequest, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsISupports> cacheToken;
- cachingChannel->GetOfflineCacheToken(getter_AddRefs(cacheToken));
- if (cacheToken) {
- nsCOMPtr<nsICacheEntry> cacheDescriptor(do_QueryInterface(cacheToken, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheDescriptor->SetMetaDataElement("offline-manifest-hash", mManifestHashValue.get());
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-void
-nsOfflineManifestItem::ReadStrictFileOriginPolicyPref()
-{
- mStrictFileOriginPolicy =
- Preferences::GetBool("security.fileuri.strict_origin_policy", true);
-}
-
-NS_IMETHODIMP
-nsOfflineManifestItem::OnStartRequest(nsIRequest *aRequest,
- nsISupports *aContext)
-{
- nsresult rv;
-
- nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool succeeded;
- rv = channel->GetRequestSucceeded(&succeeded);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!succeeded) {
- LOG(("HTTP request failed"));
- LogToConsole("Offline cache manifest HTTP request failed", this);
- mParserState = PARSE_ERROR;
- return NS_ERROR_ABORT;
- }
-
- rv = GetOldManifestContentHash(aRequest);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return nsOfflineCacheUpdateItem::OnStartRequest(aRequest, aContext);
-}
-
-NS_IMETHODIMP
-nsOfflineManifestItem::OnDataAvailable(nsIRequest *aRequest,
- nsISupports *aContext,
- nsIInputStream *aStream,
- uint64_t aOffset,
- uint32_t aCount)
-{
- uint32_t bytesRead = 0;
- aStream->ReadSegments(ReadManifest, this, aCount, &bytesRead);
- mBytesRead += bytesRead;
-
- if (mParserState == PARSE_ERROR) {
- LOG(("OnDataAvailable is canceling the request due a parse error\n"));
- return NS_ERROR_ABORT;
- }
-
- LOG(("loaded %u bytes into offline cache [offset=%u]\n",
- bytesRead, aOffset));
-
- // All the parent method does is read and discard, don't bother
- // chaining up.
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineManifestItem::OnStopRequest(nsIRequest *aRequest,
- nsISupports *aContext,
- nsresult aStatus)
-{
- if (mBytesRead == 0) {
- // We didn't need to read (because LOAD_ONLY_IF_MODIFIED was
- // specified).
- mNeedsUpdate = false;
- } else {
- // Handle any leftover manifest data.
- nsCString::const_iterator begin, end;
- mReadBuf.BeginReading(begin);
- mReadBuf.EndReading(end);
- nsresult rv = HandleManifestLine(begin, end);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = CheckNewManifestContentHash(aRequest);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return nsOfflineCacheUpdateItem::OnStopRequest(aRequest, aContext, aStatus);
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdate::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ISUPPORTS(nsOfflineCacheUpdate,
- nsIOfflineCacheUpdateObserver,
- nsIOfflineCacheUpdate,
- nsIRunnable)
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdate <public>
-//-----------------------------------------------------------------------------
-
-nsOfflineCacheUpdate::nsOfflineCacheUpdate()
- : mState(STATE_UNINITIALIZED)
- , mAddedItems(false)
- , mPartialUpdate(false)
- , mOnlyCheckUpdate(false)
- , mSucceeded(true)
- , mObsolete(false)
- , mItemsInProgress(0)
- , mRescheduleCount(0)
- , mPinnedEntryRetriesCount(0)
- , mPinned(false)
- , mByteProgress(0)
-{
-}
-
-nsOfflineCacheUpdate::~nsOfflineCacheUpdate()
-{
- LOG(("nsOfflineCacheUpdate::~nsOfflineCacheUpdate [%p]", this));
-}
-
-/* static */
-nsresult
-nsOfflineCacheUpdate::GetCacheKey(nsIURI *aURI, nsACString &aKey)
-{
- aKey.Truncate();
-
- nsCOMPtr<nsIURI> newURI;
- nsresult rv = aURI->CloneIgnoringRef(getter_AddRefs(newURI));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = newURI->GetAsciiSpec(aKey);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::InitInternal(nsIURI *aManifestURI,
- nsIPrincipal* aLoadingPrincipal)
-{
- nsresult rv;
-
- // Only http and https applications are supported.
- bool match;
- rv = aManifestURI->SchemeIs("http", &match);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!match) {
- rv = aManifestURI->SchemeIs("https", &match);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!match)
- return NS_ERROR_ABORT;
- }
-
- mManifestURI = aManifestURI;
- mLoadingPrincipal = aLoadingPrincipal;
-
- rv = mManifestURI->GetAsciiHost(mUpdateDomain);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mPartialUpdate = false;
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
- nsIURI *aDocumentURI,
- nsIPrincipal* aLoadingPrincipal,
- nsIDOMDocument *aDocument,
- nsIFile *aCustomProfileDir)
-{
- nsresult rv;
-
- // Make sure the service has been initialized
- nsOfflineCacheUpdateService* service =
- nsOfflineCacheUpdateService::EnsureService();
- if (!service)
- return NS_ERROR_FAILURE;
-
- LOG(("nsOfflineCacheUpdate::Init [%p]", this));
-
- rv = InitInternal(aManifestURI, aLoadingPrincipal);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIApplicationCacheService> cacheService =
- do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString originSuffix;
- rv = aLoadingPrincipal->GetOriginSuffix(originSuffix);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mDocumentURI = aDocumentURI;
-
- if (aCustomProfileDir) {
- rv = cacheService->BuildGroupIDForSuffix(aManifestURI, originSuffix, mGroupID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Create only a new offline application cache in the custom profile
- // This is a preload of a new cache.
-
- // XXX Custom updates don't support "updating" of an existing cache
- // in the custom profile at the moment. This support can be, though,
- // simply added as well when needed.
- mPreviousApplicationCache = nullptr;
-
- rv = cacheService->CreateCustomApplicationCache(mGroupID,
- aCustomProfileDir,
- kCustomProfileQuota,
- getter_AddRefs(mApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
-
- mCustomProfileDir = aCustomProfileDir;
- }
- else {
- rv = cacheService->BuildGroupIDForSuffix(aManifestURI, originSuffix, mGroupID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->GetActiveCache(mGroupID,
- getter_AddRefs(mPreviousApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->CreateApplicationCache(mGroupID,
- getter_AddRefs(mApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aDocumentURI,
- nullptr,
- &mPinned);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mState = STATE_INITIALIZED;
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::InitForUpdateCheck(nsIURI *aManifestURI,
- nsIPrincipal* aLoadingPrincipal,
- nsIObserver *aObserver)
-{
- nsresult rv;
-
- // Make sure the service has been initialized
- nsOfflineCacheUpdateService* service =
- nsOfflineCacheUpdateService::EnsureService();
- if (!service)
- return NS_ERROR_FAILURE;
-
- LOG(("nsOfflineCacheUpdate::InitForUpdateCheck [%p]", this));
-
- rv = InitInternal(aManifestURI, aLoadingPrincipal);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIApplicationCacheService> cacheService =
- do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString originSuffix;
- rv = aLoadingPrincipal->GetOriginSuffix(originSuffix);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->BuildGroupIDForSuffix(aManifestURI, originSuffix, mGroupID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->GetActiveCache(mGroupID,
- getter_AddRefs(mPreviousApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // To load the manifest properly using current app cache to satisfy and
- // also to compare the cached content hash value we have to set 'some'
- // app cache to write to on the channel. Otherwise the cached version will
- // be used and no actual network request will be made. We use the same
- // app cache here. OpenChannel prevents caching in this case using
- // INHIBIT_CACHING load flag.
- mApplicationCache = mPreviousApplicationCache;
-
- rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aManifestURI,
- nullptr,
- &mPinned);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mUpdateAvailableObserver = aObserver;
- mOnlyCheckUpdate = true;
-
- mState = STATE_INITIALIZED;
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::InitPartial(nsIURI *aManifestURI,
- const nsACString& clientID,
- nsIURI *aDocumentURI,
- nsIPrincipal *aLoadingPrincipal)
-{
- nsresult rv;
-
- // Make sure the service has been initialized
- nsOfflineCacheUpdateService* service =
- nsOfflineCacheUpdateService::EnsureService();
- if (!service)
- return NS_ERROR_FAILURE;
-
- LOG(("nsOfflineCacheUpdate::InitPartial [%p]", this));
-
- mPartialUpdate = true;
- mDocumentURI = aDocumentURI;
- mLoadingPrincipal = aLoadingPrincipal;
-
- mManifestURI = aManifestURI;
- rv = mManifestURI->GetAsciiHost(mUpdateDomain);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIApplicationCacheService> cacheService =
- do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->GetApplicationCache(clientID,
- getter_AddRefs(mApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!mApplicationCache) {
- nsAutoCString manifestSpec;
- rv = GetCacheKey(mManifestURI, manifestSpec);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = cacheService->CreateApplicationCache
- (manifestSpec, getter_AddRefs(mApplicationCache));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = mApplicationCache->GetManifestURI(getter_AddRefs(mManifestURI));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString groupID;
- rv = mApplicationCache->GetGroupID(groupID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aDocumentURI,
- nullptr,
- &mPinned);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mState = STATE_INITIALIZED;
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::HandleManifest(bool *aDoUpdate)
-{
- // Be pessimistic
- *aDoUpdate = false;
-
- bool succeeded;
- nsresult rv = mManifestItem->GetRequestSucceeded(&succeeded);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!succeeded || !mManifestItem->ParseSucceeded()) {
- return NS_ERROR_FAILURE;
- }
-
- if (!mManifestItem->NeedsUpdate()) {
- return NS_OK;
- }
-
- // Add items requested by the manifest.
- const nsCOMArray<nsIURI> &manifestURIs = mManifestItem->GetExplicitURIs();
- for (int32_t i = 0; i < manifestURIs.Count(); i++) {
- rv = AddURI(manifestURIs[i], nsIApplicationCache::ITEM_EXPLICIT);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- const nsCOMArray<nsIURI> &anonURIs = mManifestItem->GetAnonymousURIs();
- for (int32_t i = 0; i < anonURIs.Count(); i++) {
- rv = AddURI(anonURIs[i], nsIApplicationCache::ITEM_EXPLICIT,
- nsIRequest::LOAD_ANONYMOUS);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- const nsCOMArray<nsIURI> &fallbackURIs = mManifestItem->GetFallbackURIs();
- for (int32_t i = 0; i < fallbackURIs.Count(); i++) {
- rv = AddURI(fallbackURIs[i], nsIApplicationCache::ITEM_FALLBACK);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // The document that requested the manifest is implicitly included
- // as part of that manifest update.
- rv = AddURI(mDocumentURI, nsIApplicationCache::ITEM_IMPLICIT);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Add items previously cached implicitly
- rv = AddExistingItems(nsIApplicationCache::ITEM_IMPLICIT);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Add items requested by the script API
- rv = AddExistingItems(nsIApplicationCache::ITEM_DYNAMIC);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Add opportunistically cached items conforming current opportunistic
- // namespace list
- rv = AddExistingItems(nsIApplicationCache::ITEM_OPPORTUNISTIC,
- &mManifestItem->GetOpportunisticNamespaces());
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aDoUpdate = true;
-
- return NS_OK;
-}
-
-bool
-nsOfflineCacheUpdate::CheckUpdateAvailability()
-{
- nsresult rv;
-
- bool succeeded;
- rv = mManifestItem->GetRequestSucceeded(&succeeded);
- NS_ENSURE_SUCCESS(rv, false);
-
- if (!succeeded || !mManifestItem->ParseSucceeded()) {
- return false;
- }
-
- if (!mPinned) {
- uint16_t status;
- rv = mManifestItem->GetStatus(&status);
- NS_ENSURE_SUCCESS(rv, false);
-
- // Treat these as there would be an update available,
- // since this is indication of demand to remove this
- // offline cache.
- if (status == 404 || status == 410) {
- return true;
- }
- }
-
- return mManifestItem->NeedsUpdate();
-}
-
-void
-nsOfflineCacheUpdate::LoadCompleted(nsOfflineCacheUpdateItem *aItem)
-{
- nsresult rv;
-
- LOG(("nsOfflineCacheUpdate::LoadCompleted [%p]", this));
-
- if (mState == STATE_FINISHED) {
- LOG((" after completion, ignoring"));
- return;
- }
-
- // Keep the object alive through a Finish() call.
- nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
-
- if (mState == STATE_CANCELLED) {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- if (mState == STATE_CHECKING) {
- // Manifest load finished.
-
- if (mOnlyCheckUpdate) {
- Finish();
- NotifyUpdateAvailability(CheckUpdateAvailability());
- return;
- }
-
- NS_ASSERTION(mManifestItem,
- "Must have a manifest item in STATE_CHECKING.");
- NS_ASSERTION(mManifestItem == aItem,
- "Unexpected aItem in nsOfflineCacheUpdate::LoadCompleted");
-
- // A 404 or 410 is interpreted as an intentional removal of
- // the manifest file, rather than a transient server error.
- // Obsolete this cache group if one of these is returned.
- uint16_t status;
- rv = mManifestItem->GetStatus(&status);
- if (status == 404 || status == 410) {
- LogToConsole("Offline cache manifest removed, cache cleared", mManifestItem);
- mSucceeded = false;
- if (mPreviousApplicationCache) {
- if (mPinned) {
- // Do not obsolete a pinned application.
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_NOUPDATE);
- } else {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_OBSOLETE);
- mObsolete = true;
- }
- } else {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- mObsolete = true;
- }
- Finish();
- return;
- }
-
- bool doUpdate;
- if (NS_FAILED(HandleManifest(&doUpdate))) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- if (!doUpdate) {
- LogToConsole("Offline cache doesn't need to update", mManifestItem);
-
- mSucceeded = false;
-
- AssociateDocuments(mPreviousApplicationCache);
-
- ScheduleImplicit();
-
- // If we didn't need an implicit update, we can
- // send noupdate and end the update now.
- if (!mImplicitUpdate) {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_NOUPDATE);
- Finish();
- }
- return;
- }
-
- rv = mApplicationCache->MarkEntry(mManifestItem->mCacheKey,
- mManifestItem->mItemType);
- if (NS_FAILED(rv)) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- mState = STATE_DOWNLOADING;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING);
-
- // Start fetching resources.
- ProcessNextURI();
-
- return;
- }
-
- // Normal load finished.
- if (mItemsInProgress) // Just to be safe here!
- --mItemsInProgress;
-
- bool succeeded;
- rv = aItem->GetRequestSucceeded(&succeeded);
-
- if (mPinned && NS_SUCCEEDED(rv) && succeeded) {
- uint32_t dummy_cache_type;
- rv = mApplicationCache->GetTypes(aItem->mCacheKey, &dummy_cache_type);
- bool item_doomed = NS_FAILED(rv); // can not find it? -> doomed
-
- if (item_doomed &&
- mPinnedEntryRetriesCount < kPinnedEntryRetriesLimit &&
- (aItem->mItemType & (nsIApplicationCache::ITEM_EXPLICIT |
- nsIApplicationCache::ITEM_FALLBACK))) {
- rv = EvictOneNonPinned();
- if (NS_FAILED(rv)) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- // This reverts the item state to UNINITIALIZED that makes it to
- // be scheduled for download again.
- rv = aItem->Cancel();
- if (NS_FAILED(rv)) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- mPinnedEntryRetriesCount++;
-
- LogToConsole("An unpinned offline cache deleted");
-
- // Retry this item.
- ProcessNextURI();
- return;
- }
- }
-
- // According to parallelism this may imply more pinned retries count,
- // but that is not critical, since at one moment the algoritm will
- // stop anyway. Also, this code may soon be completely removed
- // after we have a separate storage for pinned apps.
- mPinnedEntryRetriesCount = 0;
-
- // Check for failures. 3XX, 4XX and 5XX errors on items explicitly
- // listed in the manifest will cause the update to fail.
- if (NS_FAILED(rv) || !succeeded) {
- if (aItem->mItemType &
- (nsIApplicationCache::ITEM_EXPLICIT |
- nsIApplicationCache::ITEM_FALLBACK)) {
- LogToConsole("Offline cache manifest item failed to load", aItem);
- mSucceeded = false;
- }
- } else {
- rv = mApplicationCache->MarkEntry(aItem->mCacheKey, aItem->mItemType);
- if (NS_FAILED(rv)) {
- mSucceeded = false;
- }
- }
-
- if (!mSucceeded) {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- Finish();
- return;
- }
-
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ITEMCOMPLETED);
-
- ProcessNextURI();
-}
-
-void
-nsOfflineCacheUpdate::ManifestCheckCompleted(nsresult aStatus,
- const nsCString &aManifestHash)
-{
- // Keep the object alive through a Finish() call.
- nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
-
- if (NS_SUCCEEDED(aStatus)) {
- nsAutoCString firstManifestHash;
- mManifestItem->GetManifestHash(firstManifestHash);
- if (aManifestHash != firstManifestHash) {
- LOG(("Manifest has changed during cache items download [%p]", this));
- LogToConsole("Offline cache manifest changed during update", mManifestItem);
- aStatus = NS_ERROR_FAILURE;
- }
- }
-
- if (NS_FAILED(aStatus)) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- }
-
- if (NS_FAILED(aStatus) && mRescheduleCount < kRescheduleLimit) {
- // Do the final stuff but prevent notification of STATE_FINISHED.
- // That would disconnect listeners that are responsible for document
- // association after a successful update. Forwarding notifications
- // from a new update through this dead update to them is absolutely
- // correct.
- FinishNoNotify();
-
- RefPtr<nsOfflineCacheUpdate> newUpdate =
- new nsOfflineCacheUpdate();
- // Leave aDocument argument null. Only glues and children keep
- // document instances.
- newUpdate->Init(mManifestURI, mDocumentURI, mLoadingPrincipal, nullptr,
- mCustomProfileDir);
-
- // In a rare case the manifest will not be modified on the next refetch
- // transfer all master document URIs to the new update to ensure that
- // all documents refering it will be properly cached.
- for (int32_t i = 0; i < mDocumentURIs.Count(); i++) {
- newUpdate->StickDocument(mDocumentURIs[i]);
- }
-
- newUpdate->mRescheduleCount = mRescheduleCount + 1;
- newUpdate->AddObserver(this, false);
- newUpdate->Schedule();
- }
- else {
- LogToConsole("Offline cache update done", mManifestItem);
- Finish();
- }
-}
-
-nsresult
-nsOfflineCacheUpdate::Begin()
-{
- LOG(("nsOfflineCacheUpdate::Begin [%p]", this));
-
- // Keep the object alive through a ProcessNextURI()/Finish() call.
- nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
-
- mItemsInProgress = 0;
-
- if (mState == STATE_CANCELLED) {
- nsresult rv = NS_DispatchToMainThread(NewRunnableMethod(this,
- &nsOfflineCacheUpdate::AsyncFinishWithError));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
- }
-
- if (mPartialUpdate) {
- mState = STATE_DOWNLOADING;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING);
- ProcessNextURI();
- return NS_OK;
- }
-
- // Start checking the manifest.
- mManifestItem = new nsOfflineManifestItem(mManifestURI,
- mDocumentURI,
- mLoadingPrincipal,
- mApplicationCache,
- mPreviousApplicationCache);
- if (!mManifestItem) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- mState = STATE_CHECKING;
- mByteProgress = 0;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_CHECKING);
-
- nsresult rv = mManifestItem->OpenChannel(this);
- if (NS_FAILED(rv)) {
- LoadCompleted(mManifestItem);
- }
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdate <private>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsOfflineCacheUpdate::AddExistingItems(uint32_t aType,
- nsTArray<nsCString>* namespaceFilter)
-{
- if (!mPreviousApplicationCache) {
- return NS_OK;
- }
-
- if (namespaceFilter && namespaceFilter->Length() == 0) {
- // Don't bother to walk entries when there are no namespaces
- // defined.
- return NS_OK;
- }
-
- uint32_t count = 0;
- char **keys = nullptr;
- nsresult rv = mPreviousApplicationCache->GatherEntries(aType,
- &count, &keys);
- NS_ENSURE_SUCCESS(rv, rv);
-
- AutoFreeArray autoFree(count, keys);
-
- for (uint32_t i = 0; i < count; i++) {
- if (namespaceFilter) {
- bool found = false;
- for (uint32_t j = 0; j < namespaceFilter->Length() && !found; j++) {
- found = StringBeginsWith(nsDependentCString(keys[i]),
- namespaceFilter->ElementAt(j));
- }
-
- if (!found)
- continue;
- }
-
- nsCOMPtr<nsIURI> uri;
- if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), keys[i]))) {
- rv = AddURI(uri, aType);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::ProcessNextURI()
-{
- // Keep the object alive through a Finish() call.
- nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
-
- LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p, inprogress=%d, numItems=%d]",
- this, mItemsInProgress, mItems.Length()));
-
- if (mState != STATE_DOWNLOADING) {
- LOG((" should only be called from the DOWNLOADING state, ignoring"));
- return NS_ERROR_UNEXPECTED;
- }
-
- nsOfflineCacheUpdateItem * runItem = nullptr;
- uint32_t completedItems = 0;
- for (uint32_t i = 0; i < mItems.Length(); ++i) {
- nsOfflineCacheUpdateItem * item = mItems[i];
-
- if (item->IsScheduled()) {
- runItem = item;
- break;
- }
-
- if (item->IsCompleted())
- ++completedItems;
- }
-
- if (completedItems == mItems.Length()) {
- LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p]: all items loaded", this));
-
- if (mPartialUpdate) {
- return Finish();
- } else {
- // Verify that the manifest wasn't changed during the
- // update, to prevent capturing a cache while the server
- // is being updated. The check will call
- // ManifestCheckCompleted() when it's done.
- RefPtr<nsManifestCheck> manifestCheck =
- new nsManifestCheck(this, mManifestURI, mDocumentURI, mLoadingPrincipal);
- if (NS_FAILED(manifestCheck->Begin())) {
- mSucceeded = false;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- return Finish();
- }
-
- return NS_OK;
- }
- }
-
- if (!runItem) {
- LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p]:"
- " No more items to include in parallel load", this));
- return NS_OK;
- }
-
- if (LOG_ENABLED()) {
- LOG(("%p: Opening channel for %s", this,
- runItem->mURI->GetSpecOrDefault().get()));
- }
-
- ++mItemsInProgress;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ITEMSTARTED);
-
- nsresult rv = runItem->OpenChannel(this);
- if (NS_FAILED(rv)) {
- LoadCompleted(runItem);
- return rv;
- }
-
- if (mItemsInProgress >= kParallelLoadLimit) {
- LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p]:"
- " At parallel load limit", this));
- return NS_OK;
- }
-
- // This calls this method again via a post triggering
- // a parallel item load
- return NS_DispatchToCurrentThread(this);
-}
-
-void
-nsOfflineCacheUpdate::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
-nsOfflineCacheUpdate::NotifyState(uint32_t state)
-{
- LOG(("nsOfflineCacheUpdate::NotifyState [%p, %d]", this, state));
-
- if (state == STATE_ERROR) {
- LogToConsole("Offline cache update error", mManifestItem);
- }
-
- nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
- GatherObservers(observers);
-
- for (int32_t i = 0; i < observers.Count(); i++) {
- observers[i]->UpdateStateChanged(this, state);
- }
-}
-
-void
-nsOfflineCacheUpdate::NotifyUpdateAvailability(bool updateAvailable)
-{
- if (!mUpdateAvailableObserver)
- return;
-
- LOG(("nsOfflineCacheUpdate::NotifyUpdateAvailability [this=%p, avail=%d]",
- this, updateAvailable));
-
- const char* topic = updateAvailable
- ? "offline-cache-update-available"
- : "offline-cache-update-unavailable";
-
- nsCOMPtr<nsIObserver> observer;
- observer.swap(mUpdateAvailableObserver);
- observer->Observe(mManifestURI, topic, nullptr);
-}
-
-void
-nsOfflineCacheUpdate::AssociateDocuments(nsIApplicationCache* cache)
-{
- if (!cache) {
- LOG(("nsOfflineCacheUpdate::AssociateDocuments bypassed"
- ", no cache provided [this=%p]", this));
- return;
- }
-
- nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
- GatherObservers(observers);
-
- for (int32_t i = 0; i < observers.Count(); i++) {
- observers[i]->ApplicationCacheAvailable(cache);
- }
-}
-
-void
-nsOfflineCacheUpdate::StickDocument(nsIURI *aDocumentURI)
-{
- if (!aDocumentURI)
- return;
-
- mDocumentURIs.AppendObject(aDocumentURI);
-}
-
-void
-nsOfflineCacheUpdate::SetOwner(nsOfflineCacheUpdateOwner *aOwner)
-{
- NS_ASSERTION(!mOwner, "Tried to set cache update owner twice.");
- mOwner = aOwner;
-}
-
-bool
-nsOfflineCacheUpdate::IsForGroupID(const nsCSubstring &groupID)
-{
- return mGroupID == groupID;
-}
-
-bool
-nsOfflineCacheUpdate::IsForProfile(nsIFile* aCustomProfileDir)
-{
- if (!mCustomProfileDir && !aCustomProfileDir)
- return true;
- if (!mCustomProfileDir || !aCustomProfileDir)
- return false;
-
- bool equals;
- nsresult rv = mCustomProfileDir->Equals(aCustomProfileDir, &equals);
-
- return NS_SUCCEEDED(rv) && equals;
-}
-
-nsresult
-nsOfflineCacheUpdate::UpdateFinished(nsOfflineCacheUpdate *aUpdate)
-{
- // Keep the object alive through a Finish() call.
- nsCOMPtr<nsIOfflineCacheUpdate> kungFuDeathGrip(this);
-
- mImplicitUpdate = nullptr;
-
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_NOUPDATE);
- Finish();
-
- return NS_OK;
-}
-
-void
-nsOfflineCacheUpdate::OnByteProgress(uint64_t byteIncrement)
-{
- mByteProgress += byteIncrement;
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ITEMPROGRESS);
-}
-
-nsresult
-nsOfflineCacheUpdate::ScheduleImplicit()
-{
- if (mDocumentURIs.Count() == 0)
- return NS_OK;
-
- nsresult rv;
-
- RefPtr<nsOfflineCacheUpdate> update = new nsOfflineCacheUpdate();
- NS_ENSURE_TRUE(update, NS_ERROR_OUT_OF_MEMORY);
-
- nsAutoCString clientID;
- if (mPreviousApplicationCache) {
- rv = mPreviousApplicationCache->GetClientID(clientID);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- else if (mApplicationCache) {
- rv = mApplicationCache->GetClientID(clientID);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- else {
- NS_ERROR("Offline cache update not having set mApplicationCache?");
- }
-
- rv = update->InitPartial(mManifestURI, clientID, mDocumentURI, mLoadingPrincipal);
- NS_ENSURE_SUCCESS(rv, rv);
-
- for (int32_t i = 0; i < mDocumentURIs.Count(); i++) {
- rv = update->AddURI(mDocumentURIs[i],
- nsIApplicationCache::ITEM_IMPLICIT);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- update->SetOwner(this);
- rv = update->Begin();
- NS_ENSURE_SUCCESS(rv, rv);
-
- mImplicitUpdate = update;
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::FinishNoNotify()
-{
- LOG(("nsOfflineCacheUpdate::Finish [%p]", this));
-
- mState = STATE_FINISHED;
-
- if (!mPartialUpdate && !mOnlyCheckUpdate) {
- if (mSucceeded) {
- nsIArray *namespaces = mManifestItem->GetNamespaces();
- nsresult rv = mApplicationCache->AddNamespaces(namespaces);
- if (NS_FAILED(rv)) {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- mSucceeded = false;
- }
-
- rv = mApplicationCache->Activate();
- if (NS_FAILED(rv)) {
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_ERROR);
- mSucceeded = false;
- }
-
- AssociateDocuments(mApplicationCache);
- }
-
- if (mObsolete) {
- nsCOMPtr<nsIApplicationCacheService> appCacheService =
- do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
- if (appCacheService) {
- nsAutoCString groupID;
- mApplicationCache->GetGroupID(groupID);
- appCacheService->DeactivateGroup(groupID);
- }
- }
-
- if (!mSucceeded) {
- // Update was not merged, mark all the loads as failures
- for (uint32_t i = 0; i < mItems.Length(); i++) {
- mItems[i]->Cancel();
- }
-
- mApplicationCache->Discard();
- }
- }
-
- nsresult rv = NS_OK;
-
- if (mOwner) {
- rv = mOwner->UpdateFinished(this);
- // mozilla::WeakPtr is missing some key features, like setting it to
- // null explicitly.
- mOwner = mozilla::WeakPtr<nsOfflineCacheUpdateOwner>();
- }
-
- return rv;
-}
-
-nsresult
-nsOfflineCacheUpdate::Finish()
-{
- nsresult rv = FinishNoNotify();
-
- NotifyState(nsIOfflineCacheUpdateObserver::STATE_FINISHED);
-
- return rv;
-}
-
-void
-nsOfflineCacheUpdate::AsyncFinishWithError()
-{
- NotifyState(nsOfflineCacheUpdate::STATE_ERROR);
- Finish();
-}
-
-static nsresult
-EvictOneOfCacheGroups(nsIApplicationCacheService *cacheService,
- uint32_t count, const char * const *groups)
-{
- nsresult rv;
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- nsCOMPtr<nsIURI> uri;
- rv = NS_NewURI(getter_AddRefs(uri), groups[i]);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsDependentCString group_name(groups[i]);
- nsCOMPtr<nsIApplicationCache> cache;
- rv = cacheService->GetActiveCache(group_name, getter_AddRefs(cache));
- // Maybe someone in another thread or process have deleted it.
- if (NS_FAILED(rv) || !cache)
- continue;
-
- bool pinned;
- rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(uri,
- nullptr,
- &pinned);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!pinned) {
- rv = cache->Discard();
- return NS_OK;
- }
- }
-
- return NS_ERROR_FILE_NOT_FOUND;
-}
-
-nsresult
-nsOfflineCacheUpdate::EvictOneNonPinned()
-{
- nsresult rv;
-
- nsCOMPtr<nsIApplicationCacheService> cacheService =
- do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t count;
- char **groups;
- rv = cacheService->GetGroupsTimeOrdered(&count, &groups);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = EvictOneOfCacheGroups(cacheService, count, groups);
-
- NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, groups);
- return rv;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdate::nsIOfflineCacheUpdate
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetUpdateDomain(nsACString &aUpdateDomain)
-{
- NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
-
- aUpdateDomain = mUpdateDomain;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetStatus(uint16_t *aStatus)
-{
- switch (mState) {
- case STATE_CHECKING :
- *aStatus = nsIDOMOfflineResourceList::CHECKING;
- return NS_OK;
- case STATE_DOWNLOADING :
- *aStatus = nsIDOMOfflineResourceList::DOWNLOADING;
- return NS_OK;
- default :
- *aStatus = nsIDOMOfflineResourceList::IDLE;
- return NS_OK;
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetPartial(bool *aPartial)
-{
- *aPartial = mPartialUpdate || mOnlyCheckUpdate;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetManifestURI(nsIURI **aManifestURI)
-{
- NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
-
- NS_IF_ADDREF(*aManifestURI = mManifestURI);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetSucceeded(bool *aSucceeded)
-{
- NS_ENSURE_TRUE(mState == STATE_FINISHED, NS_ERROR_NOT_AVAILABLE);
-
- *aSucceeded = mSucceeded;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::GetIsUpgrade(bool *aIsUpgrade)
-{
- NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
-
- *aIsUpgrade = (mPreviousApplicationCache != nullptr);
-
- return NS_OK;
-}
-
-nsresult
-nsOfflineCacheUpdate::AddURI(nsIURI *aURI, uint32_t aType, uint32_t aLoadFlags)
-{
- NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
-
- if (mState >= STATE_DOWNLOADING)
- return NS_ERROR_NOT_AVAILABLE;
-
- // Resource URIs must have the same scheme as the manifest.
- nsAutoCString scheme;
- aURI->GetScheme(scheme);
-
- bool match;
- if (NS_FAILED(mManifestURI->SchemeIs(scheme.get(), &match)) || !match)
- return NS_ERROR_FAILURE;
-
- // Don't fetch the same URI twice.
- for (uint32_t i = 0; i < mItems.Length(); i++) {
- bool equals;
- if (NS_SUCCEEDED(mItems[i]->mURI->Equals(aURI, &equals)) && equals &&
- mItems[i]->mLoadFlags == aLoadFlags) {
- // retain both types.
- mItems[i]->mItemType |= aType;
- return NS_OK;
- }
- }
-
- RefPtr<nsOfflineCacheUpdateItem> item =
- new nsOfflineCacheUpdateItem(aURI,
- mDocumentURI,
- mLoadingPrincipal,
- mApplicationCache,
- mPreviousApplicationCache,
- aType,
- aLoadFlags);
- if (!item) return NS_ERROR_OUT_OF_MEMORY;
-
- mItems.AppendElement(item);
- mAddedItems = true;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::AddDynamicURI(nsIURI *aURI)
-{
- if (GeckoProcessType_Default != XRE_GetProcessType())
- return NS_ERROR_NOT_IMPLEMENTED;
-
- // If this is a partial update and the resource is already in the
- // cache, we should only mark the entry, not fetch it again.
- if (mPartialUpdate) {
- nsAutoCString key;
- GetCacheKey(aURI, key);
-
- uint32_t types;
- nsresult rv = mApplicationCache->GetTypes(key, &types);
- if (NS_SUCCEEDED(rv)) {
- if (!(types & nsIApplicationCache::ITEM_DYNAMIC)) {
- mApplicationCache->MarkEntry
- (key, nsIApplicationCache::ITEM_DYNAMIC);
- }
- return NS_OK;
- }
- }
-
- return AddURI(aURI, nsIApplicationCache::ITEM_DYNAMIC);
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::Cancel()
-{
- LOG(("nsOfflineCacheUpdate::Cancel [%p]", this));
-
- if ((mState == STATE_FINISHED) || (mState == STATE_CANCELLED)) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- mState = STATE_CANCELLED;
- mSucceeded = false;
-
- // Cancel all running downloads
- for (uint32_t i = 0; i < mItems.Length(); ++i) {
- nsOfflineCacheUpdateItem * item = mItems[i];
-
- if (item->IsInProgress())
- item->Cancel();
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::AddObserver(nsIOfflineCacheUpdateObserver *aObserver,
- bool aHoldWeak)
-{
- LOG(("nsOfflineCacheUpdate::AddObserver [%p] to update [%p]", aObserver, this));
-
- NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
-
- if (aHoldWeak) {
- nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(aObserver);
- mWeakObservers.AppendObject(weakRef);
- } else {
- mObservers.AppendObject(aObserver);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver)
-{
- LOG(("nsOfflineCacheUpdate::RemoveObserver [%p] from update [%p]", aObserver, 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
-nsOfflineCacheUpdate::GetByteProgress(uint64_t * _result)
-{
- NS_ENSURE_ARG(_result);
-
- *_result = mByteProgress;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::Schedule()
-{
- LOG(("nsOfflineCacheUpdate::Schedule [%p]", this));
-
- nsOfflineCacheUpdateService* service =
- nsOfflineCacheUpdateService::EnsureService();
-
- if (!service) {
- return NS_ERROR_FAILURE;
- }
-
- return service->ScheduleUpdate(this);
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate,
- uint32_t aState)
-{
- if (aState == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
- // Take the mSucceeded flag from the underlying update, we will be
- // queried for it soon. mSucceeded of this update is false (manifest
- // check failed) but the subsequent re-fetch update might succeed
- bool succeeded;
- aUpdate->GetSucceeded(&succeeded);
- mSucceeded = succeeded;
- }
-
- NotifyState(aState);
- if (aState == nsIOfflineCacheUpdateObserver::STATE_FINISHED)
- aUpdate->RemoveObserver(this);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::ApplicationCacheAvailable(nsIApplicationCache *applicationCache)
-{
- AssociateDocuments(applicationCache);
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsOfflineCacheUpdate::nsIRunable
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsOfflineCacheUpdate::Run()
-{
- ProcessNextURI();
- return NS_OK;
-}
diff --git a/system/docshell/prefetch/nsOfflineCacheUpdate.h b/system/docshell/prefetch/nsOfflineCacheUpdate.h
deleted file mode 100644
index 2e6d6d30c..000000000
--- a/system/docshell/prefetch/nsOfflineCacheUpdate.h
+++ /dev/null
@@ -1,380 +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/. */
-
-#ifndef nsOfflineCacheUpdate_h__
-#define nsOfflineCacheUpdate_h__
-
-#include "nsIOfflineCacheUpdate.h"
-
-#include "nsAutoPtr.h"
-#include "nsCOMArray.h"
-#include "nsCOMPtr.h"
-#include "nsIChannelEventSink.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMNode.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIMutableArray.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsIApplicationCache.h"
-#include "nsIRequestObserver.h"
-#include "nsIRunnable.h"
-#include "nsIStreamListener.h"
-#include "nsIURI.h"
-#include "nsIWebProgressListener.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 "nsTHashtable.h"
-#include "nsHashKeys.h"
-
-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<nsOfflineCacheUpdateOwner>
-{
-public:
- MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsOfflineCacheUpdateOwner)
- 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 nsCSubstring &groupID);
- bool IsForProfile(nsIFile* aCustomProfileDir);
-
- virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) override;
-
-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<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,
- nsIDOMDocument *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();
-
- /** Addrefs and returns the singleton nsOfflineCacheUpdateService. */
- static nsOfflineCacheUpdateService *GetInstance();
-
- static nsresult OfflineAppPinnedForURI(nsIURI *aDocumentURI,
- nsIPrefBranch *aPrefBranch,
- bool *aPinned);
-
- static nsTHashtable<nsCStringHashKey>* AllowedDomains();
-
-private:
- ~nsOfflineCacheUpdateService();
-
- nsresult ProcessNextUpdate();
-
- nsTArray<RefPtr<nsOfflineCacheUpdate> > mUpdates;
- static nsTHashtable<nsCStringHashKey>* mAllowedDomains;
-
- bool mDisabled;
- bool mUpdateRunning;
-};
-
-#endif
diff --git a/system/docshell/prefetch/nsOfflineCacheUpdateService.cpp b/system/docshell/prefetch/nsOfflineCacheUpdateService.cpp
deleted file mode 100644
index 6a67af013..000000000
--- a/system/docshell/prefetch/nsOfflineCacheUpdateService.cpp
+++ /dev/null
@@ -1,706 +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 "OfflineCacheUpdateChild.h"
-#include "OfflineCacheUpdateParent.h"
-#include "nsXULAppAPI.h"
-#include "OfflineCacheUpdateGlue.h"
-#include "nsOfflineCacheUpdate.h"
-
-#include "nsCPrefetchService.h"
-#include "nsCURILoader.h"
-#include "nsIApplicationCacheContainer.h"
-#include "nsIApplicationCacheChannel.h"
-#include "nsIApplicationCacheService.h"
-#include "nsICachingChannel.h"
-#include "nsIContent.h"
-#include "nsIDocShell.h"
-#include "nsIDocumentLoader.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMWindow.h"
-#include "nsIDOMOfflineResourceList.h"
-#include "nsIDocument.h"
-#include "nsIObserverService.h"
-#include "nsIURL.h"
-#include "nsIWebProgress.h"
-#include "nsIWebNavigation.h"
-#include "nsICryptoHash.h"
-#include "nsIPermissionManager.h"
-#include "nsIPrincipal.h"
-#include "nsNetCID.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStreamUtils.h"
-#include "nsThreadUtils.h"
-#include "nsProxyRelease.h"
-#include "mozilla/Logging.h"
-#include "nsIAsyncVerifyRedirectCallback.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Unused.h"
-#include "nsIDocShell.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeOwner.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;
-static bool sAllowOfflineCache = true;
-
-nsTHashtable<nsCStringHashKey>* nsOfflineCacheUpdateService::mAllowedDomains = nullptr;
-
-nsTHashtable<nsCStringHashKey>* nsOfflineCacheUpdateService::AllowedDomains()
-{
- if (!mAllowedDomains)
- mAllowedDomains = new nsTHashtable<nsCStringHashKey>();
-
- 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,
- nsIDOMDocument *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;
- nsCOMPtr<nsIWeakReference> 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)
-{
- NS_NOTREACHED("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<nsIDOMDocument> 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<nsIDocument> progressDoc = outerWindow->GetDoc();
- if (!progressDoc) return NS_OK;
-
- if (!SameCOMIdentity(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)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCachePendingUpdate::OnStatusChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsresult aStatus,
- const char16_t* aMessage)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCachePendingUpdate::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- uint32_t state)
-{
- NS_NOTREACHED("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());
- Preferences::AddBoolVarCache(&sAllowOfflineCache,
- "browser.cache.offline.enable",
- true);
-}
-
-nsOfflineCacheUpdateService::~nsOfflineCacheUpdateService()
-{
- gOfflineCacheUpdateService = 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 */
-nsOfflineCacheUpdateService *
-nsOfflineCacheUpdateService::GetInstance()
-{
- if (!gOfflineCacheUpdateService) {
- gOfflineCacheUpdateService = new nsOfflineCacheUpdateService();
- if (!gOfflineCacheUpdateService)
- return nullptr;
- NS_ADDREF(gOfflineCacheUpdateService);
- nsresult rv = gOfflineCacheUpdateService->Init();
- if (NS_FAILED(rv)) {
- NS_RELEASE(gOfflineCacheUpdateService);
- return nullptr;
- }
- return gOfflineCacheUpdateService;
- }
-
- NS_ADDREF(gOfflineCacheUpdateService);
-
- return gOfflineCacheUpdateService;
-}
-
-/* static */
-nsOfflineCacheUpdateService *
-nsOfflineCacheUpdateService::EnsureService()
-{
- if (!gOfflineCacheUpdateService) {
- // Make the service manager hold a long-lived reference to the service
- nsCOMPtr<nsIOfflineCacheUpdateService> service =
- do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
- }
-
- 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,
- nsIDOMDocument *aDocument)
-{
- LOG(("nsOfflineCacheUpdateService::ScheduleOnDocumentStop [%p, manifestURI=%p, documentURI=%p doc=%p]",
- this, aManifestURI, aDocumentURI, aDocument));
-
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
- nsCOMPtr<nsIWebProgress> progress = do_QueryInterface(doc->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=%d]",
- 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,
- nsIDOMDocument *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.
- nsCOMPtr<nsIDOMOfflineResourceList> appCacheWindowObject =
- 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,
- nsIPrefBranch *aPrefBranch,
- bool pinned,
- bool *aAllowed)
-{
- *aAllowed = false;
-
- if (!sAllowOfflineCache) {
- return NS_OK;
- }
-
- if (!aPrincipal)
- return NS_ERROR_INVALID_ARG;
-
- nsCOMPtr<nsIURI> uri;
- aPrincipal->GetURI(getter_AddRefs(uri));
-
- if (!uri)
- return NS_OK;
-
- nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
- if (!innerURI)
- return NS_OK;
-
- // only http and https applications can use offline APIs.
- bool match;
- nsresult rv = innerURI->SchemeIs("http", &match);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!match) {
- rv = innerURI->SchemeIs("https", &match);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!match) {
- return NS_OK;
- }
- }
-
- nsAutoCString domain;
- rv = innerURI->GetAsciiHost(domain);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (nsOfflineCacheUpdateService::AllowedDomains()->Contains(domain)) {
- *aAllowed = true;
- return NS_OK;
- }
-
- nsCOMPtr<nsIPermissionManager> permissionManager =
- services::GetPermissionManager();
- if (!permissionManager) {
- return NS_OK;
- }
-
- uint32_t perm;
- const char *permName = pinned ? "pin-app" : "offline-app";
- permissionManager->TestExactPermissionFromPrincipal(aPrincipal, permName, &perm);
-
- if (perm == nsIPermissionManager::ALLOW_ACTION ||
- perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) {
- *aAllowed = true;
- }
-
- // offline-apps.allow_by_default is now effective at the cache selection
- // algorithm code (nsContentSink).
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateService::OfflineAppAllowed(nsIPrincipal *aPrincipal,
- nsIPrefBranch *aPrefBranch,
- bool *aAllowed)
-{
- return OfflineAppPermForPrincipal(aPrincipal, aPrefBranch, false, aAllowed);
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateService::OfflineAppAllowedForURI(nsIURI *aURI,
- nsIPrefBranch *aPrefBranch,
- bool *aAllowed)
-{
- PrincipalOriginAttributes attrs;
- nsCOMPtr<nsIPrincipal> principal =
- BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
- return OfflineAppPermForPrincipal(principal, aPrefBranch, false, aAllowed);
-}
-
-nsresult
-nsOfflineCacheUpdateService::OfflineAppPinnedForURI(nsIURI *aDocumentURI,
- nsIPrefBranch *aPrefBranch,
- bool *aPinned)
-{
- PrincipalOriginAttributes attrs;
- nsCOMPtr<nsIPrincipal> principal =
- BasePrincipal::CreateCodebasePrincipal(aDocumentURI, attrs);
- return OfflineAppPermForPrincipal(principal, aPrefBranch, true, aPinned);
-}
-
-NS_IMETHODIMP
-nsOfflineCacheUpdateService::AllowOfflineApp(nsIPrincipal *aPrincipal)
-{
- nsresult rv;
-
- if (!sAllowOfflineCache) {
- 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()->PutEntry(domain);
- }
- else {
- nsCOMPtr<nsIPermissionManager> permissionManager =
- services::GetPermissionManager();
- if (!permissionManager)
- return NS_ERROR_NOT_AVAILABLE;
-
- rv = permissionManager->AddFromPrincipal(
- aPrincipal, "offline-app", nsIPermissionManager::ALLOW_ACTION,
- nsIPermissionManager::EXPIRE_NEVER, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
diff --git a/system/docshell/prefetch/nsPrefetchService.cpp b/system/docshell/prefetch/nsPrefetchService.cpp
deleted file mode 100644
index bd2b10d30..000000000
--- a/system/docshell/prefetch/nsPrefetchService.cpp
+++ /dev/null
@@ -1,931 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsPrefetchService.h"
-#include "nsICacheEntry.h"
-#include "nsIServiceManager.h"
-#include "nsICategoryManager.h"
-#include "nsIObserverService.h"
-#include "nsIWebProgress.h"
-#include "nsCURILoader.h"
-#include "nsICacheInfoChannel.h"
-#include "nsIHttpChannel.h"
-#include "nsIURL.h"
-#include "nsISimpleEnumerator.h"
-#include "nsNetUtil.h"
-#include "nsString.h"
-#include "nsXPIDLString.h"
-#include "nsReadableUtils.h"
-#include "nsStreamUtils.h"
-#include "nsAutoPtr.h"
-#include "prtime.h"
-#include "mozilla/Logging.h"
-#include "plstr.h"
-#include "nsIAsyncVerifyRedirectCallback.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/CORSMode.h"
-#include "mozilla/dom/HTMLLinkElement.h"
-#include "nsIDOMNode.h"
-#include "nsINode.h"
-#include "nsIDocument.h"
-#include "nsContentUtils.h"
-
-using namespace mozilla;
-
-//
-// To enable logging (see mozilla/Logging.h for full details):
-//
-// set MOZ_LOG=nsPrefetch:5
-// set MOZ_LOG_FILE=prefetch.log
-//
-// this enables LogLevel::Debug level information and places all output in
-// the file prefetch.log
-//
-static LazyLogModule gPrefetchLog("nsPrefetch");
-
-#undef LOG
-#define LOG(args) MOZ_LOG(gPrefetchLog, mozilla::LogLevel::Debug, args)
-
-#undef LOG_ENABLED
-#define LOG_ENABLED() MOZ_LOG_TEST(gPrefetchLog, mozilla::LogLevel::Debug)
-
-#define PREFETCH_PREF "network.prefetch-next"
-#define PARALLELISM_PREF "network.prefetch-next.parallelism"
-#define AGGRESSIVE_PREF "network.prefetch-next.aggressive"
-
-//-----------------------------------------------------------------------------
-// helpers
-//-----------------------------------------------------------------------------
-
-static inline uint32_t
-PRTimeToSeconds(PRTime t_usec)
-{
- PRTime usec_per_sec = PR_USEC_PER_SEC;
- return uint32_t(t_usec /= usec_per_sec);
-}
-
-#define NowInSeconds() PRTimeToSeconds(PR_Now())
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode <public>
-//-----------------------------------------------------------------------------
-
-nsPrefetchNode::nsPrefetchNode(nsPrefetchService *aService,
- nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource)
- : mURI(aURI)
- , mReferrerURI(aReferrerURI)
- , mService(aService)
- , mChannel(nullptr)
- , mBytesRead(0)
- , mShouldFireLoadEvent(false)
-{
- nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
- mSources.AppendElement(source);
-}
-
-nsresult
-nsPrefetchNode::OpenChannel()
-{
- if (mSources.IsEmpty()) {
- // Don't attempt to prefetch if we don't have a source node
- // (which should never happen).
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsINode> source;
- while (!mSources.IsEmpty() && !(source = do_QueryReferent(mSources.ElementAt(0)))) {
- // If source is null remove it.
- // (which should never happen).
- mSources.RemoveElementAt(0);
- }
-
- if (!source) {
- // Don't attempt to prefetch if we don't have a source node
- // (which should never happen).
-
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsILoadGroup> loadGroup = source->OwnerDoc()->GetDocumentLoadGroup();
- CORSMode corsMode = CORS_NONE;
- net::ReferrerPolicy referrerPolicy = net::RP_Unset;
- if (source->IsHTMLElement(nsGkAtoms::link)) {
- dom::HTMLLinkElement* link = static_cast<dom::HTMLLinkElement*>(source.get());
- corsMode = link->GetCORSMode();
- referrerPolicy = link->GetLinkReferrerPolicy();
- }
-
- if (referrerPolicy == net::RP_Unset) {
- referrerPolicy = source->OwnerDoc()->GetReferrerPolicy();
- }
-
- uint32_t securityFlags;
- if (corsMode == CORS_NONE) {
- securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
- } else {
- securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
- if (corsMode == CORS_USE_CREDENTIALS) {
- securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
- }
- }
- nsresult rv = NS_NewChannelInternal(getter_AddRefs(mChannel),
- mURI,
- source,
- source->NodePrincipal(),
- nullptr, //aTriggeringPrincipal
- securityFlags,
- nsIContentPolicy::TYPE_OTHER,
- loadGroup, // aLoadGroup
- this, // aCallbacks
- nsIRequest::LOAD_BACKGROUND |
- nsICachingChannel::LOAD_ONLY_IF_MODIFIED);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // configure HTTP specific stuff
- nsCOMPtr<nsIHttpChannel> httpChannel =
- do_QueryInterface(mChannel);
- if (httpChannel) {
- httpChannel->SetReferrerWithPolicy(mReferrerURI, referrerPolicy);
- httpChannel->SetRequestHeader(
- NS_LITERAL_CSTRING("X-Moz"),
- NS_LITERAL_CSTRING("prefetch"),
- false);
- }
-
- rv = mChannel->AsyncOpen2(this);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- // Drop the ref to the channel, because we don't want to end up with
- // cycles through it.
- mChannel = nullptr;
- }
- return rv;
-}
-
-nsresult
-nsPrefetchNode::CancelChannel(nsresult error)
-{
- mChannel->Cancel(error);
- mChannel = nullptr;
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ISUPPORTS(nsPrefetchNode,
- nsIRequestObserver,
- nsIStreamListener,
- nsIInterfaceRequestor,
- nsIChannelEventSink,
- nsIRedirectResultListener)
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode::nsIStreamListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchNode::OnStartRequest(nsIRequest *aRequest,
- nsISupports *aContext)
-{
- nsresult rv;
-
- nsCOMPtr<nsIHttpChannel> httpChannel =
- do_QueryInterface(aRequest, &rv);
- if (NS_FAILED(rv)) return rv;
-
- // if the load is cross origin without CORS, or the CORS access is rejected,
- // always fire load event to avoid leaking site information.
- nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->GetLoadInfo();
- mShouldFireLoadEvent = loadInfo->GetTainting() == LoadTainting::Opaque ||
- (loadInfo->GetTainting() == LoadTainting::CORS &&
- (NS_FAILED(httpChannel->GetStatus(&rv)) ||
- NS_FAILED(rv)));
-
- // no need to prefetch http error page
- bool requestSucceeded;
- if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
- !requestSucceeded) {
- return NS_BINDING_ABORTED;
- }
-
- nsCOMPtr<nsICacheInfoChannel> cacheInfoChannel =
- do_QueryInterface(aRequest, &rv);
- if (NS_FAILED(rv)) return rv;
-
- // no need to prefetch a document that is already in the cache
- bool fromCache;
- if (NS_SUCCEEDED(cacheInfoChannel->IsFromCache(&fromCache)) &&
- fromCache) {
- LOG(("document is already in the cache; canceling prefetch\n"));
- // although it's canceled we still want to fire load event
- mShouldFireLoadEvent = true;
- return NS_BINDING_ABORTED;
- }
-
- //
- // no need to prefetch a document that must be requested fresh each
- // and every time.
- //
- uint32_t expTime;
- if (NS_SUCCEEDED(cacheInfoChannel->GetCacheTokenExpirationTime(&expTime))) {
- if (NowInSeconds() >= expTime) {
- LOG(("document cannot be reused from cache; "
- "canceling prefetch\n"));
- return NS_BINDING_ABORTED;
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrefetchNode::OnDataAvailable(nsIRequest *aRequest,
- nsISupports *aContext,
- nsIInputStream *aStream,
- uint64_t aOffset,
- uint32_t aCount)
-{
- uint32_t bytesRead = 0;
- aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &bytesRead);
- mBytesRead += bytesRead;
- LOG(("prefetched %u bytes [offset=%llu]\n", bytesRead, aOffset));
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsPrefetchNode::OnStopRequest(nsIRequest *aRequest,
- nsISupports *aContext,
- nsresult aStatus)
-{
- LOG(("done prefetching [status=%x]\n", aStatus));
-
- if (mBytesRead == 0 && aStatus == NS_OK && mChannel) {
- // we didn't need to read (because LOAD_ONLY_IF_MODIFIED was
- // specified), but the object should report loadedSize as if it
- // did.
- mChannel->GetContentLength(&mBytesRead);
- }
-
- mService->NotifyLoadCompleted(this);
- mService->DispatchEvent(this, mShouldFireLoadEvent || NS_SUCCEEDED(aStatus));
- mService->ProcessNextURI(this);
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode::nsIInterfaceRequestor
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchNode::GetInterface(const nsIID &aIID, void **aResult)
-{
- if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
- NS_ADDREF_THIS();
- *aResult = static_cast<nsIChannelEventSink *>(this);
- return NS_OK;
- }
-
- if (aIID.Equals(NS_GET_IID(nsIRedirectResultListener))) {
- NS_ADDREF_THIS();
- *aResult = static_cast<nsIRedirectResultListener *>(this);
- return NS_OK;
- }
-
- return NS_ERROR_NO_INTERFACE;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode::nsIChannelEventSink
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchNode::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
- nsIChannel *aNewChannel,
- uint32_t aFlags,
- nsIAsyncVerifyRedirectCallback *callback)
-{
- nsCOMPtr<nsIURI> newURI;
- nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI));
- if (NS_FAILED(rv))
- return rv;
-
- bool match;
- rv = newURI->SchemeIs("http", &match);
- if (NS_FAILED(rv) || !match) {
- rv = newURI->SchemeIs("https", &match);
- if (NS_FAILED(rv) || !match) {
- LOG(("rejected: URL is not of type http/https\n"));
- return NS_ERROR_ABORT;
- }
- }
-
- // HTTP request headers are not automatically forwarded to the new channel.
- nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aNewChannel);
- NS_ENSURE_STATE(httpChannel);
-
- httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("X-Moz"),
- NS_LITERAL_CSTRING("prefetch"),
- false);
-
- // Assign to mChannel after we get notification about success of the
- // redirect in OnRedirectResult.
- mRedirectChannel = aNewChannel;
-
- callback->OnRedirectVerifyCallback(NS_OK);
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode::nsIRedirectResultListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchNode::OnRedirectResult(bool proceeding)
-{
- if (proceeding && mRedirectChannel)
- mChannel = mRedirectChannel;
-
- mRedirectChannel = nullptr;
-
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService <public>
-//-----------------------------------------------------------------------------
-
-nsPrefetchService::nsPrefetchService()
- : mMaxParallelism(6)
- , mStopCount(0)
- , mHaveProcessed(false)
- , mDisabled(true)
- , mAggressive(false)
-{
-}
-
-nsPrefetchService::~nsPrefetchService()
-{
- Preferences::RemoveObserver(this, PREFETCH_PREF);
- Preferences::RemoveObserver(this, PARALLELISM_PREF);
- Preferences::RemoveObserver(this, AGGRESSIVE_PREF);
- // cannot reach destructor if prefetch in progress (listener owns reference
- // to this service)
- EmptyQueue();
-}
-
-nsresult
-nsPrefetchService::Init()
-{
- nsresult rv;
-
- // read prefs and hook up pref observer
- mDisabled = !Preferences::GetBool(PREFETCH_PREF, !mDisabled);
- Preferences::AddWeakObserver(this, PREFETCH_PREF);
-
- mMaxParallelism = Preferences::GetInt(PARALLELISM_PREF, mMaxParallelism);
- if (mMaxParallelism < 1) {
- mMaxParallelism = 1;
- }
- Preferences::AddWeakObserver(this, PARALLELISM_PREF);
-
- mAggressive = Preferences::GetBool(AGGRESSIVE_PREF, false);
- Preferences::AddWeakObserver(this, AGGRESSIVE_PREF);
-
- // Observe xpcom-shutdown event
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return NS_ERROR_FAILURE;
-
- rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!mDisabled)
- AddProgressListener();
-
- return NS_OK;
-}
-
-void
-nsPrefetchService::ProcessNextURI(nsPrefetchNode *aFinished)
-{
- nsresult rv;
-
- if (aFinished) {
- mCurrentNodes.RemoveElement(aFinished);
- }
-
- if (mCurrentNodes.Length() >= static_cast<uint32_t>(mMaxParallelism)) {
- // We already have enough prefetches going on, so hold off
- // for now.
- return;
- }
-
- do {
- if (mQueue.empty()) {
- break;
- }
- RefPtr<nsPrefetchNode> node = mQueue.front().forget();
- mQueue.pop_front();
-
- if (LOG_ENABLED()) {
- LOG(("ProcessNextURI [%s]\n",
- node->mURI->GetSpecOrDefault().get())); }
-
- //
- // if opening the channel fails (e.g. security check returns an error),
- // send an error event and then just skip to the next uri
- //
- rv = node->OpenChannel();
- if (NS_SUCCEEDED(rv)) {
- mCurrentNodes.AppendElement(node);
- } else {
- DispatchEvent(node, false);
- }
- }
- while (NS_FAILED(rv));
-}
-
-void
-nsPrefetchService::NotifyLoadRequested(nsPrefetchNode *node)
-{
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return;
-
- observerService->NotifyObservers(static_cast<nsIStreamListener*>(node),
- "prefetch-load-requested", nullptr);
-}
-
-void
-nsPrefetchService::NotifyLoadCompleted(nsPrefetchNode *node)
-{
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return;
-
- observerService->NotifyObservers(static_cast<nsIStreamListener*>(node),
- "prefetch-load-completed", nullptr);
-}
-
-void
-nsPrefetchService::DispatchEvent(nsPrefetchNode *node, bool aSuccess)
-{
- for (uint32_t i = 0; i < node->mSources.Length(); i++) {
- nsCOMPtr<nsINode> domNode = do_QueryReferent(node->mSources.ElementAt(i));
- if (domNode && domNode->IsInComposedDoc()) {
- nsContentUtils::DispatchTrustedEvent(domNode->OwnerDoc(),
- domNode,
- aSuccess ?
- NS_LITERAL_STRING("load") :
- NS_LITERAL_STRING("error"),
- /* aCanBubble = */ false,
- /* aCancelable = */ false);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService <private>
-//-----------------------------------------------------------------------------
-
-void
-nsPrefetchService::AddProgressListener()
-{
- // Register as an observer for the document loader
- nsCOMPtr<nsIWebProgress> progress =
- do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
- if (progress)
- progress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
-}
-
-void
-nsPrefetchService::RemoveProgressListener()
-{
- // Register as an observer for the document loader
- nsCOMPtr<nsIWebProgress> progress =
- do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
- if (progress)
- progress->RemoveProgressListener(this);
-}
-
-nsresult
-nsPrefetchService::EnqueueURI(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource,
- nsPrefetchNode **aNode)
-{
- RefPtr<nsPrefetchNode> node = new nsPrefetchNode(this, aURI, aReferrerURI,
- aSource);
- mQueue.push_back(node);
- node.forget(aNode);
- return NS_OK;
-}
-
-void
-nsPrefetchService::EmptyQueue()
-{
- while (!mQueue.empty()) {
- mQueue.pop_back();
- }
-}
-
-void
-nsPrefetchService::StartPrefetching()
-{
- //
- // at initialization time we might miss the first DOCUMENT START
- // notification, so we have to be careful to avoid letting our
- // stop count go negative.
- //
- if (mStopCount > 0)
- mStopCount--;
-
- LOG(("StartPrefetching [stopcount=%d]\n", mStopCount));
-
- // only start prefetching after we've received enough DOCUMENT
- // STOP notifications. we do this inorder to defer prefetching
- // until after all sub-frames have finished loading.
- if (!mStopCount) {
- mHaveProcessed = true;
- while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
- ProcessNextURI(nullptr);
- }
- }
-}
-
-void
-nsPrefetchService::StopPrefetching()
-{
- mStopCount++;
-
- LOG(("StopPrefetching [stopcount=%d]\n", mStopCount));
-
- // only kill the prefetch queue if we are actively prefetching right now
- if (mCurrentNodes.IsEmpty()) {
- return;
- }
-
- for (uint32_t i = 0; i < mCurrentNodes.Length(); ++i) {
- mCurrentNodes[i]->CancelChannel(NS_BINDING_ABORTED);
- }
- mCurrentNodes.Clear();
- EmptyQueue();
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ISUPPORTS(nsPrefetchService,
- nsIPrefetchService,
- nsIWebProgressListener,
- nsIObserver,
- nsISupportsWeakReference)
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService::nsIPrefetchService
-//-----------------------------------------------------------------------------
-
-nsresult
-nsPrefetchService::Prefetch(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource,
- bool aExplicit)
-{
- nsresult rv;
-
- NS_ENSURE_ARG_POINTER(aURI);
- NS_ENSURE_ARG_POINTER(aReferrerURI);
-
- if (LOG_ENABLED()) {
- LOG(("PrefetchURI [%s]\n", aURI->GetSpecOrDefault().get()));
- }
-
- if (mDisabled) {
- LOG(("rejected: prefetch service is disabled\n"));
- return NS_ERROR_ABORT;
- }
-
- //
- // XXX we should really be asking the protocol handler if it supports
- // caching, so we can determine if there is any value to prefetching.
- // for now, we'll only prefetch http links since we know that's the
- // most common case. ignore https links since https content only goes
- // into the memory cache.
- //
- // XXX we might want to either leverage nsIProtocolHandler::protocolFlags
- // or possibly nsIRequest::loadFlags to determine if this URI should be
- // prefetched.
- //
- bool match;
- rv = aURI->SchemeIs("http", &match);
- if (NS_FAILED(rv) || !match) {
- rv = aURI->SchemeIs("https", &match);
- if (NS_FAILED(rv) || !match) {
- LOG(("rejected: URL is not of type http/https\n"));
- return NS_ERROR_ABORT;
- }
- }
-
- //
- // the referrer URI must be http:
- //
- rv = aReferrerURI->SchemeIs("http", &match);
- if (NS_FAILED(rv) || !match) {
- rv = aReferrerURI->SchemeIs("https", &match);
- if (NS_FAILED(rv) || !match) {
- LOG(("rejected: referrer URL is neither http nor https\n"));
- return NS_ERROR_ABORT;
- }
- }
-
- // skip URLs that contain query strings, except URLs for which prefetching
- // has been explicitly requested.
- if (!aExplicit) {
- nsCOMPtr<nsIURL> url(do_QueryInterface(aURI, &rv));
- if (NS_FAILED(rv)) return rv;
- nsAutoCString query;
- rv = url->GetQuery(query);
- if (NS_FAILED(rv) || !query.IsEmpty()) {
- LOG(("rejected: URL has a query string\n"));
- return NS_ERROR_ABORT;
- }
- }
-
- //
- // Check whether it is being prefetched.
- //
- for (uint32_t i = 0; i < mCurrentNodes.Length(); ++i) {
- bool equals;
- if (NS_SUCCEEDED(mCurrentNodes[i]->mURI->Equals(aURI, &equals)) &&
- equals) {
- nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
- if (mCurrentNodes[i]->mSources.IndexOf(source) ==
- mCurrentNodes[i]->mSources.NoIndex) {
- LOG(("URL is already being prefetched, add a new reference "
- "document\n"));
- mCurrentNodes[i]->mSources.AppendElement(source);
- return NS_OK;
- } else {
- LOG(("URL is already being prefetched by this document"));
- return NS_ERROR_ABORT;
- }
- }
- }
-
- //
- // Check whether it is on the prefetch queue.
- //
- for (std::deque<RefPtr<nsPrefetchNode>>::iterator nodeIt = mQueue.begin();
- nodeIt != mQueue.end(); nodeIt++) {
- bool equals;
- RefPtr<nsPrefetchNode> node = nodeIt->get();
- if (NS_SUCCEEDED(node->mURI->Equals(aURI, &equals)) && equals) {
- nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
- if (node->mSources.IndexOf(source) ==
- node->mSources.NoIndex) {
- LOG(("URL is already being prefetched, add a new reference "
- "document\n"));
- node->mSources.AppendElement(do_GetWeakReference(aSource));
- return NS_OK;
- } else {
- LOG(("URL is already being prefetched by this document"));
- return NS_ERROR_ABORT;
- }
-
- }
- }
-
- RefPtr<nsPrefetchNode> enqueuedNode;
- rv = EnqueueURI(aURI, aReferrerURI, aSource,
- getter_AddRefs(enqueuedNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- NotifyLoadRequested(enqueuedNode);
-
- // if there are no pages loading, kick off the request immediately
- if (mStopCount == 0 && mHaveProcessed) {
- ProcessNextURI(nullptr);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrefetchService::CancelPrefetchURI(nsIURI* aURI,
- nsIDOMNode* aSource)
-{
- NS_ENSURE_ARG_POINTER(aURI);
-
- if (LOG_ENABLED()) {
- LOG(("CancelPrefetchURI [%s]\n", aURI->GetSpecOrDefault().get()));
- }
-
- //
- // look in current prefetches
- //
- for (uint32_t i = 0; i < mCurrentNodes.Length(); ++i) {
- bool equals;
- if (NS_SUCCEEDED(mCurrentNodes[i]->mURI->Equals(aURI, &equals)) &&
- equals) {
- nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
- if (mCurrentNodes[i]->mSources.IndexOf(source) !=
- mCurrentNodes[i]->mSources.NoIndex) {
- mCurrentNodes[i]->mSources.RemoveElement(source);
- if (mCurrentNodes[i]->mSources.IsEmpty()) {
- mCurrentNodes[i]->CancelChannel(NS_BINDING_ABORTED);
- mCurrentNodes.RemoveElementAt(i);
- }
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
- }
- }
-
- //
- // look into the prefetch queue
- //
- for (std::deque<RefPtr<nsPrefetchNode>>::iterator nodeIt = mQueue.begin();
- nodeIt != mQueue.end(); nodeIt++) {
- bool equals;
- RefPtr<nsPrefetchNode> node = nodeIt->get();
- if (NS_SUCCEEDED(node->mURI->Equals(aURI, &equals)) && equals) {
- nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
- if (node->mSources.IndexOf(source) !=
- node->mSources.NoIndex) {
-
-#ifdef DEBUG
- int32_t inx = node->mSources.IndexOf(source);
- nsCOMPtr<nsIDOMNode> domNode =
- do_QueryReferent(node->mSources.ElementAt(inx));
- MOZ_ASSERT(domNode);
-#endif
-
- node->mSources.RemoveElement(source);
- if (node->mSources.IsEmpty()) {
- mQueue.erase(nodeIt);
- }
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
- }
- }
-
- // not found!
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsPrefetchService::PrefetchURI(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource,
- bool aExplicit)
-{
- return Prefetch(aURI, aReferrerURI, aSource, aExplicit);
-}
-
-NS_IMETHODIMP
-nsPrefetchService::HasMoreElements(bool *aHasMore)
-{
- *aHasMore = (mCurrentNodes.Length() || !mQueue.empty());
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService::nsIWebProgressListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchService::OnProgressChange(nsIWebProgress *aProgress,
- nsIRequest *aRequest,
- int32_t curSelfProgress,
- int32_t maxSelfProgress,
- int32_t curTotalProgress,
- int32_t maxTotalProgress)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrefetchService::OnStateChange(nsIWebProgress* aWebProgress,
- nsIRequest *aRequest,
- uint32_t progressStateFlags,
- nsresult aStatus)
-{
- if (mAggressive) {
- LOG(("Document load state is ignored in aggressive mode"));
- return NS_OK;
- }
-
- if (progressStateFlags & STATE_IS_DOCUMENT) {
- if (progressStateFlags & STATE_STOP)
- StartPrefetching();
- else if (progressStateFlags & STATE_START)
- StopPrefetching();
- }
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsPrefetchService::OnLocationChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsIURI *location,
- uint32_t aFlags)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrefetchService::OnStatusChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsresult aStatus,
- const char16_t* aMessage)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPrefetchService::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- uint32_t state)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService::nsIObserver
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsPrefetchService::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *aData)
-{
- LOG(("nsPrefetchService::Observe [topic=%s]\n", aTopic));
-
- if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
- StopPrefetching();
- EmptyQueue();
- mDisabled = true;
- }
- else if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
- const nsCString converted = NS_ConvertUTF16toUTF8(aData);
- const char* pref = converted.get();
- if (!strcmp(pref, PREFETCH_PREF)) {
- if (Preferences::GetBool(PREFETCH_PREF, false)) {
- if (mDisabled) {
- LOG(("enabling prefetching\n"));
- mDisabled = false;
- AddProgressListener();
- }
- } else {
- if (!mDisabled) {
- LOG(("disabling prefetching\n"));
- StopPrefetching();
- EmptyQueue();
- mDisabled = true;
- RemoveProgressListener();
- }
- }
- } else if (!strcmp(pref, PARALLELISM_PREF)) {
- mMaxParallelism = Preferences::GetInt(PARALLELISM_PREF, mMaxParallelism);
- if (mMaxParallelism < 1) {
- mMaxParallelism = 1;
- }
- // If our parallelism has increased, go ahead and kick off enough
- // prefetches to fill up our allowance. If we're now over our
- // allowance, we'll just silently let some of them finish to get
- // back below our limit.
- while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
- ProcessNextURI(nullptr);
- }
- } else if (!strcmp(pref, AGGRESSIVE_PREF)) {
- mAggressive = Preferences::GetBool(AGGRESSIVE_PREF, false);
- // in aggressive mode, clear stop count and start prefetching immediately
- if (mAggressive) {
- mStopCount = 0;
- StartPrefetching();
- }
- }
- }
-
- return NS_OK;
-}
-
-// vim: ts=4 sw=4 expandtab
diff --git a/system/docshell/prefetch/nsPrefetchService.h b/system/docshell/prefetch/nsPrefetchService.h
deleted file mode 100644
index 883449e68..000000000
--- a/system/docshell/prefetch/nsPrefetchService.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsPrefetchService_h__
-#define nsPrefetchService_h__
-
-#include "nsCPrefetchService.h"
-#include "nsIObserver.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIChannelEventSink.h"
-#include "nsIRedirectResultListener.h"
-#include "nsIWebProgressListener.h"
-#include "nsIStreamListener.h"
-#include "nsIChannel.h"
-#include "nsIURI.h"
-#include "nsWeakReference.h"
-#include "nsCOMPtr.h"
-#include "nsAutoPtr.h"
-#include "mozilla/Attributes.h"
-#include <deque>
-
-class nsPrefetchService;
-class nsPrefetchNode;
-
-//-----------------------------------------------------------------------------
-// nsPrefetchService
-//-----------------------------------------------------------------------------
-
-class nsPrefetchService final : public nsIPrefetchService
- , public nsIWebProgressListener
- , public nsIObserver
- , public nsSupportsWeakReference
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIPREFETCHSERVICE
- NS_DECL_NSIWEBPROGRESSLISTENER
- NS_DECL_NSIOBSERVER
-
- nsPrefetchService();
-
- nsresult Init();
- void ProcessNextURI(nsPrefetchNode *aFinished);
-
- void NotifyLoadRequested(nsPrefetchNode *node);
- void NotifyLoadCompleted(nsPrefetchNode *node);
- void DispatchEvent(nsPrefetchNode *node, bool aSuccess);
-
-private:
- ~nsPrefetchService();
-
- nsresult Prefetch(nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource,
- bool aExplicit);
-
- void AddProgressListener();
- void RemoveProgressListener();
- nsresult EnqueueURI(nsIURI *aURI, nsIURI *aReferrerURI,
- nsIDOMNode *aSource, nsPrefetchNode **node);
- void EmptyQueue();
-
- void StartPrefetching();
- void StopPrefetching();
-
- std::deque<RefPtr<nsPrefetchNode>> mQueue;
- nsTArray<RefPtr<nsPrefetchNode>> mCurrentNodes;
- int32_t mMaxParallelism;
- int32_t mStopCount;
- // true if pending document loads have ever reached zero.
- int32_t mHaveProcessed;
- bool mDisabled;
-
- // In usual case prefetch does not start until all normal loads are done.
- // Aggressive mode ignores normal loads and just start prefetch ASAP.
- // It's mainly for testing purpose and discoraged for normal use;
- // see https://bugzilla.mozilla.org/show_bug.cgi?id=1281415 for details.
- bool mAggressive;
-};
-
-//-----------------------------------------------------------------------------
-// nsPrefetchNode
-//-----------------------------------------------------------------------------
-
-class nsPrefetchNode final : public nsIStreamListener
- , public nsIInterfaceRequestor
- , public nsIChannelEventSink
- , public nsIRedirectResultListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIREQUESTOBSERVER
- NS_DECL_NSISTREAMLISTENER
- NS_DECL_NSIINTERFACEREQUESTOR
- NS_DECL_NSICHANNELEVENTSINK
- NS_DECL_NSIREDIRECTRESULTLISTENER
-
- nsPrefetchNode(nsPrefetchService *aPrefetchService,
- nsIURI *aURI,
- nsIURI *aReferrerURI,
- nsIDOMNode *aSource);
-
- nsresult OpenChannel();
- nsresult CancelChannel(nsresult error);
-
- nsCOMPtr<nsIURI> mURI;
- nsCOMPtr<nsIURI> mReferrerURI;
- nsTArray<nsCOMPtr<nsIWeakReference>> mSources;
-
-private:
- ~nsPrefetchNode() {}
-
- RefPtr<nsPrefetchService> mService;
- nsCOMPtr<nsIChannel> mChannel;
- nsCOMPtr<nsIChannel> mRedirectChannel;
- int64_t mBytesRead;
- bool mShouldFireLoadEvent;
-};
-
-#endif // !nsPrefetchService_h__