зеркало из https://github.com/mozilla/pjs.git
implement navigator.isLocallyAvailable. b=373231, r=biesi, sr=jst
This commit is contained in:
Родитель
78eff2581b
Коммит
08e612af60
|
@ -39,7 +39,7 @@
|
|||
|
||||
interface nsIDOMOfflineResourceList;
|
||||
|
||||
[scriptable, uuid(609439fa-63e4-4f71-9512-904867f154e7)]
|
||||
[scriptable, uuid(21c6561e-4778-47ed-96d0-eadc46d6a3ec)]
|
||||
interface nsIDOMClientInformation : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -51,6 +51,8 @@ interface nsIDOMClientInformation : nsISupports
|
|||
void registerContentHandler(in DOMString mimeType, in DOMString uri, in DOMString title);
|
||||
void registerProtocolHandler(in DOMString protocol, in DOMString uri, in DOMString title);
|
||||
|
||||
boolean isLocallyAvailable(in DOMString uri, in boolean whenOffline);
|
||||
|
||||
readonly attribute nsIDOMOfflineResourceList offlineResources;
|
||||
};
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "nsStyleCoord.h"
|
||||
#include "nsMimeTypeArray.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsPluginArray.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#ifdef OJI
|
||||
|
@ -8503,6 +8504,77 @@ nsNavigator::RegisterProtocolHandler(const nsAString& aProtocol,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavigator::IsLocallyAvailable(const nsAString &aURI,
|
||||
PRBool aWhenOffline,
|
||||
PRBool *aIsAvailable)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This method of checking the cache will only work for http/https urls
|
||||
PRBool match;
|
||||
rv = uri->SchemeIs("http", &match);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!match) {
|
||||
rv = uri->SchemeIs("https", &match);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!match) return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// Same origin check
|
||||
nsCOMPtr<nsIJSContextStack> stack = do_GetService(sJSStackContractID);
|
||||
NS_ENSURE_TRUE(stack, NS_ERROR_FAILURE);
|
||||
|
||||
JSContext *cx = nsnull;
|
||||
rv = stack->Peek(&cx);
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
|
||||
|
||||
rv = nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx, uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// these load flags cause an error to be thrown if there is no
|
||||
// valid cache entry, and skip the load if there is.
|
||||
// if the cache is busy, assume that it is not yet available rather
|
||||
// than waiting for it to become available.
|
||||
PRUint32 loadFlags = nsIChannel::INHIBIT_CACHING |
|
||||
nsIChannel::LOAD_NO_NETWORK_IO |
|
||||
nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
|
||||
|
||||
if (aWhenOffline) {
|
||||
loadFlags |= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE |
|
||||
nsICachingChannel::LOAD_ONLY_FROM_CACHE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), uri,
|
||||
nsnull, nsnull, nsnull, loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = channel->Open(getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
stream->Close();
|
||||
|
||||
nsresult status;
|
||||
rv = channel->GetStatus(&status);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
rv = httpChannel->GetRequestSucceeded(aIsAvailable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
*aIsAvailable = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavigator::GetOfflineResources(nsIDOMOfflineResourceList **aList)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
_TEST_FILES = \
|
||||
test_offlineResources.html \
|
||||
test_isLocallyAvailable.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>navigator.isLocallyAvailable Test</title>
|
||||
|
||||
<link rel="offline-resource" href="http://localhost:8888/tests/SimpleTest/SimpleTest.js">
|
||||
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function run_test()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
// check invalid urls
|
||||
try {
|
||||
navigator.isLocallyAvailable("http://different.origin.com", false);
|
||||
ok(false, "can't check from a different origin");
|
||||
} catch(e) {
|
||||
ok(true, "can't check from a different origin");
|
||||
}
|
||||
|
||||
try {
|
||||
navigator.isLocallyAvailable("ftp://localhost/blah/blah", false);
|
||||
ok(false, "urls must be http or https");
|
||||
} catch(e) {
|
||||
ok(true, "urls must be http or https");
|
||||
}
|
||||
|
||||
// check an URL that should definitely not be there
|
||||
ok(navigator.isLocallyAvailable("http://localhost:8888/blah/blah/blah",
|
||||
false) == false,
|
||||
"unknown item shouldn't be available online");
|
||||
ok(navigator.isLocallyAvailable("http://localhost:8888/blah/blah/blah",
|
||||
true) == false,
|
||||
"unknown item shouldn't be available offline");
|
||||
|
||||
// check a URL that should be available on and offline
|
||||
var url = "http://localhost:8888/tests/SimpleTest/SimpleTest.js";
|
||||
ok(navigator.isLocallyAvailable(url, false) == true,
|
||||
url + " should be available online");
|
||||
ok(navigator.isLocallyAvailable(url, true) == true,
|
||||
url + " should be available offline");
|
||||
|
||||
// Pull it out of the disk cache
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
var session = cacheService.createSession
|
||||
("HTTP",
|
||||
Components.interfaces.nsICache.STORE_ON_DISK,
|
||||
Components.interfaces.nsICache.STREAM_BASED);
|
||||
var entry = session.openCacheEntry(url, Components.interfaces.nsICache.ACCESS_WRITE, false);
|
||||
entry.doom();
|
||||
entry.close();
|
||||
|
||||
// Now it should be available offline but not online
|
||||
ok(navigator.isLocallyAvailable(url, false) == false,
|
||||
url + " should not be available online");
|
||||
|
||||
ok(navigator.isLocallyAvailable(url, true) == true,
|
||||
url + " should be available offline");
|
||||
|
||||
// Clear the offline cache/ownership on the way out
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Components.interfaces.nsICache.STORE_OFFLINE,
|
||||
true)
|
||||
.QueryInterface(Components.interfaces.nsIOfflineCacheSession);
|
||||
cacheSession.setOwnedKeys(window.location.host,
|
||||
window.location.protocol + "//" + window.location.host + window.location.pathname,
|
||||
0, []);
|
||||
cacheSession.setOwnedKeys(window.location.host, "", 0, []);
|
||||
cacheSession.evictUnownedEntries();
|
||||
|
||||
cacheService.evictEntries(Components.interfaces.nsICache.STORE_OFFLINE);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Give the offline resources some time to load.
|
||||
setTimeout("run_test()", 1000);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -50,7 +50,7 @@ interface nsIFile;
|
|||
* 3) Support for uniquely identifying cached data in cases when the URL
|
||||
* is insufficient (e.g., HTTP form submission).
|
||||
*/
|
||||
[scriptable, uuid(855bcc4d-0987-45b6-b138-3bf0bf407703)]
|
||||
[scriptable, uuid(afafb719-bdf5-49c8-a4a9-db39ec331c9b)]
|
||||
interface nsICachingChannel : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -123,6 +123,12 @@ interface nsICachingChannel : nsISupports
|
|||
* Caching channel specific load flags:
|
||||
*/
|
||||
|
||||
/**
|
||||
* This load flag causes the offline cache to be checked when fetching
|
||||
* a request. It will be set automatically if the browser is offline.
|
||||
*/
|
||||
const unsigned long LOAD_CHECK_OFFLINE_CACHE = 1 << 27;
|
||||
|
||||
/**
|
||||
* This load flag causes the local cache to be skipped when fetching a
|
||||
* request. Unlike LOAD_BYPASS_CACHE, it does not force an end-to-end load
|
||||
|
@ -139,7 +145,8 @@ interface nsICachingChannel : nsISupports
|
|||
/**
|
||||
* This load flag inhibits fetching from the net if the data in the cache
|
||||
* has been evicted. An error of NS_ERROR_DOCUMENT_NOT_CACHED will be sent
|
||||
* to the listener's onStopRequest in this case.
|
||||
* to the listener's onStopRequest in this case. This flag is set
|
||||
* automatically when the application is offline.
|
||||
*/
|
||||
const unsigned long LOAD_ONLY_FROM_CACHE = 1 << 30;
|
||||
|
||||
|
|
|
@ -259,4 +259,11 @@ interface nsIChannel : nsIRequest
|
|||
* should only do so with good reason.
|
||||
*/
|
||||
const unsigned long LOAD_CALL_CONTENT_SNIFFERS = 1 << 21;
|
||||
|
||||
/**
|
||||
* This load flag inhibits fetching from the net. An error of
|
||||
* NS_ERROR_NEEDS_NETWORK will be sent to the listener's onStopRequest
|
||||
* if network IO is necessary to complete the request.
|
||||
*/
|
||||
const unsigned long LOAD_NO_NETWORK_IO = 1 << 22;
|
||||
};
|
||||
|
|
|
@ -208,6 +208,13 @@
|
|||
#define NS_ERROR_NET_INTERRUPT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 71)
|
||||
|
||||
/**
|
||||
* The requested action would require network IO, but
|
||||
* nsIChannel::LOAD_NO_NETWORK_IO was specified.
|
||||
*/
|
||||
#define NS_ERROR_NEEDS_NETWORK \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 72)
|
||||
|
||||
// XXX really need to better rationalize these error codes. are consumers of
|
||||
// necko really expected to know how to discern the meaning of these??
|
||||
|
||||
|
|
|
@ -1662,6 +1662,13 @@ nsFtpState::Connect()
|
|||
mState = FTP_COMMAND_CONNECT;
|
||||
mNextState = FTP_S_USER;
|
||||
|
||||
if (mChannel->HasLoadFlag(nsIChannel::LOAD_NO_NETWORK_IO)){
|
||||
mInternalError = NS_ERROR_NEEDS_NETWORK;
|
||||
mState = FTP_ERROR;
|
||||
CloseWithStatus(mInternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = Process();
|
||||
|
||||
// check for errors.
|
||||
|
|
|
@ -187,7 +187,10 @@ nsresult
|
|||
nsGopherContentStream::OpenSocket(nsIEventTarget *target)
|
||||
{
|
||||
// This function is called to get things started.
|
||||
//
|
||||
|
||||
if (mChannel->HasLoadFlag(nsIChannel::LOAD_NO_NETWORK_IO))
|
||||
return NS_ERROR_NEEDS_NETWORK;
|
||||
|
||||
// We begin by opening a socket to the specified host and wait for the
|
||||
// socket to become writable.
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ nsHttpChannel::Connect(PRBool firstTime)
|
|||
// are we offline?
|
||||
PRBool offline = gIOService->IsOffline();
|
||||
if (offline)
|
||||
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
|
||||
mLoadFlags |= (LOAD_ONLY_FROM_CACHE | LOAD_CHECK_OFFLINE_CACHE);
|
||||
else if (PL_strcmp(mConnectionInfo->ProxyType(), "unknown") == 0)
|
||||
return ResolveProxy(); // Lazily resolve proxy info
|
||||
|
||||
|
@ -330,6 +330,10 @@ nsHttpChannel::Connect(PRBool firstTime)
|
|||
// check to see if authorization headers should be included
|
||||
AddAuthorizationHeaders();
|
||||
|
||||
if (mLoadFlags & LOAD_NO_NETWORK_IO) {
|
||||
return NS_ERROR_NEEDS_NETWORK;
|
||||
}
|
||||
|
||||
// hit the net...
|
||||
rv = SetupTransaction();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -1307,9 +1311,10 @@ nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed)
|
|||
|
||||
// Set the desired cache access mode accordingly...
|
||||
nsCacheAccessMode accessRequested;
|
||||
if (offline || (mLoadFlags & INHIBIT_CACHING)) {
|
||||
if (mLoadFlags & (LOAD_ONLY_FROM_CACHE | INHIBIT_CACHING)) {
|
||||
// If we have been asked to bypass the cache and not write to the
|
||||
// cache, then don't use the cache at all.
|
||||
// cache, then don't use the cache at all. Unless we're actually
|
||||
// offline, which takes precedence over BYPASS_LOCAL_CACHE.
|
||||
if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
accessRequested = nsICache::ACCESS_READ;
|
||||
|
@ -1330,7 +1335,7 @@ nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed)
|
|||
rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE,
|
||||
getter_AddRefs(mCacheEntry));
|
||||
|
||||
if (offline &&
|
||||
if ((mLoadFlags & LOAD_CHECK_OFFLINE_CACHE) &&
|
||||
!(NS_SUCCEEDED(rv) || rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)) {
|
||||
// couldn't find it in the main cache, check the offline cache
|
||||
|
||||
|
@ -1545,10 +1550,12 @@ nsHttpChannel::CheckCache()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
buf.Adopt(0);
|
||||
|
||||
// If we were only granted read access, then assume the entry is valid.
|
||||
// unless it is INHBIT_CACHING
|
||||
if (mCacheAccess == nsICache::ACCESS_READ &&
|
||||
!(mLoadFlags & INHIBIT_CACHING)) {
|
||||
// Don't bother to validate LOAD_ONLY_FROM_CACHE items.
|
||||
// Don't bother to validate items that are read-only,
|
||||
// unless they are read-only because of INHIBIT_CACHING.
|
||||
if (mLoadFlags & LOAD_ONLY_FROM_CACHE ||
|
||||
(mCacheAccess == nsICache::ACCESS_READ &&
|
||||
!(mLoadFlags & INHIBIT_CACHING))) {
|
||||
mCachedContentIsValid = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче