Bug 536295 - e10s HTTP: offline application cache, r=dwitte, sr=cbiesinger, a=fennec-2.0b2+

--HG--
rename : uriloader/prefetch/nsOfflineCacheUpdate.cpp => uriloader/prefetch/OfflineCacheUpdateChild.cpp
rename : uriloader/prefetch/nsOfflineCacheUpdate.cpp => uriloader/prefetch/nsOfflineCacheUpdateService.cpp
This commit is contained in:
Honza Bambas 2010-10-20 19:12:32 +02:00
Родитель 7b00a05d5e
Коммит e3cf711385
38 изменённых файлов: 2672 добавлений и 975 удалений

Просмотреть файл

@ -5735,7 +5735,7 @@ var OfflineApps = {
var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
getService(Ci.nsIOfflineCacheUpdateService);
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject);
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window);
},
/////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -74,7 +74,6 @@
#include "nsIApplicationCache.h"
#include "nsIApplicationCacheContainer.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIApplicationCacheService.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMLoadStatus.h"
#include "nsICookieService.h"
@ -942,29 +941,6 @@ nsContentSink::PrefetchDNS(const nsAString &aHref)
}
}
nsresult
nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey)
{
aCacheKey.Truncate();
nsresult rv;
nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aChannel, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> cacheKey;
rv = cachingChannel->GetCacheKey(getter_AddRefs(cacheKey));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsCString> cacheKeyString =
do_QueryInterface(cacheKey, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = cacheKeyString->GetData(aCacheKey);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
nsIURI *aManifestURI,
@ -994,17 +970,8 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
NS_ENSURE_SUCCESS(rv, rv);
if (!equal) {
// This is a foreign entry, mark it as such and force a reload to avoid
// loading the foreign entry. The next attempt will not choose this
// cache entry (because it has been marked foreign).
nsCAutoString cachekey;
rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
NS_ENSURE_SUCCESS(rv, rv);
rv = aLoadApplicationCache->MarkEntry(cachekey,
nsIApplicationCache::ITEM_FOREIGN);
NS_ENSURE_SUCCESS(rv, rv);
// This is a foreign entry, force a reload to avoid loading the foreign
// entry. The entry will be marked as foreign to avoid loading it again.
*aAction = CACHE_SELECTION_RELOAD;
}
@ -1219,6 +1186,13 @@ nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
case CACHE_SELECTION_RELOAD: {
// This situation occurs only for toplevel documents, see bottom
// of SelectDocAppCache method.
// The document has been loaded from a different offline cache group than
// the manifest it refers to, i.e. this is a foreign entry, mark it as such
// and force a reload to avoid loading it. The next attempt will not
// choose it.
applicationCacheChannel->MarkOfflineCacheEntryAsForeign();
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
webNav->Stop(nsIWebNavigation::STOP_ALL);

Просмотреть файл

@ -230,6 +230,10 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#ifdef MOZ_IPC
#include "nsXULAppAPI.h"
#endif
using namespace mozilla;
// Number of documents currently loading
@ -5928,7 +5932,13 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(aNewChannel);
if (appCacheChannel) {
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(newURI));
#ifdef MOZ_IPC
// Permission will be checked in the parent process.
if (GeckoProcessType_Default != XRE_GetProcessType())
appCacheChannel->SetChooseApplicationCache(PR_TRUE);
else
#endif
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(newURI));
}
if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
@ -8581,7 +8591,14 @@ nsDocShell::DoURILoad(nsIURI * aURI,
// Loads with the correct permissions should check for a matching
// application cache.
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(aURI));
#ifdef MOZ_IPC
// Permission will be checked in the parent process
if (GeckoProcessType_Default != XRE_GetProcessType())
appCacheChannel->SetChooseApplicationCache(PR_TRUE);
else
#endif
appCacheChannel->SetChooseApplicationCache(
ShouldCheckAppCache(aURI));
}
// Make sure to give the caller a channel if we managed to create one

Просмотреть файл

@ -8164,6 +8164,22 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
if (mApplicationCache)
return NS_OK;
// Instantiate the application object now. It observes update belonging to
// this window's document and correctly updates the applicationCache object
// state.
nsCOMPtr<nsIDOMOfflineResourceList> applicationCache;
GetApplicationCache(getter_AddRefs(applicationCache));
nsCOMPtr<nsIObserver> observer = do_QueryInterface(applicationCache);
if (observer)
observer->Observe(aSubject, aTopic, aData);
return NS_OK;
}
NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -85,6 +85,7 @@
using namespace mozilla::ipc;
using namespace mozilla::net;
using namespace mozilla::places;
using namespace mozilla::docshell;
namespace mozilla {
namespace dom {

Просмотреть файл

@ -44,6 +44,7 @@ include protocol PDocumentRendererShmem;
include protocol PDocumentRendererNativeID;
include protocol PContentPermissionRequest;
include protocol PRenderFrame;
include protocol POfflineCacheUpdate;
include "TabMessageUtils.h";
include "gfxMatrix.h";
@ -73,6 +74,7 @@ rpc protocol PBrowser
manages PDocumentRendererNativeID;
manages PContentPermissionRequest;
manages PRenderFrame;
manages POfflineCacheUpdate;
both:
AsyncMessage(nsString aMessage, nsString aJSON);
@ -187,6 +189,33 @@ parent:
*/
async PRenderFrame();
/**
* Starts an offline application cache update.
* @param manifestURI
* URI of the manifest to fetch, the application cache group ID
* @param documentURI
* URI of the document that referred the manifest
* @param clientID
* The group cache version identifier to use
* @param stickDocument
* True if the update was initiated by a document load that referred
* a manifest.
* False if the update was initiated by applicationCache.update() call.
*
* Tells the update to carry the documentURI to a potential separate
* update of implicit (master) items.
*
* Why this argument? If the document was not found in an offline cache
* before load and refers a manifest and this manifest itself has not
* been changed since the last fetch, we will not do the application
* cache group update. But we must cache the document (identified by the
* documentURI). This argument will ensure that a previously uncached
* document will get cached and that we don't re-cache a document that
* has already been cached (stickDocument=false).
*/
POfflineCacheUpdate(URI manifestURI, URI documentURI, nsCString clientID,
bool stickDocument);
__delete__();
child:

Просмотреть файл

@ -41,6 +41,7 @@
#include "mozilla/dom/PContentDialogChild.h"
#include "mozilla/layers/PLayersChild.h"
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
#include "BasicLayers.h"
#include "nsIWebBrowser.h"
@ -94,6 +95,7 @@
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::layout;
using namespace mozilla::docshell;
NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
@ -809,6 +811,24 @@ TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
return true;
}
POfflineCacheUpdateChild*
TabChild::AllocPOfflineCacheUpdate(const URI& manifestURI,
const URI& documentURI,
const nsCString& clientID,
const bool& stickDocument)
{
NS_RUNTIMEABORT("unused");
return nsnull;
}
bool
TabChild::DeallocPOfflineCacheUpdate(POfflineCacheUpdateChild* actor)
{
OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor);
delete offlineCacheUpdate;
return true;
}
bool
TabChild::RecvLoadRemoteScript(const nsString& aURL)
{

Просмотреть файл

@ -277,6 +277,12 @@ public:
virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType, const IPC::URI& uri);
virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor);
virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate(const URI& manifestURI,
const URI& documentURI,
const nsCString& clientID,
const bool& stickDocument);
virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateChild* offlineCacheUpdate);
nsIWebNavigation* WebNavigation() { return mWebNav; }
JSContext* GetJSContext() { return mCx; }

Просмотреть файл

@ -43,6 +43,7 @@
#include "mozilla/ipc/DocumentRendererShmemParent.h"
#include "mozilla/ipc/DocumentRendererNativeIDParent.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "nsIURI.h"
#include "nsFocusManager.h"
@ -703,6 +704,35 @@ TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
return true;
}
mozilla::docshell::POfflineCacheUpdateParent*
TabParent::AllocPOfflineCacheUpdate(const URI& aManifestURI,
const URI& aDocumentURI,
const nsCString& aClientID,
const bool& stickDocument)
{
nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
new mozilla::docshell::OfflineCacheUpdateParent();
nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aClientID,
stickDocument);
if (NS_FAILED(rv))
return nsnull;
POfflineCacheUpdateParent* result = update.get();
update.forget();
return result;
}
bool
TabParent::DeallocPOfflineCacheUpdate(mozilla::docshell::POfflineCacheUpdateParent* actor)
{
mozilla::docshell::OfflineCacheUpdateParent* update =
static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(actor);
update->Release();
return true;
}
PRBool
TabParent::ShouldDelayDialogs()
{

Просмотреть файл

@ -170,6 +170,13 @@ public:
virtual PContentPermissionRequestParent* AllocPContentPermissionRequest(const nsCString& aType, const IPC::URI& uri);
virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestParent* actor);
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdate(
const URI& aManifestURI,
const URI& aDocumentURI,
const nsCString& aClientID,
const bool& stickDocument);
virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateParent* actor);
JSBool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
NS_DECL_ISUPPORTS

Просмотреть файл

