#include "content/browser/service_worker/service_worker_request_handler.h"
+#include <string>
+
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/common/service_worker/service_worker_types.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "webkit/browser/blob/blob_storage_context.h"
namespace content {
int kUserDataKey; // Key value is not important.
class ServiceWorkerRequestInterceptor
- : public net::URLRequestJobFactory::ProtocolHandler {
+ : public net::URLRequestInterceptor {
public:
ServiceWorkerRequestInterceptor() {}
virtual ~ServiceWorkerRequestInterceptor() {}
- virtual net::URLRequestJob* MaybeCreateJob(
+ virtual net::URLRequestJob* MaybeInterceptRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const OVERRIDE {
ServiceWorkerRequestHandler* handler =
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor);
};
+bool IsMethodSupportedForAppCache(const std::string& method) {
+ return (method == "GET") || (method == "HEAD");
+}
+
+bool IsSchemeAndMethodSupportedForAppCache(const net::URLRequest* request) {
+ return request->url().SchemeIsHTTPOrHTTPS() &&
+ IsMethodSupportedForAppCache(request->method());
+}
+
} // namespace
void ServiceWorkerRequestHandler::InitializeHandler(
net::URLRequest* request,
ServiceWorkerContextWrapper* context_wrapper,
+ webkit_blob::BlobStorageContext* blob_storage_context,
int process_id,
int provider_id,
- ResourceType::Type resource_type) {
- if (!ServiceWorkerUtils::IsFeatureEnabled())
+ ResourceType resource_type) {
+ if (!IsSchemeAndMethodSupportedForAppCache(request)) {
return;
+ }
if (!context_wrapper || !context_wrapper->context() ||
provider_id == kInvalidServiceWorkerProviderId) {
ServiceWorkerProviderHost* provider_host =
context_wrapper->context()->GetProviderHost(process_id, provider_id);
- if (!provider_host)
+ if (!provider_host || !provider_host->IsContextAlive())
return;
- if (!provider_host->ShouldHandleRequest(resource_type))
+ scoped_ptr<ServiceWorkerRequestHandler> handler(
+ provider_host->CreateRequestHandler(resource_type,
+ blob_storage_context->AsWeakPtr()));
+ if (!handler)
return;
- scoped_ptr<ServiceWorkerRequestHandler> handler(
- new ServiceWorkerRequestHandler(context_wrapper->context()->AsWeakPtr(),
- provider_host->AsWeakPtr(),
- resource_type));
request->SetUserData(&kUserDataKey, handler.release());
}
request->GetUserData(&kUserDataKey));
}
-scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
+scoped_ptr<net::URLRequestInterceptor>
ServiceWorkerRequestHandler::CreateInterceptor() {
- return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ return scoped_ptr<net::URLRequestInterceptor>(
new ServiceWorkerRequestInterceptor);
}
ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
}
-net::URLRequestJob* ServiceWorkerRequestHandler::MaybeCreateJob(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) {
- if (!context_ || !provider_host_) {
- // We can't do anything other than to fall back to network.
- job_ = NULL;
- return NULL;
- }
-
- // This may get called multiple times for original and redirect requests:
- // A. original request case: job_ is null, no previous location info.
- // B. redirect or restarted request case:
- // a) job_ is non-null if the previous location was forwarded to SW.
- // b) job_ is null if the previous location was fallback.
- // c) job_ is non-null if additional restart was required to fall back.
-
- // We've come here by restart, we already have original request and it
- // tells we should fallback to network. (Case B-c)
- if (job_.get() && job_->ShouldFallbackToNetwork()) {
- job_ = NULL;
- return NULL;
- }
-
- // It's for original request (A) or redirect case (B-a or B-b).
- DCHECK(!job_.get() || job_->ShouldForwardToServiceWorker());
-
- job_ = new ServiceWorkerURLRequestJob(request, network_delegate,
- provider_host_);
- if (ServiceWorkerUtils::IsMainResourceType(resource_type_))
- PrepareForMainResource(request->url());
- else
- PrepareForSubResource();
-
- if (job_->ShouldFallbackToNetwork()) {
- // If we know we can fallback to network at this point (in case
- // the storage lookup returned immediately), just return NULL here to
- // fallback to network.
- job_ = NULL;
- return NULL;
- }
-
- return job_.get();
-}
-
ServiceWorkerRequestHandler::ServiceWorkerRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- ResourceType::Type resource_type)
+ base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
+ ResourceType resource_type)
: context_(context),
provider_host_(provider_host),
- resource_type_(resource_type),
- weak_factory_(this) {
-}
-
-void ServiceWorkerRequestHandler::PrepareForMainResource(const GURL& url) {
- DCHECK(job_.get());
- DCHECK(context_);
- // The corresponding provider_host may already have associate version in
- // redirect case, unassociate it now.
- provider_host_->AssociateVersion(NULL);
- context_->storage()->FindRegistrationForDocument(
- url,
- base::Bind(&self::DidLookupRegistrationForMainResource,
- weak_factory_.GetWeakPtr()));
-}
-
-void ServiceWorkerRequestHandler::DidLookupRegistrationForMainResource(
- ServiceWorkerStatusCode status,
- const scoped_refptr<ServiceWorkerRegistration>& registration) {
- DCHECK(job_.get());
- if (status != SERVICE_WORKER_OK || !registration->active_version()) {
- // No registration, or no active version for the registration is available.
- job_->FallbackToNetwork();
- return;
- }
- DCHECK(registration);
- provider_host_->AssociateVersion(registration->active_version());
- job_->ForwardToServiceWorker();
-}
-
-void ServiceWorkerRequestHandler::PrepareForSubResource() {
- DCHECK(job_.get());
- DCHECK(context_);
- DCHECK(provider_host_->associated_version());
- job_->ForwardToServiceWorker();
+ blob_storage_context_(blob_storage_context),
+ resource_type_(resource_type) {
}
} // namespace content