service_worker_url_request_job_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/basictypes.h" 6#include "base/callback.h" 7#include "base/memory/scoped_ptr.h" 8#include "base/message_loop/message_loop.h" 9#include "base/run_loop.h" 10#include "content/browser/fileapi/chrome_blob_storage_context.h" 11#include "content/browser/fileapi/mock_url_request_delegate.h" 12#include "content/browser/service_worker/embedded_worker_registry.h" 13#include "content/browser/service_worker/embedded_worker_test_helper.h" 14#include "content/browser/service_worker/service_worker_context_core.h" 15#include "content/browser/service_worker/service_worker_provider_host.h" 16#include "content/browser/service_worker/service_worker_registration.h" 17#include "content/browser/service_worker/service_worker_test_utils.h" 18#include "content/browser/service_worker/service_worker_url_request_job.h" 19#include "content/browser/service_worker/service_worker_version.h" 20#include "content/common/service_worker/service_worker_messages.h" 21#include "content/public/browser/blob_handle.h" 22#include "content/public/test/test_browser_context.h" 23#include "content/public/test/test_browser_thread_bundle.h" 24#include "net/base/io_buffer.h" 25#include "net/http/http_request_headers.h" 26#include "net/http/http_response_headers.h" 27#include "net/url_request/url_request.h" 28#include "net/url_request/url_request_context.h" 29#include "net/url_request/url_request_job_factory_impl.h" 30#include "testing/gtest/include/gtest/gtest.h" 31#include "webkit/browser/blob/blob_storage_context.h" 32#include "webkit/browser/blob/blob_url_request_job.h" 33#include "webkit/browser/blob/blob_url_request_job_factory.h" 34#include "webkit/common/blob/blob_data.h" 35 36namespace content { 37 38class ServiceWorkerURLRequestJobTest; 39 40namespace { 41 42const int kProcessID = 1; 43const int kProviderID = 100; 44const char kTestData[] = "Here is sample text for the blob."; 45 46class MockHttpProtocolHandler 47 : public net::URLRequestJobFactory::ProtocolHandler { 48 public: 49 MockHttpProtocolHandler( 50 base::WeakPtr<ServiceWorkerProviderHost> provider_host, 51 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context) 52 : provider_host_(provider_host), 53 blob_storage_context_(blob_storage_context) {} 54 virtual ~MockHttpProtocolHandler() {} 55 56 virtual net::URLRequestJob* MaybeCreateJob( 57 net::URLRequest* request, 58 net::NetworkDelegate* network_delegate) const OVERRIDE { 59 ServiceWorkerURLRequestJob* job = new ServiceWorkerURLRequestJob( 60 request, network_delegate, provider_host_, blob_storage_context_); 61 job->ForwardToServiceWorker(); 62 return job; 63 } 64 65 private: 66 base::WeakPtr<ServiceWorkerProviderHost> provider_host_; 67 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context_; 68}; 69 70// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns 71// the memory. 72webkit_blob::BlobProtocolHandler* CreateMockBlobProtocolHandler( 73 webkit_blob::BlobStorageContext* blob_storage_context) { 74 // The FileSystemContext and MessageLoopProxy are not actually used but a 75 // MessageLoopProxy is needed to avoid a DCHECK in BlobURLRequestJob ctor. 76 return new webkit_blob::BlobProtocolHandler( 77 blob_storage_context, NULL, base::MessageLoopProxy::current().get()); 78} 79 80} // namespace 81 82class ServiceWorkerURLRequestJobTest : public testing::Test { 83 protected: 84 ServiceWorkerURLRequestJobTest() 85 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), 86 blob_data_(new webkit_blob::BlobData("blob-id:myblob")) {} 87 virtual ~ServiceWorkerURLRequestJobTest() {} 88 89 virtual void SetUp() OVERRIDE { 90 browser_context_.reset(new TestBrowserContext); 91 SetUpWithHelper(new EmbeddedWorkerTestHelper(kProcessID)); 92 } 93 94 void SetUpWithHelper(EmbeddedWorkerTestHelper* helper) { 95 helper_.reset(helper); 96 97 registration_ = new ServiceWorkerRegistration( 98 GURL("http://example.com/"), 99 GURL("http://example.com/service_worker.js"), 100 1L, 101 helper_->context()->AsWeakPtr()); 102 version_ = new ServiceWorkerVersion( 103 registration_, 1L, helper_->context()->AsWeakPtr()); 104 105 scoped_ptr<ServiceWorkerProviderHost> provider_host( 106 new ServiceWorkerProviderHost( 107 kProcessID, kProviderID, helper_->context()->AsWeakPtr(), NULL)); 108 provider_host->SetActiveVersion(version_.get()); 109 110 ChromeBlobStorageContext* chrome_blob_storage_context = 111 ChromeBlobStorageContext::GetFor(browser_context_.get()); 112 // Wait for chrome_blob_storage_context to finish initializing. 113 base::RunLoop().RunUntilIdle(); 114 webkit_blob::BlobStorageContext* blob_storage_context = 115 chrome_blob_storage_context->context(); 116 117 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl); 118 url_request_job_factory_->SetProtocolHandler( 119 "http", 120 new MockHttpProtocolHandler(provider_host->AsWeakPtr(), 121 blob_storage_context->AsWeakPtr())); 122 url_request_job_factory_->SetProtocolHandler( 123 "blob", CreateMockBlobProtocolHandler(blob_storage_context)); 124 url_request_context_.set_job_factory(url_request_job_factory_.get()); 125 126 helper_->context()->AddProviderHost(provider_host.Pass()); 127 } 128 129 virtual void TearDown() OVERRIDE { 130 version_ = NULL; 131 registration_ = NULL; 132 helper_.reset(); 133 } 134 135 void TestRequest(int expected_status_code, 136 const std::string& expected_status_text, 137 const std::string& expected_response) { 138 request_ = url_request_context_.CreateRequest( 139 GURL("http://example.com/foo.html"), 140 net::DEFAULT_PRIORITY, 141 &url_request_delegate_, 142 NULL); 143 144 request_->set_method("GET"); 145 request_->Start(); 146 base::RunLoop().RunUntilIdle(); 147 EXPECT_TRUE(request_->status().is_success()); 148 EXPECT_EQ(expected_status_code, 149 request_->response_headers()->response_code()); 150 EXPECT_EQ(expected_status_text, 151 request_->response_headers()->GetStatusText()); 152 EXPECT_EQ(expected_response, url_request_delegate_.response_data()); 153 } 154 155 TestBrowserThreadBundle thread_bundle_; 156 157 scoped_ptr<TestBrowserContext> browser_context_; 158 scoped_ptr<EmbeddedWorkerTestHelper> helper_; 159 scoped_refptr<ServiceWorkerRegistration> registration_; 160 scoped_refptr<ServiceWorkerVersion> version_; 161 162 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_; 163 net::URLRequestContext url_request_context_; 164 MockURLRequestDelegate url_request_delegate_; 165 scoped_ptr<net::URLRequest> request_; 166 167 scoped_refptr<webkit_blob::BlobData> blob_data_; 168 169 private: 170 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest); 171}; 172 173TEST_F(ServiceWorkerURLRequestJobTest, Simple) { 174 version_->SetStatus(ServiceWorkerVersion::ACTIVATED); 175 TestRequest(200, "OK", std::string()); 176} 177 178// Responds to fetch events with a blob. 179class BlobResponder : public EmbeddedWorkerTestHelper { 180 public: 181 BlobResponder(int mock_render_process_id, const std::string& blob_uuid) 182 : EmbeddedWorkerTestHelper(mock_render_process_id), 183 blob_uuid_(blob_uuid) {} 184 virtual ~BlobResponder() {} 185 186 protected: 187 virtual void OnFetchEvent(int embedded_worker_id, 188 int request_id, 189 const ServiceWorkerFetchRequest& request) OVERRIDE { 190 SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished( 191 embedded_worker_id, 192 request_id, 193 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, 194 ServiceWorkerResponse(GURL(""), 195 200, 196 "OK", 197 std::map<std::string, std::string>(), 198 blob_uuid_))); 199 } 200 201 std::string blob_uuid_; 202 203 private: 204 DISALLOW_COPY_AND_ASSIGN(BlobResponder); 205}; 206 207TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) { 208 ChromeBlobStorageContext* blob_storage_context = 209 ChromeBlobStorageContext::GetFor(browser_context_.get()); 210 std::string expected_response; 211 for (int i = 0; i < 1024; ++i) { 212 blob_data_->AppendData(kTestData); 213 expected_response += kTestData; 214 } 215 scoped_ptr<webkit_blob::BlobDataHandle> blob_handle = 216 blob_storage_context->context()->AddFinishedBlob(blob_data_); 217 SetUpWithHelper(new BlobResponder(kProcessID, blob_handle->uuid())); 218 219 version_->SetStatus(ServiceWorkerVersion::ACTIVATED); 220 TestRequest(200, "OK", expected_response); 221} 222 223TEST_F(ServiceWorkerURLRequestJobTest, NonExistentBlobUUIDResponse) { 224 SetUpWithHelper(new BlobResponder(kProcessID, "blob-id:nothing-is-here")); 225 version_->SetStatus(ServiceWorkerVersion::ACTIVATED); 226 TestRequest(500, "Service Worker Response Error", std::string()); 227} 228 229// TODO(kinuko): Add more tests with different response data and also for 230// FallbackToNetwork case. 231 232} // namespace content 233