@ -57,6 +57,15 @@
#include "nsIScriptGlobalObject.h"
#include "nsIWebNavigation.h"
#ifdef MOZ_IPC
#include "nsXULAppAPI.h"
#define IS_CHILD_PROCESS() \
(GeckoProcessType_Default != XRE_GetProcessType())
#else
#define IS_CHILD_PROCESS() \
(false)
#endif
// Event names
#define CHECKING_STR "checking"
@ -137,6 +146,8 @@ nsDOMOfflineResourceList::nsDOMOfflineResourceList(nsIURI *aManifestURI,
, mDocumentURI(aDocumentURI)
, mCachedKeys(nsnull)
, mCachedKeysCount(0)
, mExposeCacheUpdateStatus(true)
, mStatus(nsIDOMOfflineResourceList::IDLE)
{
mOwner = aWindow;
mScriptContext = aScriptContext;
@ -170,26 +181,29 @@ nsDOMOfflineResourceList::Init()
if (!innerURI)
return NS_ERROR_FAILURE;
mApplicationCacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Check for in-progress cache updates
nsCOMPtr<nsIOfflineCacheUpdateService> cacheUpdateService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 numUpdates;
rv = cacheUpdateService->GetNumUpdates(&numUpdates);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < numUpdates; i++) {
nsCOMPtr<nsIOfflineCacheUpdate> cacheUpdate;
rv = cacheUpdateService->GetUpdate(i, getter_AddRefs(cacheUpdate));
if (!IS_CHILD_PROCESS())
{
mApplicationCacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
UpdateAdded(cacheUpdate);
// Check for in-progress cache updates
nsCOMPtr<nsIOfflineCacheUpdateService> cacheUpdateService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 numUpdates;
rv = cacheUpdateService->GetNumUpdates(&numUpdates);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < numUpdates; i++) {
nsCOMPtr<nsIOfflineCacheUpdate> cacheUpdate;
rv = cacheUpdateService->GetUpdate(i, getter_AddRefs(cacheUpdate));
NS_ENSURE_SUCCESS(rv, rv);
UpdateAdded(cacheUpdate);
NS_ENSURE_SUCCESS(rv, rv);
}
}
// watch for new offline cache updates
@ -235,6 +249,9 @@ nsDOMOfflineResourceList::Disconnect()
NS_IMETHODIMP
nsDOMOfflineResourceList::GetMozItems(nsIDOMDOMStringList **aItems)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
*aItems = nsnull;
nsRefPtr<nsDOMStringList> items = new nsDOMStringList();
@ -270,6 +287,9 @@ nsDOMOfflineResourceList::GetMozItems(nsIDOMDOMStringList **aItems)
NS_IMETHODIMP
nsDOMOfflineResourceList::MozHasItem(const nsAString& aURI, PRBool* aExists)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -297,6 +317,9 @@ nsDOMOfflineResourceList::MozHasItem(const nsAString& aURI, PRBool* aExists)
NS_IMETHODIMP
nsDOMOfflineResourceList::GetMozLength(PRUint32 *aLength)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
if (!mManifestURI) {
*aLength = 0;
return NS_OK;
@ -315,6 +338,9 @@ nsDOMOfflineResourceList::GetMozLength(PRUint32 *aLength)
NS_IMETHODIMP
nsDOMOfflineResourceList::MozItem(PRUint32 aIndex, nsAString& aURI)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -334,6 +360,9 @@ nsDOMOfflineResourceList::MozItem(PRUint32 aIndex, nsAString& aURI)
NS_IMETHODIMP
nsDOMOfflineResourceList::MozAdd(const nsAString& aURI)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -398,6 +427,9 @@ nsDOMOfflineResourceList::MozAdd(const nsAString& aURI)
NS_IMETHODIMP
nsDOMOfflineResourceList::MozRemove(const nsAString& aURI)
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -453,26 +485,14 @@ nsDOMOfflineResourceList::GetStatus(PRUint16 *aStatus)
// If there is an update in process, use its status.
if (mCacheUpdate) {
if (mCacheUpdate && mExposeCacheUpdateStatus) {
rv = mCacheUpdate->GetStatus(aStatus);
if (NS_SUCCEEDED(rv) && *aStatus != nsIDOMOfflineResourceList::IDLE) {
return NS_OK;
}
}
nsCOMPtr<nsIApplicationCache> activeCache;
rv = mApplicationCacheService->GetActiveCache(mManifestSpec,
getter_AddRefs(activeCache));
NS_ENSURE_SUCCESS(rv, rv);
if (activeCache == nsnull) {
*aStatus = nsIDOMOfflineResourceList::OBSOLETE;
} else if (appCache == activeCache) {
*aStatus = nsIDOMOfflineResourceList::IDLE;
} else {
*aStatus = nsIDOMOfflineResourceList::UPDATEREADY;
}
*aStatus = mStatus;
return NS_OK;
}
@ -490,9 +510,12 @@ nsDOMOfflineResourceList::Update()
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMWindow> window =
do_QueryInterface(mOwner);
nsCOMPtr<nsIOfflineCacheUpdate> update;
rv = updateService->ScheduleUpdate(mManifestURI, mDocumentURI,
getter_AddRefs(update));
window, getter_AddRefs(update));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -508,33 +531,39 @@ nsDOMOfflineResourceList::SwapCache()
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIApplicationCacheService> serv =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIApplicationCache> currentAppCache = GetDocumentAppCache();
nsCOMPtr<nsIApplicationCache> newAppCache;
rv = serv->GetActiveCache(mManifestSpec, getter_AddRefs(newAppCache));
NS_ENSURE_SUCCESS(rv, rv);
// In the case of an obsolete cache group, newAppCache might be null.
// We will disassociate from the cache in that case.
if (newAppCache == currentAppCache) {
if (!currentAppCache) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
// Check the current and potentially newly available cache are not identical.
if (mAvailableApplicationCache == currentAppCache) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
if (mAvailableApplicationCache) {
nsCString currClientId, availClientId;
currentAppCache->GetClientID(currClientId);
mAvailableApplicationCache->GetClientID(availClientId);
if (availClientId == currClientId)
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
ClearCachedKeys();
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
GetDocumentAppCacheContainer();
// In the case of an obsolete cache group, newAppCache might be null.
// We will disassociate from the cache in that case.
if (appCacheContainer) {
rv = appCacheContainer->SetApplicationCache(newAppCache);
rv = appCacheContainer->SetApplicationCache(mAvailableApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
mAvailableApplicationCache = nsnull;
mStatus = nsIDOMOfflineResourceList::IDLE;
return NS_OK;
}
@ -727,53 +756,50 @@ nsDOMOfflineResourceList::Observe(nsISupports *aSubject,
// nsDOMOfflineResourceList::nsIOfflineCacheUpdateObserver
//
NS_IMETHODIMP
nsDOMOfflineResourceList::Error(nsIOfflineCacheUpdate *aUpdate)
nsDOMOfflineResourceList::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate,
PRUint32 event)
{
SendEvent(NS_LITERAL_STRING(ERROR_STR));
mExposeCacheUpdateStatus =
(event == STATE_CHECKING) ||
(event == STATE_DOWNLOADING) ||
(event == STATE_ITEMSTARTED) ||
(event == STATE_ITEMCOMPLETED) ||
// During notification of "obsolete" we must expose state of the update
(event == STATE_OBSOLETE);
switch (event) {
case STATE_ERROR:
SendEvent(NS_LITERAL_STRING(ERROR_STR));
break;
case STATE_CHECKING:
SendEvent(NS_LITERAL_STRING(CHECKING_STR));
break;
case STATE_NOUPDATE:
SendEvent(NS_LITERAL_STRING(NOUPDATE_STR));
break;
case STATE_OBSOLETE:
mStatus = nsIDOMOfflineResourceList::OBSOLETE;
mAvailableApplicationCache = nsnull;
SendEvent(NS_LITERAL_STRING(OBSOLETE_STR));
break;
case STATE_DOWNLOADING:
SendEvent(NS_LITERAL_STRING(DOWNLOADING_STR));
break;
case STATE_ITEMSTARTED:
SendEvent(NS_LITERAL_STRING(PROGRESS_STR));
break;
case STATE_ITEMCOMPLETED:
// Nothing to do here...
break;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::Checking(nsIOfflineCacheUpdate *aUpdate)
nsDOMOfflineResourceList::ApplicationCacheAvailable(nsIApplicationCache *aApplicationCache)
{
SendEvent(NS_LITERAL_STRING(CHECKING_STR));
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::NoUpdate(nsIOfflineCacheUpdate *aUpdate)
{
SendEvent(NS_LITERAL_STRING(NOUPDATE_STR));
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::Downloading(nsIOfflineCacheUpdate *aUpdate)
{
SendEvent(NS_LITERAL_STRING(DOWNLOADING_STR));
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::ItemStarted(nsIOfflineCacheUpdate *aUpdate,
nsIDOMLoadStatus *aItem)
{
SendEvent(NS_LITERAL_STRING(PROGRESS_STR));
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::ItemCompleted(nsIOfflineCacheUpdate *aUpdate,
nsIDOMLoadStatus *aItem)
{
return NS_OK;
}
NS_IMETHODIMP
nsDOMOfflineResourceList::Obsolete(nsIOfflineCacheUpdate *aUpdate)
{
SendEvent(NS_LITERAL_STRING(OBSOLETE_STR));
mAvailableApplicationCache = aApplicationCache;
return NS_OK;
}
@ -875,8 +901,10 @@ nsDOMOfflineResourceList::UpdateCompleted(nsIOfflineCacheUpdate *aUpdate)
if (NS_SUCCEEDED(rv) && succeeded && !partial) {
if (isUpgrade) {
mStatus = nsIDOMOfflineResourceList::UPDATEREADY;
SendEvent(NS_LITERAL_STRING(UPDATEREADY_STR));
} else {
mStatus = nsIDOMOfflineResourceList::IDLE;
SendEvent(NS_LITERAL_STRING(CACHED_STR));
}
}
@ -905,6 +933,9 @@ nsDOMOfflineResourceList::GetCacheKey(nsIURI *aURI, nsCString &aKey)
nsresult
nsDOMOfflineResourceList::CacheKeys()
{
if (IS_CHILD_PROCESS())
return NS_ERROR_NOT_IMPLEMENTED;
if (mCachedKeys)
return NS_OK;
@ -929,6 +960,3 @@ nsDOMOfflineResourceList::ClearCachedKeys()
mCachedKeysCount = 0;
}
}

Просмотреть файл

@ -110,7 +110,10 @@ private:
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIApplicationCacheService> mApplicationCacheService;
nsCOMPtr<nsIApplicationCache> mAvailableApplicationCache;
nsCOMPtr<nsIOfflineCacheUpdate> mCacheUpdate;
bool mExposeCacheUpdateStatus;
PRUint16 mStatus;
// The set of dynamic keys for this application cache object.
char **mCachedKeys;

Просмотреть файл

@ -67,6 +67,7 @@ IPDLDIRS = \
netwerk/protocol/http \
netwerk/protocol/wyciwyg \
netwerk/cookie \
uriloader/prefetch \
$(NULL)
##-----------------------------------------------------------------------------

Просмотреть файл

@ -111,9 +111,16 @@ interface nsIApplicationCacheNamespace : nsISupports
* loads. Inactive caches will be removed from the cache when they are
* no longer referenced.
*/
[scriptable, uuid(663e2e2e-04a0-47b6-87b3-a122be46cb53)]
[scriptable, uuid(32f83e3f-470c-4423-a86a-d35d1c215ccb)]
interface nsIApplicationCache : nsISupports
{
/**
* Init this application cache instance to just hold the group ID and
* the client ID to work just as a handle to the real cache. Used on
* content process to simplify the application cache code.
*/
void initAsHandle(in ACString groupId, in ACString clientId);
/**
* Entries in an application cache can be marked as one or more of
* the following types.

Просмотреть файл

@ -43,7 +43,7 @@
/**
* Interface implemented by channels that support application caches.
*/
[scriptable, uuid(9acfd21c-9c07-459f-8dae-ed2ffba23ddc)]
[scriptable, uuid(8d9024e6-ab01-442d-8119-2f55d55d91b0)]
interface nsIApplicationCacheChannel : nsIApplicationCacheContainer
{
/**
@ -75,4 +75,11 @@ interface nsIApplicationCacheChannel : nsIApplicationCacheContainer
* is called.
*/
attribute boolean chooseApplicationCache;
/**
* A shortcut method to mark the cache item of this channel as 'foreign'.
* See the 'cache selection algorithm' and CACHE_SELECTION_RELOAD
* action handling in nsContentSink.
*/
void markOfflineCacheEntryAsForeign();
};

Просмотреть файл

@ -512,6 +512,19 @@
{0x8e, 0x1c, 0xd1, 0xaf, 0x79, 0xdf, 0xd1, 0x2f} \
}
#define NS_APPLICATIONCACHE_CLASSNAME \
"nsApplicationCache"
#define NS_APPLICATIONCACHE_CONTRACTID \
"@mozilla.org/network/application-cache;1"
#define NS_APPLICATIONCACHE_CID \
{ /* 463440c5-baad-4f3c-9e50-0b107abe7183 */ \
0x463440c5, \
0xbaad, \
0x4f3c, \
{0x9e, 0x50, 0xb, 0x10, 0x7a, 0xbe, 0x71, 0x83 } \
}
/******************************************************************************
* netwerk/protocol/http/ classes
*/

Просмотреть файл

@ -61,6 +61,7 @@
#include "nsSOCKSSocketProvider.h"
#include "nsCacheService.h"
#include "nsDiskCacheDeviceSQL.h"
#include "nsApplicationCache.h"
#include "nsMimeTypes.h"
#include "nsNetStrings.h"
#include "nsDNSPrefetch.h"
@ -211,6 +212,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAboutCacheEntry)
#ifdef NECKO_OFFLINE_CACHE
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsOfflineCacheDevice, nsOfflineCacheDevice::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsApplicationCacheNamespace)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsApplicationCache)
#endif
#ifdef NECKO_PROTOCOL_file
@ -709,6 +711,7 @@ NS_DEFINE_NAMED_CID(NS_CACHESERVICE_CID);
#ifdef NECKO_OFFLINE_CACHE
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHESERVICE_CID);
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHENAMESPACE_CID);
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHE_CID);
#endif
#ifdef NECKO_COOKIES
NS_DEFINE_NAMED_CID(NS_COOKIEMANAGER_CID);
@ -833,6 +836,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
#ifdef NECKO_OFFLINE_CACHE
{ &kNS_APPLICATIONCACHESERVICE_CID, false, NULL, nsOfflineCacheDeviceConstructor },
{ &kNS_APPLICATIONCACHENAMESPACE_CID, false, NULL, nsApplicationCacheNamespaceConstructor },
{ &kNS_APPLICATIONCACHE_CID, false, NULL, nsApplicationCacheConstructor },
#endif
#ifdef NECKO_COOKIES
{ &kNS_COOKIEMANAGER_CID, false, NULL, nsICookieServiceConstructor },
@ -964,6 +968,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
#ifdef NECKO_OFFLINE_CACHE
{ NS_APPLICATIONCACHESERVICE_CONTRACTID, &kNS_APPLICATIONCACHESERVICE_CID },
{ NS_APPLICATIONCACHENAMESPACE_CONTRACTID, &kNS_APPLICATIONCACHENAMESPACE_CID },
{ NS_APPLICATIONCACHE_CONTRACTID, &kNS_APPLICATIONCACHE_CID },
#endif
#ifdef NECKO_COOKIES
{ NS_COOKIEMANAGER_CONTRACTID, &kNS_COOKIEMANAGER_CID },

62
netwerk/cache/nsApplicationCache.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,62 @@
/* vim:set ts=2 sw=2 sts=2 et cin: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by Mozilla Corporation are Copyright (C) 2010
* Mozilla Corporation. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
class nsApplicationCache : public nsIApplicationCache
, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPLICATIONCACHE
nsApplicationCache(nsOfflineCacheDevice *device,
const nsACString &group,
const nsACString &clientID);
nsApplicationCache();
virtual ~nsApplicationCache();
void MarkInvalid();
private:
nsRefPtr<nsOfflineCacheDevice> mDevice;
nsCString mGroup;
nsCString mClientID;
PRBool mValid;
};

61
netwerk/cache/nsDiskCacheDeviceSQL.cpp поставляемый
Просмотреть файл

@ -41,6 +41,7 @@
#include "nsDiskCache.h"
#include "nsDiskCacheDeviceSQL.h"
#include "nsCacheService.h"
#include "nsApplicationCache.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
@ -594,32 +595,16 @@ nsApplicationCacheNamespace::GetData(nsACString &out)
* nsApplicationCache
*/
class nsApplicationCache : public nsIApplicationCache
, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPLICATIONCACHE
nsApplicationCache(nsOfflineCacheDevice *device,
const nsACString &group,
const nsACString &clientID);
virtual ~nsApplicationCache();
void MarkInvalid() { mValid = PR_FALSE; }
private:
nsRefPtr<nsOfflineCacheDevice> mDevice;
nsCString mGroup;
nsCString mClientID;
PRBool mValid;
};
NS_IMPL_ISUPPORTS2(nsApplicationCache,
nsIApplicationCache,
nsISupportsWeakReference)
nsApplicationCache::nsApplicationCache()
: mDevice(nsnull)
, mValid(PR_TRUE)
{
}
nsApplicationCache::nsApplicationCache(nsOfflineCacheDevice *device,
const nsACString &group,
const nsACString &clientID)
@ -632,6 +617,9 @@ nsApplicationCache::nsApplicationCache(nsOfflineCacheDevice *device,
nsApplicationCache::~nsApplicationCache()
{
if (!mDevice)
return;
mDevice->mCaches.Remove(mClientID);
// If this isn't an active cache anymore, it can be destroyed.
@ -639,6 +627,24 @@ nsApplicationCache::~nsApplicationCache()
Discard();
}
void
nsApplicationCache::MarkInvalid()
{
mValid = PR_FALSE;
}
NS_IMETHODIMP
nsApplicationCache::InitAsHandle(const nsACString &groupId,
const nsACString &clientId)
{
NS_ENSURE_FALSE(mDevice, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(mGroup.IsEmpty(), NS_ERROR_ALREADY_INITIALIZED);
mGroup = groupId;
mClientID = clientId;
return NS_OK;
}
NS_IMETHODIMP
nsApplicationCache::GetGroupID(nsACString &out)
{
@ -656,6 +662,8 @@ nsApplicationCache::GetClientID(nsACString &out)
NS_IMETHODIMP
nsApplicationCache::GetActive(PRBool *out)
{
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
*out = mDevice->IsActiveCache(mGroup, mClientID);
return NS_OK;
}
@ -664,6 +672,7 @@ NS_IMETHODIMP
nsApplicationCache::Activate()
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
mDevice->ActivateCache(mGroup, mClientID);
return NS_OK;
@ -673,6 +682,7 @@ NS_IMETHODIMP
nsApplicationCache::Discard()
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
mValid = PR_FALSE;
@ -689,6 +699,7 @@ nsApplicationCache::MarkEntry(const nsACString &key,
PRUint32 typeBits)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->MarkEntry(mClientID, key, typeBits);
}
@ -699,6 +710,7 @@ nsApplicationCache::UnmarkEntry(const nsACString &key,
PRUint32 typeBits)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->UnmarkEntry(mClientID, key, typeBits);
}
@ -708,6 +720,7 @@ nsApplicationCache::GetTypes(const nsACString &key,
PRUint32 *typeBits)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->GetTypes(mClientID, key, typeBits);
}
@ -718,6 +731,7 @@ nsApplicationCache::GatherEntries(PRUint32 typeBits,
char *** keys)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->GatherEntries(mClientID, typeBits, count, keys);
}
@ -726,6 +740,7 @@ NS_IMETHODIMP
nsApplicationCache::AddNamespaces(nsIArray *namespaces)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
if (!namespaces)
return NS_OK;
@ -757,6 +772,7 @@ nsApplicationCache::GetMatchingNamespace(const nsACString &key,
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->GetMatchingNamespace(mClientID, key, out);
}
@ -765,6 +781,7 @@ NS_IMETHODIMP
nsApplicationCache::GetUsage(PRUint32 *usage)
{
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mDevice, NS_ERROR_NOT_AVAILABLE);
return mDevice->GetUsage(mClientID, usage);
}

Просмотреть файл

@ -184,6 +184,21 @@ class StartRequestEvent : public ChannelEvent
nsCString mSecurityInfoSerialization;
};
bool
HttpChannelChild::RecvAssociateApplicationCache(const nsCString &groupID,
const nsCString &clientID)
{
nsresult rv;
mApplicationCache = do_CreateInstance(
NS_APPLICATIONCACHE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return true;
mLoadedFromApplicationCache = PR_TRUE;
mApplicationCache->InitAsHandle(groupID, clientID);
return true;
}
bool
HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
const PRBool& useResponseHead,
@ -878,6 +893,22 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
return NS_OK;
}
nsCString appCacheClientId;
if (mInheritApplicationCache) {
// Pick up an application cache from the notification
// callbacks if available
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
GetCallback(appCacheContainer);
if (appCacheContainer) {
nsCOMPtr<nsIApplicationCache> appCache;
rv = appCacheContainer->GetApplicationCache(getter_AddRefs(appCache));
if (NS_SUCCEEDED(rv) && appCache) {
appCache->GetClientID(appCacheClientId);
}
}
}
//
// Send request to the chrome process...
//
@ -902,7 +933,8 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
mRequestHeaders, mRequestHead.Method(), uploadStreamData,
uploadStreamInfo, mPriority, mRedirectionLimit,
mAllowPipelining, mForceAllowThirdPartyCookie, mSendResumeAt,
mStartPos, mEntityID);
mStartPos, mEntityID, mChooseApplicationCache,
appCacheClientId);
return NS_OK;
}
@ -1047,13 +1079,16 @@ HttpChannelChild::SetNewListener(nsIStreamListener *listener,
NS_IMETHODIMP
HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
{
DROP_DEAD();
NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
{
// FIXME: redirects call. so stub OK for now. Fix in bug 536295.
return NS_ERROR_NOT_IMPLEMENTED;
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
mApplicationCache = aApplicationCache;
return NS_OK;
}
//-----------------------------------------------------------------------------
@ -1061,34 +1096,43 @@ HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpChannelChild::GetLoadedFromApplicationCache(PRBool *retval)
HttpChannelChild::GetLoadedFromApplicationCache(PRBool *aLoadedFromApplicationCache)
{
// FIXME: stub for bug 536295
*retval = 0;
*aLoadedFromApplicationCache = mLoadedFromApplicationCache;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetInheritApplicationCache(PRBool *aInheritApplicationCache)
HttpChannelChild::GetInheritApplicationCache(PRBool *aInherit)
{
DROP_DEAD();
*aInherit = mInheritApplicationCache;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetInheritApplicationCache(PRBool aInheritApplicationCache)
HttpChannelChild::SetInheritApplicationCache(PRBool aInherit)
{
// FIXME: Browser calls this early, so stub OK for now. Fix in bug 536295.
mInheritApplicationCache = aInherit;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetChooseApplicationCache(PRBool *aChooseApplicationCache)
HttpChannelChild::GetChooseApplicationCache(PRBool *aChoose)
{
DROP_DEAD();
*aChoose = mChooseApplicationCache;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetChooseApplicationCache(PRBool aChooseApplicationCache)
HttpChannelChild::SetChooseApplicationCache(PRBool aChoose)
{
// FIXME: Browser calls this early, so stub OK for now. Fix in bug 536295.
mChooseApplicationCache = aChoose;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::MarkOfflineCacheEntryAsForeign()
{
SendMarkOfflineCacheEntryAsForeign();
return NS_OK;
}

Просмотреть файл

@ -141,6 +141,8 @@ protected:
const PRUint32& redirectFlags,
const nsHttpResponseHead& responseHead);
bool RecvRedirect3Complete();
bool RecvAssociateApplicationCache(const nsCString& groupID,
const nsCString& clientID);
bool RecvDeleteSelf();
bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nsnull);

Просмотреть файл

@ -54,6 +54,8 @@
#include "nsSerializationHelper.h"
#include "nsISerializable.h"
#include "nsIAssociatedContentSecurity.h"
#include "nsIApplicationCacheService.h"
#include "nsIOfflineCacheUpdate.h"
namespace mozilla {
namespace net {
@ -110,7 +112,9 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
const PRBool& forceAllowThirdPartyCookie,
const bool& doResumeAt,
const PRUint64& startPos,
const nsCString& entityID)
const nsCString& entityID,
const bool& chooseApplicationCache,
const nsCString& appCacheClientID)
{
nsCOMPtr<nsIURI> uri(aURI);
nsCOMPtr<nsIURI> originalUri(aOriginalURI);
@ -176,6 +180,41 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
httpChan->SetAllowPipelining(allowPipelining);
httpChan->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
do_QueryInterface(mChannel);
nsCOMPtr<nsIApplicationCacheService> appCacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
PRBool setChooseApplicationCache = chooseApplicationCache;
if (appCacheChan && appCacheService) {
// We might potentially want to drop this flag (that is TRUE by default)
// after we succefully associate the channel with an application cache
// reported by the channel child. Dropping it here may be too early.
appCacheChan->SetInheritApplicationCache(PR_FALSE);
if (!appCacheClientID.IsEmpty()) {
nsCOMPtr<nsIApplicationCache> appCache;
rv = appCacheService->GetApplicationCache(appCacheClientID,
getter_AddRefs(appCache));
if (NS_SUCCEEDED(rv)) {
appCacheChan->SetApplicationCache(appCache);
setChooseApplicationCache = PR_FALSE;
}
}
if (setChooseApplicationCache) {
nsCOMPtr<nsIOfflineCacheUpdateService> offlineUpdateService =
do_GetService("@mozilla.org/offlinecacheupdate-service;1", &rv);
if (NS_SUCCEEDED(rv)) {
rv = offlineUpdateService->OfflineAppAllowedForURI(uri,
nsnull,
&setChooseApplicationCache);
if (setChooseApplicationCache && NS_SUCCEEDED(rv))
appCacheChan->SetChooseApplicationCache(PR_TRUE);
}
}
}
rv = httpChan->AsyncOpen(mChannelListener, nsnull);
if (NS_FAILED(rv))
return SendCancelEarly(rv);
@ -273,6 +312,14 @@ HttpChannelParent::RecvDocumentChannelCleanup()
return true;
}
bool
HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
{
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
httpChan->MarkOfflineCacheEntryAsForeign();
return true;
}
//-----------------------------------------------------------------------------
// nsIRequestObserver and nsIStreamListener methods equivalents
//-----------------------------------------------------------------------------
@ -296,6 +343,22 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
nsCString cachedCharset;
chan->GetCacheTokenCachedCharset(cachedCharset);
PRBool loadedFromApplicationCache;
chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
if (loadedFromApplicationCache) {
nsCOMPtr<nsIApplicationCache> appCache;
chan->GetApplicationCache(getter_AddRefs(appCache));
nsCString appCacheGroupId;
nsCString appCacheClientId;
appCache->GetGroupID(appCacheGroupId);
appCache->GetClientID(appCacheClientId);
if (mIPCClosed ||
!SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
{
return NS_ERROR_UNEXPECTED;
}
}
nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest);
if (encodedChannel)
encodedChannel->SetApplyConversion(PR_FALSE);

Просмотреть файл

@ -96,7 +96,9 @@ protected:
const PRBool& forceAllowThirdPartyCookie,
const bool& doResumeAt,
const PRUint64& startPos,
const nsCString& entityID);
const nsCString& entityID,
const bool& chooseApplicationCache,
const nsCString& appCacheClientID);
virtual bool RecvSetPriority(const PRUint16& priority);
virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
@ -110,6 +112,7 @@ protected:
const PRInt32& broken,
const PRInt32& no);
virtual bool RecvDocumentChannelCleanup();
virtual bool RecvMarkOfflineCacheEntryAsForeign();
virtual void ActorDestroy(ActorDestroyReason why);

Просмотреть файл

@ -76,7 +76,9 @@ parent:
PRBool forceAllowThirdPartyCookie,
bool resumeAt,
PRUint64 startPos,
nsCString entityID);
nsCString entityID,
bool chooseApplicationCache,
nsCString appCacheClientID);
SetPriority(PRUint16 priority);
@ -99,6 +101,21 @@ parent:
// partial cleanup on parent.
DocumentChannelCleanup();
// This might have to be sync. If this fails we must fail the document load
// to avoid endless loop.
//
// Explanation: the document loaded was loaded from the offline cache. But
// the cache group id (the manifest URL) of the cache group it was loaded
// from is different then the manifest the document refers to in the html
// tag. If we detect this during the cache selection algorithm, we must not
// load this document from the offline cache group it was just loaded from.
// Marking the cache entry as foreign in its cache group will prevent
// the document to load from the bad offline cache group. After it is marked,
// we reload the document to take the effect. If we fail to mark the entry
// as foreign, we will end up in the same situation and reload again and
// again, indefinitely.
MarkOfflineCacheEntryAsForeign();
__delete__();
child:
@ -135,6 +152,10 @@ child:
// Called if redirect successful so that child can complete setup.
Redirect3Complete();
// Associte the child with an application ids
AssociateApplicationCache(nsCString groupID,
nsCString clientID);
// Tell child to delete channel (all IPDL deletes must be done from child to
// avoid races: see bug 591708).
DeleteSelf();

