Bug 756717 - Implement 'appcache jar' for apps, r=tlee+jduell

This commit is contained in:
Honza Bambas
2012-07-31 02:36:00 -04:00
parent 36ab946393
commit 005f85a9a0
29 changed files with 397 additions and 147 deletions

View File

@@ -886,12 +886,8 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
"mDocument must implement nsIApplicationCacheContainer.");
if (aLoadApplicationCache) {
nsAutoCString groupID;
rv = aLoadApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> groupURI;
rv = NS_NewURI(getter_AddRefs(groupURI), groupID);
rv = aLoadApplicationCache->GetManifestURI(getter_AddRefs(groupURI));
NS_ENSURE_SUCCESS(rv, rv);
bool equal = false;
@@ -975,11 +971,7 @@ nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplication
// Return the uri and invoke the update process for the selected
// application cache.
nsAutoCString groupID;
rv = aLoadApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewURI(aManifestURI, groupID);
rv = aLoadApplicationCache->GetManifestURI(aManifestURI);
NS_ENSURE_SUCCESS(rv, rv);
*aAction = CACHE_SELECTION_UPDATE;

View File

@@ -230,7 +230,8 @@ parent:
* has already been cached (stickDocument=false).
*/
POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI,
nsCString clientID, bool stickDocument);
bool isInBrowserElement, uint32_t appId,
bool stickDocument);
sync PIndexedDB(nsCString asciiOrigin)
returns (bool allowed);

View File

@@ -1177,9 +1177,10 @@ TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
POfflineCacheUpdateChild*
TabChild::AllocPOfflineCacheUpdate(const URIParams& manifestURI,
const URIParams& documentURI,
const nsCString& clientID,
const bool& stickDocument)
const URIParams& documentURI,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument)
{
NS_RUNTIMEABORT("unused");
return nullptr;

View File

@@ -253,9 +253,11 @@ public:
virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal& aPrincipal);
virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor);
virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate(const URIParams& manifestURI,
virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate(
const URIParams& manifestURI,
const URIParams& documentURI,
const nsCString& clientID,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument);
virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateChild* offlineCacheUpdate);

View File

@@ -1028,14 +1028,15 @@ TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
mozilla::docshell::POfflineCacheUpdateParent*
TabParent::AllocPOfflineCacheUpdate(const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const nsCString& aClientID,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument)
{
nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
new mozilla::docshell::OfflineCacheUpdateParent();
nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aClientID,
stickDocument);
nsresult rv = update->Schedule(aManifestURI, aDocumentURI,
isInBrowserElement, appId, stickDocument);
if (NS_FAILED(rv))
return nullptr;

View File

@@ -181,7 +181,8 @@ public:
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdate(
const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const nsCString& aClientID,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument);
virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateParent* actor);

View File