Просмотреть файл

@ -4533,6 +4533,25 @@ nsHttpChannel::SetChooseApplicationCache(PRBool aChoose)
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::MarkOfflineCacheEntryAsForeign()
{
if (!mApplicationCache)
return NS_ERROR_NOT_AVAILABLE;
nsresult rv;
nsCAutoString cacheKey;
rv = GenerateCacheKey(mPostID, cacheKey);
NS_ENSURE_SUCCESS(rv, rv);
rv = mApplicationCache->MarkEntry(cacheKey,
nsIApplicationCache::ITEM_FOREIGN);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsIAsyncVerifyRedirectCallback
//-----------------------------------------------------------------------------

Просмотреть файл

@ -46,22 +46,47 @@ MODULE = prefetch
LIBRARY_NAME = prefetch_s
LIBXUL_LIBRARY = 1
ifdef MOZ_IPC
EXPORTS_NAMESPACES = mozilla/docshell
EXPORTS_mozilla/docshell += \
OfflineCacheUpdateParent.h \
OfflineCacheUpdateChild.h \
$(NULL)
endif
CPPSRCS = \
nsPrefetchService.cpp \
nsOfflineCacheUpdate.cpp \
nsOfflineCacheUpdateService.cpp \
OfflineCacheUpdateGlue.cpp \
$(NULL)
ifdef MOZ_IPC
CPPSRCS += \
OfflineCacheUpdateChild.cpp \
OfflineCacheUpdateParent.cpp
endif
XPIDLSRCS = \
nsIPrefetchService.idl \
nsIOfflineCacheUpdate.idl \
$(NULL)
EXPORTS = \
nsCPrefetchService.h \
$(NULL)
LOCAL_INCLUDES = \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/content/events/src \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
# vim: ts=4 sw=4 noexpandtab

Просмотреть файл

@ -0,0 +1,533 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "OfflineCacheUpdateChild.h"
#include "nsOfflineCacheUpdate.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
#include "nsIApplicationCacheContainer.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIApplicationCacheService.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDOMWindow.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 "prlog.h"
#include "nsIAsyncVerifyRedirectCallback.h"
static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nsnull;
#if defined(PR_LOGGING)
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
// set NSPR_LOG_FILE=offlineupdate.log
//
// this enables PR_LOG_ALWAYS level information and places all output in
// the file offlineupdate.log
//
extern PRLogModuleInfo *gOfflineCacheUpdateLog;
#endif
#define LOG(args) PR_LOG(gOfflineCacheUpdateLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gOfflineCacheUpdateLog, 4)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild::nsISupports
//-----------------------------------------------------------------------------
NS_INTERFACE_MAP_BEGIN(OfflineCacheUpdateChild)
NS_INTERFACE_MAP_ENTRY(nsIOfflineCacheUpdate)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(OfflineCacheUpdateChild)
NS_IMPL_RELEASE_WITH_DESTROY(OfflineCacheUpdateChild, RefcountHitZero())
void
OfflineCacheUpdateChild::RefcountHitZero()
{
if (mIPCActivated) {
// ContentChild::DeallocPOfflineCacheUpdate will delete this
OfflineCacheUpdateChild::Send__delete__(this);
} else {
delete this; // we never opened IPDL channel
}
}
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateChild::OfflineCacheUpdateChild(nsIDOMWindow* aWindow)
: mState(STATE_UNINITIALIZED)
, mIsUpgrade(PR_FALSE)
, mIPCActivated(PR_FALSE)
, mWindow(aWindow)
{
}
OfflineCacheUpdateChild::~OfflineCacheUpdateChild()
{
LOG(("OfflineCacheUpdateChild::~OfflineCacheUpdateChild [%p]", this));
}
nsresult
OfflineCacheUpdateChild::GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers)
{
for (PRInt32 i = 0; i < mWeakObservers.Count(); i++) {
nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
do_QueryReferent(mWeakObservers[i]);
if (observer)
aObservers.AppendObject(observer);
else
mWeakObservers.RemoveObjectAt(i--);
}
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
aObservers.AppendObject(mObservers[i]);
}
return NS_OK;
}
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;
PRBool 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 defined(PR_LOGGING)
if (LOG_ENABLED()) {
nsCAutoString clientID;
if (aApplicationCache) {
aApplicationCache->GetClientID(clientID);
}
LOG(("Update %p: associating app cache %s to document %p",
this, clientID.get(), aDocument));
}
#endif
rv = container->SetApplicationCache(aApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// OfflineCacheUpdateChild::nsIOfflineCacheUpdate
//-----------------------------------------------------------------------------
NS_IMETHODIMP
OfflineCacheUpdateChild::Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument)
{
nsresult rv;
// Make sure the service has been initialized
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (!service)
return NS_ERROR_FAILURE;
LOG(("OfflineCacheUpdateChild::Init [%p]", this));
// Only http and https applications are supported.
PRBool 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;
mState = STATE_INITIALIZED;
if (aDocument)
SetDocument(aDocument);
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::InitPartial(nsIURI *aManifestURI,
const nsACString& clientID,
nsIURI *aDocumentURI)
{
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::GetUpdateDomain(nsACString &aUpdateDomain)
{
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
aUpdateDomain = mUpdateDomain;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetStatus(PRUint16 *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(PRBool *aPartial)
{
*aPartial = PR_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(PRBool *aSucceeded)
{
NS_ENSURE_TRUE(mState == STATE_FINISHED, NS_ERROR_NOT_AVAILABLE);
*aSucceeded = mSucceeded;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::GetIsUpgrade(PRBool *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::AddObserver(nsIOfflineCacheUpdateObserver *aObserver,
PRBool 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 (PRInt32 i = 0; i < mWeakObservers.Count(); i++) {
nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
do_QueryReferent(mWeakObservers[i]);
if (observer == aObserver) {
mWeakObservers.RemoveObjectAt(i);
return NS_OK;
}
}
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
if (mObservers[i] == aObserver) {
mObservers.RemoveObjectAt(i);
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateChild::Schedule()
{
LOG(("OfflineCacheUpdateChild::Schedule [%p]", this));
#ifdef MOZ_IPC
NS_ASSERTION(mWindow, "Window must be provided to the offline cache update child");
#endif
nsCOMPtr<nsPIDOMWindow> piWindow =
do_QueryInterface(mWindow);
mWindow = nsnull;
nsIDocShell *docshell = piWindow->GetDocShell();
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(docshell);
if (!item) {
NS_WARNING("doc shell tree item is null");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShellTreeOwner> owner;
item->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
if (!tabchild) {
NS_WARNING("tab is null");
return NS_ERROR_FAILURE;
}
// because owner implements nsITabChild, we can assume that it is
// the one and only TabChild.
mozilla::dom::TabChild* child = static_cast<mozilla::dom::TabChild*>(tabchild.get());
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-added"));
observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-added",
nsnull);
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 != nsnull;
// 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.
child->SendPOfflineCacheUpdateConstructor(this,
IPC::URI(mManifestURI),
IPC::URI(mDocumentURI),
mClientID,
stickDocument);
mIPCActivated = PR_TRUE;
this->AddRef();
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;
rv = GatherObservers(observers);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 i = 0; i < observers.Count(); i++)
observers[i]->ApplicationCacheAvailable(cache);
return true;
}
bool
OfflineCacheUpdateChild::RecvNotifyStateEvent(const PRUint32 &event)
{
LOG(("OfflineCacheUpdateChild::RecvNotifyStateEvent [%p]", this));
// 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;
nsresult rv = GatherObservers(observers);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 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));
nsRefPtr<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",
nsnull);
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().
this->Release();
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsOfflineCacheUpdateChild_h
#define nsOfflineCacheUpdateChild_h
#include "mozilla/docshell/POfflineCacheUpdateChild.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsICacheService.h"
#include "nsIDOMDocument.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIURI.h"
#include "nsString.h"
#include "nsWeakReference.h"
namespace mozilla {
namespace docshell {
class OfflineCacheUpdateChild : public nsIOfflineCacheUpdate
, public POfflineCacheUpdateChild
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATE
virtual bool
RecvNotifyStateEvent(const PRUint32& stateEvent);
virtual bool
RecvAssociateDocuments(
const nsCString& cacheGroupId,
const nsCString& cacheClientId);
virtual bool
RecvFinish(const bool& succeded,
const bool& isUpgrade);
OfflineCacheUpdateChild(nsIDOMWindow* aWindow);
~OfflineCacheUpdateChild();
void SetDocument(nsIDOMDocument *aDocument);
private:
nsresult AssociateDocument(nsIDOMDocument *aDocument,
nsIApplicationCache *aApplicationCache);
nsresult GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
nsresult Finish();
void RefcountHitZero();
enum {
STATE_UNINITIALIZED,
STATE_INITIALIZED,
STATE_CHECKING,
STATE_DOWNLOADING,
STATE_CANCELLED,
STATE_FINISHED
} mState;
PRPackedBool mIsUpgrade;
PRPackedBool mSucceeded;
PRPackedBool mIPCActivated;
nsCString mUpdateDomain;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCString mClientID;
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<nsIDOMWindow> mWindow;
};
}
}
#endif

Просмотреть файл

@ -0,0 +1,234 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#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 "prlog.h"
#if defined(PR_LOGGING)
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
// set NSPR_LOG_FILE=offlineupdate.log
//
// this enables PR_LOG_ALWAYS level information and places all output in
// the file offlineupdate.log
//
extern PRLogModuleInfo *gOfflineCacheUpdateLog;
#endif
#define LOG(args) PR_LOG(gOfflineCacheUpdateLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gOfflineCacheUpdateLog, 4)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateGlue::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS3(OfflineCacheUpdateGlue,
nsIOfflineCacheUpdate,
nsIOfflineCacheUpdateObserver,
nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateGlue <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateGlue::OfflineCacheUpdateGlue()
{
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",
nsnull);
LOG(("Done offline-cache-update-added"));
}
if (!EnsureUpdate())
return NS_ERROR_NULL_POINTER;
// Do not use weak reference, we must survive!
mUpdate->AddObserver(this, PR_FALSE);
return mUpdate->Schedule();
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument)
{
if (!EnsureUpdate())
return NS_ERROR_NULL_POINTER;
mDocumentURI = aDocumentURI;
if (aDocument)
SetDocument(aDocument);
return mUpdate->Init(aManifestURI, aDocumentURI, nsnull);
}
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;
PRBool loadedFromAppCache;
appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
if (loadedFromAppCache)
return;
if (EnsureUpdate()) {
mUpdate->StickDocument(mDocumentURI);
}
mDocument = aDocument;
}
NS_IMETHODIMP
OfflineCacheUpdateGlue::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate, PRUint32 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",
nsnull);
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 defined(PR_LOGGING)
if (LOG_ENABLED()) {
nsCAutoString clientID;
if (aApplicationCache) {
aApplicationCache->GetClientID(clientID);
}
LOG(("Update %p: associating app cache %s to document %p",
this, clientID.get(), mDocument));
}
#endif
rv = container->SetApplicationCache(aApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
}
}

Просмотреть файл

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsOfflineCacheUpdateGlue_h
#define nsOfflineCacheUpdateGlue_h
#include "nsIOfflineCacheUpdate.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsString.h"
#include "nsWeakReference.h"
class nsOfflineCacheUpdate;
namespace mozilla {
namespace docshell {
// Like FORWARD_SAFE except methods:
// Schedule
// Init
#define NS_ADJUSTED_FORWARD_NSIOFFLINECACHEUPDATE(_to) \
NS_SCRIPTABLE NS_IMETHOD GetStatus(PRUint16 *aStatus) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetStatus(aStatus); } \
NS_SCRIPTABLE NS_IMETHOD GetPartial(PRBool *aPartial) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetPartial(aPartial); } \
NS_SCRIPTABLE NS_IMETHOD GetIsUpgrade(PRBool *aIsUpgrade) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsUpgrade(aIsUpgrade); } \
NS_SCRIPTABLE NS_IMETHOD GetUpdateDomain(nsACString & aUpdateDomain) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUpdateDomain(aUpdateDomain); } \
NS_SCRIPTABLE NS_IMETHOD GetManifestURI(nsIURI **aManifestURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetManifestURI(aManifestURI); } \
NS_SCRIPTABLE NS_IMETHOD GetSucceeded(PRBool *aSucceeded) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetSucceeded(aSucceeded); } \
NS_SCRIPTABLE NS_IMETHOD InitPartial(nsIURI *aManifestURI, const nsACString & aClientID, nsIURI *aDocumentURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->InitPartial(aManifestURI, aClientID, aDocumentURI); } \
NS_SCRIPTABLE NS_IMETHOD AddDynamicURI(nsIURI *aURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddDynamicURI(aURI); } \
NS_SCRIPTABLE NS_IMETHOD AddObserver(nsIOfflineCacheUpdateObserver *aObserver, PRBool aHoldWeak) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddObserver(aObserver, aHoldWeak); } \
NS_SCRIPTABLE NS_IMETHOD RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver) { return !_to ? NS_ERROR_NULL_POINTER : _to->RemoveObserver(aObserver); }
class OfflineCacheUpdateGlue : public nsSupportsWeakReference
, public nsIOfflineCacheUpdate
, public nsIOfflineCacheUpdateObserver
{
public:
NS_DECL_ISUPPORTS
private:
nsIOfflineCacheUpdate* EnsureUpdate();
public:
NS_ADJUSTED_FORWARD_NSIOFFLINECACHEUPDATE(EnsureUpdate())
NS_SCRIPTABLE NS_IMETHOD Schedule(void);
NS_SCRIPTABLE NS_IMETHOD Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument);
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
OfflineCacheUpdateGlue();
~OfflineCacheUpdateGlue();
void SetDocument(nsIDOMDocument *aDocument);
private:
nsRefPtr<nsOfflineCacheUpdate> mUpdate;
/* Document that requested this update */
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIURI> mDocumentURI;
};
}
}
#endif