@@ -773,8 +773,16 @@ nsDOMOfflineResourceList::CacheKeys()
if (mCachedKeys)
return NS_OK;
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetOwner());
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
nsAutoCString groupID;
mApplicationCacheService->BuildGroupID(
mManifestURI, loadContext, groupID);
nsCOMPtr<nsIApplicationCache> appCache;
mApplicationCacheService->GetActiveCache(mManifestSpec,
mApplicationCacheService->GetActiveCache(groupID,
getter_AddRefs(appCache));
if (!appCache) {

View File

@@ -14,12 +14,12 @@ function manifestUpdated()
.getService(SpecialPowers.Ci.nsIApplicationCacheService);
var foreign2cache = appCacheService.chooseApplicationCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContext());
OfflineTest.ok(foreign2cache, "Foreign 2 cache present, chosen for foreign2.html");
OfflineTest.is(foreign2cache.groupID, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest")
OfflineTest.is(foreign2cache.manifestURI.asciiSpec, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest")
var foreign1cache = appCacheService.getActiveCache(
var foreign1cache = OfflineTest.getActiveCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest");
OfflineTest.ok(foreign1cache, "Foreign 1 cache loaded");
foreign1cache.discard();
@@ -33,16 +33,16 @@ function onLoaded()
var appCacheService = SpecialPowers.Components.classes["@mozilla.org/network/application-cache-service;1"]
.getService(SpecialPowers.Ci.nsIApplicationCacheService);
var foreign1cache = appCacheService.getActiveCache(
var foreign1cache = OfflineTest.getActiveCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest");
OfflineTest.ok(foreign1cache, "Foreign 1 cache loaded");
var foreign2cache = appCacheService.getActiveCache(
var foreign2cache = OfflineTest.getActiveCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest");
OfflineTest.ok(!foreign2cache, "Foreign 2 cache not present");
foreign1cache = appCacheService.chooseApplicationCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContext());
OfflineTest.ok(!foreign1cache, "foreign2.html not chosen from foreign1 cache");
try

View File

@@ -235,18 +235,33 @@ waitForAdd: function(url, onFinished) {
setTimeout(this.priv(waitFunc), 500);
},
getManifestUrl: function()
manifestURL: function(overload)
{
return window.top.document.documentElement.getAttribute("manifest");
var manifestURLspec = overload || window.top.document.documentElement.getAttribute("manifest");
var ios = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
var baseURI = ios.newURI(window.location.href, null, null);
return ios.newURI(manifestURLspec, null, baseURI);
},
getActiveCache: function()
loadContext: function()
{
return SpecialPowers.wrap(window).QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsILoadContext);
},
getActiveCache: function(overload)
{
// Note that this is the current active cache in the cache stack, not the
// one associated with this window.
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
return serv.getActiveCache(this.getManifestUrl());
var groupID = serv.buildGroupID(this.manifestURL(overload), this.loadContext());
return serv.getActiveCache(groupID);
},
getActiveSession: function()
@@ -271,23 +286,6 @@ priv: function(func)
}
},
checkCustomCache: function(group, url, expectEntry, callback)
{
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
var cache = serv.getActiveCache(group);
var cacheSession = null;
if (cache) {
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
.getService(Ci.nsICacheService);
cacheSession = cacheService.createSession(cache.clientID,
Ci.nsICache.STORE_OFFLINE,
true);
}
this._checkCache(cacheSession, url, expectEntry, callback);
},
checkCacheEntries: function(entries, callback)
{
var checkNextEntry = function() {

View File

@@ -11,6 +11,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
<script class="testbody" type="text/javascript">
@@ -96,12 +97,7 @@ function cleanCache(manifestURL)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
var cache = serv.getActiveCache(manifestURL);
var cache = OfflineTest.getActiveCache(manifestURL);
if (cache)
cache.discard();
}

View File

@@ -126,6 +126,6 @@ if (OfflineTest.setup()) {
</head>
<body>
<iframe name="fallbackFrame" src="http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/namespace1/non-existing.html"></iframe>
<iframe name="fallbackFrame" src=""></iframe>
</body>
</html>

View File

@@ -25,10 +25,10 @@ function manifestUpdated()
.getService(SpecialPowers.Ci.nsIApplicationCacheService);
foreign1cache = appCacheService.chooseApplicationCache(
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContext());
OfflineTest.ok(foreign1cache, "foreign2.html chosen from foreign1 cache");
OfflineTest.is(foreign1cache.groupID, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest")
OfflineTest.is(foreign1cache.manifestURI.asciiSpec, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest")
window.location = "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html";
}

View File

@@ -8,6 +8,7 @@
interface nsIArray;
interface nsIFile;
interface nsIURI;
/**
* Application caches can store a set of namespace entries that affect
@@ -79,7 +80,7 @@ interface nsIApplicationCacheNamespace : nsISupports
* loads. Inactive caches will be removed from the cache when they are
* no longer referenced.
*/
[scriptable, uuid(C3A17414-763B-4235-8BB7-B48324F95DF8)]
[scriptable, uuid(06568DAE-C374-4383-A122-0CC96C7177F2)]
interface nsIApplicationCache : nsISupports
{
/**
@@ -119,8 +120,13 @@ interface nsIApplicationCache : nsISupports
const unsigned long ITEM_OPPORTUNISTIC = 1 << 6;
/**
* The group ID for this cache group. This is the URI of the
* manifest file.
* URI of the manfiest specifying this application cache.
**/
readonly attribute nsIURI manifestURI;
/**
* The group ID for this cache group. It is an internally generated string
* and cannot be used as manifest URL spec.
**/
readonly attribute ACString groupID;

View File

@@ -8,14 +8,23 @@
interface nsIApplicationCache;
interface nsIFile;
interface nsIURI;
interface nsILoadContext;
/**
* The application cache service manages the set of application cache
* groups.
*/
[scriptable, uuid(28adfdc7-6718-4b3e-bdb2-ecfefa3c8910)]
[scriptable, uuid(F94DB1CC-AB56-480b-8F86-40748878557E)]
interface nsIApplicationCacheService : nsISupports
{
/**
* Create group string identifying cache group according the manifest
* URL and the given load context.
*/
ACString buildGroupID(in nsIURI aManifestURL,
in nsILoadContext aLoadContext);
/**
* Create a new, empty application cache for the given cache
* group.
@@ -56,7 +65,8 @@ interface nsIApplicationCacheService : nsISupports
/**
* Try to find the best application cache to serve a resource.
*/
nsIApplicationCache chooseApplicationCache(in ACString key);
nsIApplicationCache chooseApplicationCache(in ACString key,
[optional] in nsILoadContext loadContext);
/**
* Flags the key as being opportunistically cached.

View File

@@ -21,6 +21,18 @@ nsApplicationCacheService::nsApplicationCacheService()
mCacheService = nsCacheService::GlobalInstance();
}
NS_IMETHODIMP
nsApplicationCacheService::BuildGroupID(nsIURI *aManifestURL,
nsILoadContext *aLoadContext,
nsACString &_result)
{
nsresult rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID(
aManifestURL, aLoadContext, _result);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsApplicationCacheService::CreateApplicationCache(const nsACString &group,
nsIApplicationCache **out)
@@ -91,6 +103,7 @@ nsApplicationCacheService::DeactivateGroup(const nsACString &group)
NS_IMETHODIMP
nsApplicationCacheService::ChooseApplicationCache(const nsACString &key,
nsILoadContext *aLoadContext,
nsIApplicationCache **out)
{
if (!mCacheService)
@@ -99,7 +112,8 @@ nsApplicationCacheService::ChooseApplicationCache(const nsACString &key,
nsRefPtr<nsOfflineCacheDevice> device;
nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device));
NS_ENSURE_SUCCESS(rv, rv);
return device->ChooseApplicationCache(key, out);
return device->ChooseApplicationCache(key, aLoadContext, out);
}
NS_IMETHODIMP

View File

@@ -15,6 +15,10 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPLICATIONCACHESERVICE
private:
nsresult GetJARIdentifier(nsIURI *aURI,
nsILoadContext *aLoadContext,
nsACString &_result);
nsRefPtr<nsCacheService> mCacheService;
};

View File

@@ -663,6 +663,19 @@ nsApplicationCache::InitAsHandle(const nsACString &groupId,
return NS_OK;
}
NS_IMETHODIMP
nsApplicationCache::GetManifestURI(nsIURI **out)
{
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), mGroup);
NS_ENSURE_SUCCESS(rv, rv);
rv = uri->CloneIgnoringRef(out);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsApplicationCache::GetGroupID(nsACString &out)
{
@@ -1220,6 +1233,82 @@ nsOfflineCacheDevice::Init()
return NS_OK;
}
namespace {
nsresult
GetGroupForCache(const nsCSubstring &clientID, nsCString &group)
{
group.Assign(clientID);
group.Truncate(group.FindChar('|'));
NS_UnescapeURL(group);
return NS_OK;
}
nsresult
GetJARIdentifier(nsIURI *aURI,
nsILoadContext *aLoadContext,
nsACString &_result)
{
_result.Truncate();
if (!aLoadContext)
return NS_OK;
// These lines are here for compatibility only. We must not fill the
// JAR identifier when this is no-app context, otherwise web content
// offline application cache loads would not be satisfied (cache would
// not be found).
bool isInBrowserElement;
nsresult rv = aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t appId;
rv = aLoadContext->GetAppId(&appId);
NS_ENSURE_SUCCESS(rv, rv);
if (!isInBrowserElement && appId == NECKO_NO_APP_ID)
return NS_OK;
// This load context has some special attributes, create a jar identifier
_result.AppendInt(appId);
_result.Append('+');
_result.Append(isInBrowserElement ? 't' : 'f');
return NS_OK;
}
} // anon namespace
// static
nsresult
nsOfflineCacheDevice::BuildApplicationCacheGroupID(nsIURI *aManifestURL,
nsILoadContext *aLoadContext,
nsACString &_result)
{
nsCOMPtr<nsIURI> newURI;
nsresult rv = aManifestURL->CloneIgnoringRef(getter_AddRefs(newURI));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString manifestSpec;
rv = newURI->GetAsciiSpec(manifestSpec);
NS_ENSURE_SUCCESS(rv, rv);
_result.Assign(manifestSpec);
nsAutoCString jarid;
rv = GetJARIdentifier(aManifestURL, aLoadContext, jarid);
NS_ENSURE_SUCCESS(rv, rv);
// Include JAR ID, i.e. the extended origin if present.
if (!jarid.IsEmpty()) {
_result.Append('#');
_result.Append(jarid);
}
return NS_OK;
}
nsresult
nsOfflineCacheDevice::InitActiveCaches()
{
@@ -2274,34 +2363,49 @@ nsOfflineCacheDevice::DeactivateGroup(const nsACString &group)
}
bool
nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI, const nsCString &clientID)
nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI,
const nsACString &clientID,
nsILoadContext *loadContext)
{
if (mActiveCaches.Contains(clientID)) {
nsAutoCString groupID;
nsresult rv = GetGroupForCache(clientID, groupID);
NS_ENSURE_SUCCESS(rv, false);
if (!mActiveCaches.Contains(clientID))
return false;
nsCOMPtr<nsIURI> groupURI;
rv = NS_NewURI(getter_AddRefs(groupURI), groupID);
if (NS_SUCCEEDED(rv)) {
// When we are choosing an initial cache to load the top
// level document from, the URL of that document must have
// the same origin as the manifest, according to the spec.
// The following check is here because explicit, fallback
// and dynamic entries might have origin different from the
// manifest origin.
if (NS_SecurityCompareURIs(keyURI, groupURI,
GetStrictFileOriginPolicy()))
return true;
}
}
nsAutoCString groupID;
nsresult rv = GetGroupForCache(clientID, groupID);
NS_ENSURE_SUCCESS(rv, false);
return false;
nsCOMPtr<nsIURI> groupURI;
rv = NS_NewURI(getter_AddRefs(groupURI), groupID);
if (NS_FAILED(rv))
return false;
// When we are choosing an initial cache to load the top
// level document from, the URL of that document must have
// the same origin as the manifest, according to the spec.
// The following check is here because explicit, fallback
// and dynamic entries might have origin different from the
// manifest origin.
if (!NS_SecurityCompareURIs(keyURI, groupURI,
GetStrictFileOriginPolicy()))
return false;
// Check the groupID we found is equal to groupID based
// on the load context demanding load from app cache.
// This is check of extended origin.
nsAutoCString demandedGroupID;
rv = BuildApplicationCacheGroupID(groupURI, loadContext, demandedGroupID);
NS_ENSURE_SUCCESS(rv, false);
if (groupID != demandedGroupID)
return false;
return true;
}
nsresult
nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
nsILoadContext *loadContext,
nsIApplicationCache **out)
{
*out = nullptr;
@@ -2329,7 +2433,7 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
rv = statement->GetUTF8String(0, clientID);
NS_ENSURE_SUCCESS(rv, rv);
if (CanUseCache(keyURI, clientID)) {
if (CanUseCache(keyURI, clientID, loadContext)) {
return GetApplicationCache(clientID, out);
}
}
@@ -2361,7 +2465,7 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
rv = nsstatement->GetUTF8String(0, clientID);
NS_ENSURE_SUCCESS(rv, rv);
if (CanUseCache(keyURI, clientID)) {
if (CanUseCache(keyURI, clientID, loadContext)) {
return GetApplicationCache(clientID, out);
}
}
@@ -2428,17 +2532,6 @@ nsOfflineCacheDevice::IsActiveCache(const nsCSubstring &group,
return mActiveCachesByGroup.Get(group, &active) && *active == clientID;
}
nsresult
nsOfflineCacheDevice::GetGroupForCache(const nsACString &clientID,
nsCString &out)
{
out.Assign(clientID);
out.Truncate(out.FindChar('|'));
NS_UnescapeURL(out);
return NS_OK;
}
/**
* Preference accessors
*/

View File

@@ -132,13 +132,14 @@ public:
const nsACString &ownerDomain);
nsresult EvictUnownedEntries(const char *clientID);
static nsresult BuildApplicationCacheGroupID(nsIURI *aManifestURL,
nsILoadContext *aLoadContext,
nsACString &_result);
nsresult ActivateCache(const nsCSubstring &group,
const nsCSubstring &clientID);
bool IsActiveCache(const nsCSubstring &group,
const nsCSubstring &clientID);
nsresult GetGroupForCache(const nsCSubstring &clientID,
nsCString &out);
nsresult CreateApplicationCache(const nsACString &group,
nsIApplicationCache **out);
@@ -151,6 +152,7 @@ public:
nsresult DeactivateGroup(const nsACString &group);
nsresult ChooseApplicationCache(const nsACString &key,
nsILoadContext *loadContext,
nsIApplicationCache **out);
nsresult CacheOpportunistically(nsIApplicationCache* cache,
@@ -199,7 +201,7 @@ private:
nsresult EnableEvictionObserver();
nsresult DisableEvictionObserver();
bool CanUseCache(nsIURI *keyURI, const nsCString &clientID);
bool CanUseCache(nsIURI *keyURI, const nsACString &clientID, nsILoadContext *loadContext);
nsresult MarkEntry(const nsCString &clientID,
const nsACString &key,

View File

@@ -2422,8 +2422,14 @@ nsHttpChannel::OpenCacheEntry(bool usingSSL)
nsCOMPtr<nsIApplicationCacheService> appCacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
if (appCacheService) {
nsCOMPtr<nsILoadContext> loadContext;
GetCallback(loadContext);
if (!loadContext)
LOG((" no load context while choosing application cache"));
nsresult rv = appCacheService->ChooseApplicationCache
(cacheKey, getter_AddRefs(mApplicationCache));
(cacheKey, loadContext, getter_AddRefs(mApplicationCache));
NS_ENSURE_SUCCESS(rv, rv);
}
}

View File

@@ -180,7 +180,8 @@ NS_IMETHODIMP
OfflineCacheUpdateChild::Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIFile *aCustomProfileDir)
nsIFile *aCustomProfileDir,
nsILoadContext *aLoadContext)
{
nsresult rv;
@@ -221,6 +222,8 @@ OfflineCacheUpdateChild::Init(nsIURI *aManifestURI,
if (aDocument)
SetDocument(aDocument);
mLoadContext = aLoadContext;
return NS_OK;
}
@@ -411,11 +414,20 @@ OfflineCacheUpdateChild::Schedule()
// See also nsOfflineCacheUpdate::ScheduleImplicit.
bool stickDocument = mDocument != nullptr;
// Carry load context to the parent
bool isInBrowserElement = false;
uint32_t appId = NECKO_NO_APP_ID;
if (mLoadContext) {
mLoadContext->GetIsInBrowserElement(&isInBrowserElement);
mLoadContext->GetAppId(&appId);
}
// 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, manifestURI, documentURI,
mClientID, stickDocument);
isInBrowserElement, appId,
stickDocument);
mIPCActivated = true;
this->AddRef();

View File

@@ -72,9 +72,8 @@ private:
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCString mClientID;
nsCOMPtr<nsIObserverService> mObserverService;
nsCOMPtr<nsILoadContext> mLoadContext;
/* Clients watching this update for changes */
nsCOMArray<nsIWeakReference> mWeakObservers;

View File

@@ -92,7 +92,8 @@ NS_IMETHODIMP
OfflineCacheUpdateGlue::Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIFile *aCustomProfileDir)
nsIFile *aCustomProfileDir,
nsILoadContext *aLoadContext)
{
if (!EnsureUpdate())
return NS_ERROR_NULL_POINTER;
@@ -102,7 +103,7 @@ OfflineCacheUpdateGlue::Init(nsIURI *aManifestURI,
if (aDocument)
SetDocument(aDocument);
return mUpdate->Init(aManifestURI, aDocumentURI, nullptr, aCustomProfileDir);
return mUpdate->Init(aManifestURI, aDocumentURI, nullptr, aCustomProfileDir, aLoadContext);
}
void

View File

@@ -49,9 +49,10 @@ public:
NS_ADJUSTED_FORWARD_NSIOFFLINECACHEUPDATE(EnsureUpdate())
NS_IMETHOD Schedule(void);
NS_IMETHOD Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIFile *aCustomProfileDir);
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIFile *aCustomProfileDir,
nsILoadContext *aLoadContext);
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER

View File

@@ -23,6 +23,7 @@ using namespace mozilla::ipc;
//
extern PRLogModuleInfo *gOfflineCacheUpdateLog;
#endif
#undef LOG
#define LOG(args) PR_LOG(gOfflineCacheUpdateLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gOfflineCacheUpdateLog, 4)
@@ -33,8 +34,9 @@ namespace docshell {
// OfflineCacheUpdateParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(OfflineCacheUpdateParent,
nsIOfflineCacheUpdateObserver)
NS_IMPL_ISUPPORTS2(OfflineCacheUpdateParent,
nsIOfflineCacheUpdateObserver,
nsILoadContext)
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent <public>
@@ -66,11 +68,16 @@ OfflineCacheUpdateParent::ActorDestroy(ActorDestroyReason why)
nsresult
OfflineCacheUpdateParent::Schedule(const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const nsCString& aClientID,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument)
{
LOG(("OfflineCacheUpdateParent::RecvSchedule [%p]", this));
// Load context members
mIsInBrowserElement = isInBrowserElement;
mAppId = appId;
nsRefPtr<nsOfflineCacheUpdate> update;
nsCOMPtr<nsIURI> manifestURI = DeserializeURI(aManifestURI);
if (!manifestURI)
@@ -85,14 +92,14 @@ OfflineCacheUpdateParent::Schedule(const URIParams& aManifestURI,
if (!service)
return NS_ERROR_FAILURE;
service->FindUpdate(manifestURI, documentURI, getter_AddRefs(update));
service->FindUpdate(manifestURI, this, 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, nullptr, nullptr);
rv = update->Init(manifestURI, documentURI, nullptr, nullptr, this);
NS_ENSURE_SUCCESS(rv, rv);
rv = update->Schedule();
@@ -154,5 +161,64 @@ OfflineCacheUpdateParent::ApplicationCacheAvailable(nsIApplicationCache *aApplic
return NS_OK;
}
//-----------------------------------------------------------------------------
// OfflineCacheUpdateParent::nsILoadContext
//-----------------------------------------------------------------------------
NS_IMETHODIMP
OfflineCacheUpdateParent::GetAssociatedWindow(nsIDOMWindow * *aAssociatedWindow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetTopWindow(nsIDOMWindow * *aTopWindow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetTopFrameElement(nsIDOMElement** aElement)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::IsAppOfType(uint32_t appType, bool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetIsContent(bool *aIsContent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetUsePrivateBrowsing(bool *aUsePrivateBrowsing)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetIsInBrowserElement(bool *aIsInBrowserElement)
{
*aIsInBrowserElement = mIsInBrowserElement;
return NS_OK;
}
NS_IMETHODIMP
OfflineCacheUpdateParent::GetAppId(uint32_t *aAppId)
{
*aAppId = mAppId;
return NS_OK;
}
} // docshell
} // mozilla

View File

@@ -10,6 +10,7 @@
#include "nsIOfflineCacheUpdate.h"
#include "nsString.h"
#include "nsILoadContext.h"
namespace mozilla {
@@ -21,17 +22,20 @@ namespace docshell {
class OfflineCacheUpdateParent : public POfflineCacheUpdateParent
, public nsIOfflineCacheUpdateObserver
, public nsILoadContext
{
typedef mozilla::ipc::URIParams URIParams;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
NS_DECL_NSILOADCONTEXT
nsresult
Schedule(const URIParams& manifestURI,
const URIParams& documentURI,
const nsCString& clientID,
const bool& isInBrowserElement,
const uint32_t& appId,
const bool& stickDocument);
OfflineCacheUpdateParent();
@@ -42,6 +46,9 @@ public:
private:
void RefcountHitZero();
bool mIPCClosed;
bool mIsInBrowserElement;
uint32_t mAppId;
};
} // namespace docshell

View File

@@ -15,6 +15,7 @@ interface nsIPrincipal;
interface nsIPrefBranch;
interface nsIApplicationCache;
interface nsIFile;
interface nsILoadContext;
[scriptable, uuid(47360d57-8ef4-4a5d-8865-1a27a739ad1a)]
interface nsIOfflineCacheUpdateObserver : nsISupports {
@@ -62,7 +63,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports {
* load its items one by one, sending itemCompleted() to any registered
* observers.
*/
[scriptable, uuid(2FA574B8-AE62-426b-BE95-08E6AA957455)]
[scriptable, uuid(D47966B2-1EBC-45c5-8639-2937ED200281)]
interface nsIOfflineCacheUpdate : nsISupports {
/**
* Fetch the status of the running update. This will return a value
@@ -107,7 +108,8 @@ interface nsIOfflineCacheUpdate : nsISupports {
* The page that is requesting the update.
*/
void init(in nsIURI aManifestURI, in nsIURI aDocumentURI, in nsIDOMDocument aDocument,
[optional] in nsIFile aCustomProfileDir);
[optional] in nsIFile aCustomProfileDir,
[optional] in nsILoadContext aLoadContext);
/**
* Initialize the update for partial processing.
@@ -237,5 +239,3 @@ interface nsIOfflineCacheUpdateService : nsISupports {
boolean offlineAppAllowedForURI(in nsIURI aURI,
in nsIPrefBranch aPrefBranch);
};

View File

@@ -1177,7 +1177,8 @@ nsresult
nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMDocument *aDocument,
nsIFile *aCustomProfileDir)
nsIFile *aCustomProfileDir,
nsILoadContext *aLoadContext)
{
nsresult rv;
@@ -1208,18 +1209,16 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
rv = mManifestURI->GetAsciiHost(mUpdateDomain);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString manifestSpec;
rv = GetCacheKey(mManifestURI, manifestSpec);
NS_ENSURE_SUCCESS(rv, rv);
mDocumentURI = aDocumentURI;
nsCOMPtr<nsIApplicationCacheService> cacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mDocumentURI = aDocumentURI;
if (aCustomProfileDir) {
rv = GetCacheKey(aManifestURI, mGroupID);
NS_ENSURE_SUCCESS(rv, rv);
// Create only a new offline application cache in the custom profile
// This is a preload of a new cache.
@@ -1228,7 +1227,7 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
// simply added as well when needed.
mPreviousApplicationCache = nullptr;
rv = cacheService->CreateCustomApplicationCache(manifestSpec,
rv = cacheService->CreateCustomApplicationCache(mGroupID,
aCustomProfileDir,
kCustomProfileQuota,
getter_AddRefs(mApplicationCache));
@@ -1237,11 +1236,16 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
mCustomProfileDir = aCustomProfileDir;
}
else {
rv = cacheService->GetActiveCache(manifestSpec,
rv = cacheService->BuildGroupID(aManifestURI,
aLoadContext,
mGroupID);
NS_ENSURE_SUCCESS(rv, rv);
rv = cacheService->GetActiveCache(mGroupID,
getter_AddRefs(mPreviousApplicationCache));
NS_ENSURE_SUCCESS(rv, rv);
rv = cacheService->CreateApplicationCache(manifestSpec,
rv = cacheService->CreateApplicationCache(mGroupID,
getter_AddRefs(mApplicationCache));
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -1251,6 +1255,8 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
&mPinned);
NS_ENSURE_SUCCESS(rv, rv);
mLoadContext = aLoadContext;
mState = STATE_INITIALIZED;
return NS_OK;
}
@@ -1295,11 +1301,11 @@ nsOfflineCacheUpdate::InitPartial(nsIURI *aManifestURI,
NS_ENSURE_SUCCESS(rv, rv);
}
nsAutoCString groupID;
rv = mApplicationCache->GetGroupID(groupID);
rv = mApplicationCache->GetManifestURI(getter_AddRefs(mManifestURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewURI(getter_AddRefs(mManifestURI), groupID);
nsAutoCString groupID;
rv = mApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aDocumentURI,
@@ -1566,7 +1572,8 @@ nsOfflineCacheUpdate::ManifestCheckCompleted(nsresult aStatus,
new nsOfflineCacheUpdate();
// Leave aDocument argument null. Only glues and children keep
// document instances.
newUpdate->Init(mManifestURI, mDocumentURI, nullptr, mCustomProfileDir);
newUpdate->Init(mManifestURI, mDocumentURI, nullptr,
mCustomProfileDir, mLoadContext);
// In a rare case the manifest will not be modified on the next refetch
// transfer all master document URIs to the new update to ensure that
@@ -1830,6 +1837,12 @@ nsOfflineCacheUpdate::SetOwner(nsOfflineCacheUpdateOwner *aOwner)
mOwner = aOwner;
}
bool
nsOfflineCacheUpdate::IsForGroupID(const nsCSubstring &groupID)
{
return mGroupID == groupID;
}
nsresult
nsOfflineCacheUpdate::UpdateFinished(nsOfflineCacheUpdate *aUpdate)
{

View File

@@ -209,6 +209,8 @@ public:
void SetOwner(nsOfflineCacheUpdateOwner *aOwner);
bool IsForGroupID(const nsCSubstring &groupID);
virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate);
protected:
@@ -254,9 +256,11 @@ private:
bool mObsolete;
nsCString mUpdateDomain;
nsCString mGroupID;
nsCOMPtr<nsIURI> mManifestURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIFile> mCustomProfileDir;
nsCOMPtr<nsILoadContext> mLoadContext;
nsCOMPtr<nsIApplicationCache> mApplicationCache;
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
@@ -308,7 +312,7 @@ public:
nsresult ScheduleUpdate(nsOfflineCacheUpdate *aUpdate);
nsresult FindUpdate(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsILoadContext *aLoadContext,
nsOfflineCacheUpdate **aUpdate);
nsresult Schedule(nsIURI *aManifestURI,

View File

@@ -27,6 +27,7 @@
#include "nsIObserverService.h"
#include "nsIURL.h"
#include "nsIWebProgress.h"
#include "nsIWebNavigation.h"
#include "nsICryptoHash.h"
#include "nsICacheEntryDescriptor.h"
#include "nsIPermissionManager.h"
@@ -399,11 +400,21 @@ nsOfflineCacheUpdateService::GetUpdate(uint32_t aIndex,
nsresult
nsOfflineCacheUpdateService::FindUpdate(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsILoadContext *aLoadContext,
nsOfflineCacheUpdate **aUpdate)
{
nsresult rv;
nsCOMPtr<nsIApplicationCacheService> cacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString groupID;
rv = cacheService->BuildGroupID(aManifestURI,
aLoadContext,
groupID);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsOfflineCacheUpdate> update;
for (uint32_t i = 0; i < mUpdates.Length(); i++) {
update = mUpdates[i];
@@ -417,15 +428,9 @@ nsOfflineCacheUpdateService::FindUpdate(nsIURI *aManifestURI,
continue;
}
nsCOMPtr<nsIURI> manifestURI;
update->GetManifestURI(getter_AddRefs(manifestURI));
if (manifestURI) {
bool equals;
rv = manifestURI->Equals(aManifestURI, &equals);
if (equals) {
update.swap(*aUpdate);
return NS_OK;
}
if (update->IsForGroupID(groupID)) {
update.swap(*aUpdate);
return NS_OK;
}
}
@@ -450,7 +455,14 @@ nsOfflineCacheUpdateService::Schedule(nsIURI *aManifestURI,
nsresult rv;
rv = update->Init(aManifestURI, aDocumentURI, aDocument, aCustomProfileDir);
nsCOMPtr<nsILoadContext> loadContext;
if (aWindow) {
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
loadContext = do_QueryInterface(webNav);
}
rv = update->Init(aManifestURI, aDocumentURI, aDocument,
aCustomProfileDir, loadContext);
NS_ENSURE_SUCCESS(rv, rv);
rv = update->Schedule();