Просмотреть файл

@ -0,0 +1,169 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "OfflineCacheUpdateParent.h"
#include "nsOfflineCacheUpdate.h"
#include "nsIApplicationCache.h"
static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nsnull;
#if defined(PR_LOGGING)
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
// set NSPR_LOG_FILE=offlineupdate.log
//
// this enables PR_LOG_ALWAYS level information and places all output in
// the file offlineupdate.log
//
extern PRLogModuleInfo *gOfflineCacheUpdateLog;
#endif
#define LOG(args) PR_LOG(gOfflineCacheUpdateLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gOfflineCacheUpdateLog, 4)
namespace mozilla {
namespace docshell {
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(OfflineCacheUpdateParent,
nsIOfflineCacheUpdateObserver)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent <public>
//-----------------------------------------------------------------------------
OfflineCacheUpdateParent::OfflineCacheUpdateParent()
{
// Make sure the service has been initialized
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (!service)
return;
LOG(("OfflineCacheUpdateParent::OfflineCacheUpdateParent [%p]", this));
}
OfflineCacheUpdateParent::~OfflineCacheUpdateParent()
{
LOG(("OfflineCacheUpdateParent::~OfflineCacheUpdateParent [%p]", this));
}
nsresult
OfflineCacheUpdateParent::Schedule(const URI& aManifestURI,
const URI& aDocumentURI,
const nsCString& aClientID,
const bool& stickDocument)
{
LOG(("OfflineCacheUpdateParent::RecvSchedule [%p]", this));
nsRefPtr<nsOfflineCacheUpdate> update;
nsCOMPtr<nsIURI> manifestURI(aManifestURI);
nsCOMPtr<nsIURI> documentURI(aDocumentURI);
nsOfflineCacheUpdateService* service =
nsOfflineCacheUpdateService::EnsureService();
if (!service)
return NS_ERROR_FAILURE;
service->FindUpdate(manifestURI, documentURI, getter_AddRefs(update));
if (!update) {
update = new nsOfflineCacheUpdate();
nsresult rv;
// Leave aDocument argument null. Only glues and children keep
// document instances.
rv = update->Init(manifestURI, documentURI, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = update->Schedule();
NS_ENSURE_SUCCESS(rv, rv);
}
update->AddObserver(this, PR_FALSE);
if (stickDocument) {
nsCOMPtr<nsIURI> stickURI;
documentURI->Clone(getter_AddRefs(stickURI));
update->StickDocument(stickURI);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate, PRUint32 state)
{
LOG(("OfflineCacheUpdateParent::StateEvent [%p]", this));
SendNotifyStateEvent(state);
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.
PRBool isUpgrade;
aUpdate->GetIsUpgrade(&isUpgrade);
PRBool succeeded;
aUpdate->GetSucceeded(&succeeded);
SendFinish(succeeded, isUpgrade);
}
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::ApplicationCacheAvailable(nsIApplicationCache *aApplicationCache)
{
NS_ENSURE_ARG(aApplicationCache);
nsCString cacheClientId;
aApplicationCache->GetClientID(cacheClientId);
nsCString cacheGroupId;
aApplicationCache->GetGroupID(cacheGroupId);
SendAssociateDocuments(cacheGroupId, cacheClientId);
return NS_OK;
}
} // docshell
} // mozilla

Просмотреть файл

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsOfflineCacheUpdateParent_h
#define nsOfflineCacheUpdateParent_h
#include "mozilla/docshell/POfflineCacheUpdateParent.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsString.h"
namespace mozilla {
namespace docshell {
class OfflineCacheUpdateParent : public POfflineCacheUpdateParent
, public nsIOfflineCacheUpdateObserver
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
nsresult
Schedule(const URI& manifestURI,
const URI& documentURI,
const nsCString& clientID,
const bool& stickDocument);
OfflineCacheUpdateParent();
~OfflineCacheUpdateParent();
private:
void RefcountHitZero();
};
}
}
#endif

Просмотреть файл

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
include protocol PBrowser;
include "mozilla/net/NeckoMessageUtils.h";
using IPC::URI;
namespace mozilla {
namespace docshell {
//-------------------------------------------------------------------
protocol POfflineCacheUpdate
{
manager PBrowser;
parent:
__delete__();
child:
NotifyStateEvent(PRUint32 stateEvent);
AssociateDocuments(nsCString cacheGroupId, nsCString cacheClientId);
Finish(bool succeded, bool isUpgrate);
};
}
}

Просмотреть файл

@ -0,0 +1,40 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla Firefox.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation <http://www.mozilla.org/>.
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Jason Duell
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
IPDLSRCS = \
POfflineCacheUpdate.ipdl \
$(NULL)

Просмотреть файл

@ -39,76 +39,44 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsIDOMWindow;
interface nsIDOMNode;
interface nsIDOMDocument;
interface nsIDOMLoadStatus;
interface nsIOfflineCacheUpdate;
interface nsIPrincipal;
interface nsIPrefBranch;
interface nsIApplicationCache;
[scriptable, uuid(a28abeaf-a0b4-4440-b2fe-bc78249710ea)]
[scriptable, uuid(47360d57-8ef4-4a5d-8865-1a27a739ad1a)]
interface nsIOfflineCacheUpdateObserver : nsISupports {
/**
* There was an error updating the cache.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
*/
void error(in nsIOfflineCacheUpdate aUpdate);
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_FINISHED = 10;
/**
* The manifest is being checked for updates
* aUpdate has changed its state.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
* @param event
* See enumeration above
*/
void checking(in nsIOfflineCacheUpdate aUpdate);
void updateStateChanged(in nsIOfflineCacheUpdate aUpdate, in PRUint32 state);
/**
* No update was necessary.
* Informs the observer about an application being available to associate.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
* @param applicationCache
* The application cache instance that has been created or found by the
* update to associate with
*/
void noUpdate(in nsIOfflineCacheUpdate aUpdate);
/**
* The cache group is now obsolete.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
*/
void obsolete(in nsIOfflineCacheUpdate aUpdate);
/**
* Starting to download resources
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
*/
void downloading(in nsIOfflineCacheUpdate aUpdate);
/**
* An item has started downloading.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
* @param aItem
* load status for the item that is being downloaded.
*/
void itemStarted(in nsIOfflineCacheUpdate aUpdate,
in nsIDOMLoadStatus aItem);
/**
* An item has finished loading.
*
* @param aUpdate
* The nsIOfflineCacheUpdate being processed.
* @param aItem
* load status for the item that completed.
*/
void itemCompleted(in nsIOfflineCacheUpdate aUpdate,
in nsIDOMLoadStatus aItem);
void applicationCacheAvailable(in nsIApplicationCache applicationCache);
};
/**
@ -125,7 +93,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports {
* load its items one by one, sending itemCompleted() to any registered
* observers.
*/
[scriptable, uuid(877261bb-b952-4d27-847e-859bdd47c0ec)]
[scriptable, uuid(24605d81-8cf9-4021-8575-7f39aacbf31a)]
interface nsIOfflineCacheUpdate : nsISupports {
/**
* Fetch the status of the running update. This will return a value
@ -169,7 +137,7 @@ interface nsIOfflineCacheUpdate : nsISupports {
* @param aDocumentURI
* The page that is requesting the update.
*/
void init(in nsIURI aManifestURI, in nsIURI aDocumentURI);
void init(in nsIURI aManifestURI, in nsIURI aDocumentURI, in nsIDOMDocument aDocument);
/**
* Initialize the update for partial processing.
@ -200,12 +168,6 @@ interface nsIOfflineCacheUpdate : nsISupports {
*/
void schedule();
/**
* Access to the list of items in the update.
*/
readonly attribute unsigned long count;
nsIDOMLoadStatus item(in unsigned long index);
/**
* Observe loads that are added to the update.
*
@ -254,7 +216,8 @@ interface nsIOfflineCacheUpdateService : nsISupports {
* Otherwise a new update will be scheduled.
*/
nsIOfflineCacheUpdate scheduleUpdate(in nsIURI aManifestURI,
in nsIURI aDocumentURI);
in nsIURI aDocumentURI,
in nsIDOMWindow aWindow);
/**
* Schedule a cache update for a manifest when the document finishes

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -211,11 +211,13 @@ public:
};
class nsOfflineCacheUpdate : public nsIOfflineCacheUpdate
, public nsIOfflineCacheUpdateObserver
, public nsOfflineCacheUpdateOwner
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATE
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
nsOfflineCacheUpdate();
~nsOfflineCacheUpdate();
@ -230,7 +232,7 @@ public:
void LoadCompleted();
void ManifestCheckCompleted(nsresult aStatus,
const nsCString &aManifestHash);
void AddDocument(nsIDOMDocument *aDocument);
void StickDocument(nsIURI *aDocumentURI);
void SetOwner(nsOfflineCacheUpdateOwner *aOwner);
@ -247,19 +249,13 @@ private:
// specified namespaces will be added.
nsresult AddExistingItems(PRUint32 aType,
nsTArray<nsCString>* namespaceFilter = nsnull);
nsresult ScheduleImplicit();
nsresult AssociateDocuments(nsIApplicationCache* cache);
nsresult GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
nsresult NotifyError();
nsresult NotifyChecking();
nsresult NotifyNoUpdate();
nsresult NotifyObsolete();
nsresult NotifyDownloading();
nsresult NotifyStarted(nsOfflineCacheUpdateItem *aItem);
nsresult NotifyCompleted(nsOfflineCacheUpdateItem *aItem);
nsresult AssociateDocument(nsIDOMDocument *aDocument,
nsIApplicationCache *aApplicationCache);
nsresult ScheduleImplicit();
nsresult NotifyState(PRUint32 state);
nsresult Finish();
nsresult FinishNoNotify();
enum {
STATE_UNINITIALIZED,
@ -279,7 +275,6 @@ private:
nsCString mUpdateDomain;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCString mClientID;
@ -299,7 +294,7 @@ private:
nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
/* Documents that requested this update */
nsCOMArray<nsIDOMDocument> mDocuments;
nsCOMArray<nsIURI> mDocumentURIs;
/* Reschedule count. When an update is rescheduled due to
* mismatched manifests, the reschedule count will be increased. */
@ -323,10 +318,15 @@ public:
nsresult Init();
nsresult Schedule(nsOfflineCacheUpdate *aUpdate);
nsresult ScheduleUpdate(nsOfflineCacheUpdate *aUpdate);
nsresult FindUpdate(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsOfflineCacheUpdate **aUpdate);
nsresult Schedule(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIDOMWindow* aWindow,
nsIOfflineCacheUpdate **aUpdate);
virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate);

Просмотреть файл

@ -0,0 +1,612 @@
/* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifdef MOZ_IPC
#include "OfflineCacheUpdateChild.h"
#include "OfflineCacheUpdateParent.h"
#include "nsXULAppAPI.h"
#endif
#include "OfflineCacheUpdateGlue.h"
#include "nsOfflineCacheUpdate.h"
#include "nsCPrefetchService.h"
#include "nsCURILoader.h"
#include "nsIApplicationCacheContainer.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIApplicationCacheService.h"
#include "nsICache.h"
#include "nsICacheService.h"
#include "nsICacheSession.h"
#include "nsICachingChannel.h"
#include "nsIContent.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 "nsICacheEntryDescriptor.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "prlog.h"
#include "nsIAsyncVerifyRedirectCallback.h"
static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nsnull;
#ifdef MOZ_IPC
typedef mozilla::docshell::OfflineCacheUpdateParent OfflineCacheUpdateParent;
typedef mozilla::docshell::OfflineCacheUpdateChild OfflineCacheUpdateChild;
#endif
typedef mozilla::docshell::OfflineCacheUpdateGlue OfflineCacheUpdateGlue;
#if defined(PR_LOGGING)
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
// set NSPR_LOG_FILE=offlineupdate.log
//
// this enables PR_LOG_ALWAYS level information and places all output in
// the file offlineupdate.log
//
PRLogModuleInfo *gOfflineCacheUpdateLog;
#endif
#define LOG(args) PR_LOG(gOfflineCacheUpdateLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gOfflineCacheUpdateLog, 4)
class AutoFreeArray {
public:
AutoFreeArray(PRUint32 count, char **values)
: mCount(count), mValues(values) {};
~AutoFreeArray() { NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mValues); }
private:
PRUint32 mCount;
char **mValues;
};
static nsresult
DropReferenceFromURL(nsIURI * aURI)
{
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (url) {
nsresult rv = url->SetRef(EmptyCString());
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCachePendingUpdate
//-----------------------------------------------------------------------------
class nsOfflineCachePendingUpdate : public nsIWebProgressListener
, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
nsOfflineCachePendingUpdate(nsOfflineCacheUpdateService *aService,
nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument)
: mService(aService)
, mManifestURI(aManifestURI)
, mDocumentURI(aDocumentURI)
{
mDocument = do_GetWeakReference(aDocument);
}
private:
nsRefPtr<nsOfflineCacheUpdateService> mService;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIWeakReference> mDocument;
};
NS_IMPL_ISUPPORTS2(nsOfflineCachePendingUpdate,
nsIWebProgressListener,
nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIWebProgressListener
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnProgressChange(nsIWebProgress *aProgress,
nsIRequest *aRequest,
PRInt32 curSelfProgress,
PRInt32 maxSelfProgress,
PRInt32 curTotalProgress,
PRInt32 maxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest *aRequest,
PRUint32 progressStateFlags,
nsresult aStatus)
{
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);
NS_RELEASE_THIS();
return NS_OK;
}
if (!(progressStateFlags & STATE_STOP)) {
return NS_OK;
}
nsCOMPtr<nsIDOMWindow> window;
aWebProgress->GetDOMWindow(getter_AddRefs(window));
if (!window) return NS_OK;
nsCOMPtr<nsIDOMDocument> progressDoc;
window->GetDocument(getter_AddRefs(progressDoc));
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,
updateDoc, window, getter_AddRefs(update));
}
aWebProgress->RemoveProgressListener(this);
NS_RELEASE_THIS();
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI *location)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const PRUnichar* aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCachePendingUpdate::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRUint32 state)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS3(nsOfflineCacheUpdateService,
nsIOfflineCacheUpdateService,
nsIObserver,
nsISupportsWeakReference)
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService <public>
//-----------------------------------------------------------------------------
nsOfflineCacheUpdateService::nsOfflineCacheUpdateService()
: mDisabled(PR_FALSE)
, mUpdateRunning(PR_FALSE)
{
}
nsOfflineCacheUpdateService::~nsOfflineCacheUpdateService()
{
gOfflineCacheUpdateService = nsnull;
}
nsresult
nsOfflineCacheUpdateService::Init()
{
#if defined(PR_LOGGING)
if (!gOfflineCacheUpdateLog)
gOfflineCacheUpdateLog = PR_NewLogModule("nsOfflineCacheUpdate");
#endif
// 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,
PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
gOfflineCacheUpdateService = this;
return NS_OK;
}
/* static */
nsOfflineCacheUpdateService *
nsOfflineCacheUpdateService::GetInstance()
{
if (!gOfflineCacheUpdateService) {
gOfflineCacheUpdateService = new nsOfflineCacheUpdateService();
if (!gOfflineCacheUpdateService)
return nsnull;
NS_ADDREF(gOfflineCacheUpdateService);
nsresult rv = gOfflineCacheUpdateService->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(gOfflineCacheUpdateService);
return nsnull;
}
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,
nsIDOMDocument *aDocument)
{
LOG(("nsOfflineCacheUpdateService::ScheduleOnDocumentStop [%p, manifestURI=%p, documentURI=%p doc=%p]",
this, aManifestURI, aDocumentURI, aDocument));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
nsCOMPtr<nsISupports> container = doc->GetContainer();
nsCOMPtr<nsIWebProgress> progress = do_QueryInterface(container);
NS_ENSURE_TRUE(progress, NS_ERROR_INVALID_ARG);
// Proceed with cache update
nsRefPtr<nsOfflineCachePendingUpdate> update =
new nsOfflineCachePendingUpdate(this, aManifestURI,
aDocumentURI, 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.
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
nsRefPtr<nsOfflineCacheUpdate> update = mUpdates[0];
mUpdates.RemoveElementAt(0);
mUpdateRunning = PR_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 = PR_TRUE;
return mUpdates[0]->Begin();
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateService::GetNumUpdates(PRUint32 *aNumUpdates)
{
LOG(("nsOfflineCacheUpdateService::GetNumUpdates [%p]", this));
*aNumUpdates = mUpdates.Length();
return NS_OK;
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::GetUpdate(PRUint32 aIndex,
nsIOfflineCacheUpdate **aUpdate)
{
LOG(("nsOfflineCacheUpdateService::GetUpdate [%p, %d]", this, aIndex));
if (aIndex < mUpdates.Length()) {
NS_ADDREF(*aUpdate = mUpdates[aIndex]);
} else {
*aUpdate = nsnull;
}
return NS_OK;
}
nsresult
nsOfflineCacheUpdateService::FindUpdate(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsOfflineCacheUpdate **aUpdate)
{
nsresult rv;
nsRefPtr<nsOfflineCacheUpdate> update;
for (PRUint32 i = 0; i < mUpdates.Length(); i++) {
update = mUpdates[i];
PRBool partial;
rv = update->GetPartial(&partial);
NS_ENSURE_SUCCESS(rv, rv);
if (partial) {
// Partial updates aren't considered
continue;
}
nsCOMPtr<nsIURI> manifestURI;
update->GetManifestURI(getter_AddRefs(manifestURI));
if (manifestURI) {
PRBool equals;
rv = manifestURI->Equals(aManifestURI, &equals);
if (equals) {
update.swap(*aUpdate);
return NS_OK;
}
}
}
return NS_ERROR_NOT_AVAILABLE;
}
nsresult
nsOfflineCacheUpdateService::Schedule(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIDOMWindow* aWindow,
nsIOfflineCacheUpdate **aUpdate)
{
nsCOMPtr<nsIOfflineCacheUpdate> update;
#ifdef MOZ_IPC
if (GeckoProcessType_Default != XRE_GetProcessType()) {
update = new OfflineCacheUpdateChild(aWindow);
}
else
#endif
{
update = new OfflineCacheUpdateGlue();
}
nsresult rv;
rv = update->Init(aManifestURI, aDocumentURI, aDocument);
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,
nsIDOMWindow *aWindow,
nsIOfflineCacheUpdate **aUpdate)
{
return Schedule(aManifestURI, aDocumentURI, nsnull, aWindow, aUpdate);
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIObserver
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateService::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
if (mUpdates.Length() > 0)
mUpdates[0]->Cancel();
mDisabled = PR_TRUE;
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsOfflineCacheUpdateService::nsIOfflineCacheUpdateService
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateService::OfflineAppAllowed(nsIPrincipal *aPrincipal,
nsIPrefBranch *aPrefBranch,
PRBool *aAllowed)
{
nsCOMPtr<nsIURI> codebaseURI;
nsresult rv = aPrincipal->GetURI(getter_AddRefs(codebaseURI));
NS_ENSURE_SUCCESS(rv, rv);
return OfflineAppAllowedForURI(codebaseURI, aPrefBranch, aAllowed);
}
NS_IMETHODIMP
nsOfflineCacheUpdateService::OfflineAppAllowedForURI(nsIURI *aURI,
nsIPrefBranch *aPrefBranch,
PRBool *aAllowed)
{
*aAllowed = PR_FALSE;
if (!aURI)
return NS_OK;
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
if (!innerURI)
return NS_OK;
// only http and https applications can use offline APIs.
PRBool 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;
}
}
nsCOMPtr<nsIPermissionManager> permissionManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!permissionManager) {
return NS_OK;
}
PRUint32 perm;
permissionManager->TestExactPermission(innerURI, "offline-app", &perm);
if (perm == nsIPermissionManager::UNKNOWN_ACTION) {
nsCOMPtr<nsIPrefBranch> branch = aPrefBranch;
if (!branch) {
branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
}
if (branch) {
rv = branch->GetBoolPref("offline-apps.allow_by_default", aAllowed);
if (NS_FAILED(rv)) {
*aAllowed = PR_FALSE;
}
}
return NS_OK;
}
if (perm == nsIPermissionManager::DENY_ACTION) {
return NS_OK;
}
*aAllowed = PR_TRUE;
return NS_OK;
}