1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// Copyright 2014 The Chromium Authors. All rights reserved. 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// Use of this source code is governed by a BSD-style license that can be 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// found in the LICENSE file. 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "base/bind.h" 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "base/callback.h" 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "base/command_line.h" 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "base/run_loop.h" 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "base/strings/utf_string_conversions.h" 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/fileapi/chrome_blob_storage_context.h" 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "content/browser/service_worker/embedded_worker_instance.h" 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/embedded_worker_registry.h" 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/service_worker_context_core.h" 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/service_worker_context_observer.h" 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "content/browser/service_worker/service_worker_context_wrapper.h" 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/service_worker_registration.h" 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/service_worker_test_utils.h" 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/browser/service_worker/service_worker_version.h" 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/common/service_worker/service_worker_messages.h" 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/common/service_worker/service_worker_status_code.h" 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/common/service_worker/service_worker_types.h" 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/browser/browser_context.h" 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/browser/browser_thread.h" 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/browser/render_process_host.h" 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/browser/storage_partition.h" 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/browser/web_contents.h" 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/common/content_switches.h" 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/test/browser_test_utils.h" 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/test/content_browser_test.h" 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/public/test/content_browser_test_utils.h" 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "content/shell/browser/shell.h" 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "net/test/embedded_test_server/embedded_test_server.h" 33e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "net/test/embedded_test_server/http_request.h" 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "net/test/embedded_test_server/http_response.h" 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "net/url_request/url_request_filter.h" 36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "net/url_request/url_request_interceptor.h" 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "net/url_request/url_request_test_job.h" 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "storage/browser/blob/blob_data_handle.h" 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "storage/browser/blob/blob_storage_context.h" 403c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#include "storage/common/blob/blob_data.h" 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnamespace content { 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnamespace { 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstruct FetchResult { 47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerStatusCode status; 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerFetchEventResult result; 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerResponse response; 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org scoped_ptr<storage::BlobDataHandle> blob_data_handle; 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid RunAndQuit(const base::Closure& closure, 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::Closure& quit, 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::MessageLoopProxy* original_message_loop) { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org closure.Run(); 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org original_message_loop->PostTask(FROM_HERE, quit); 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 593c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid RunOnIOThread(const base::Closure& closure) { 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::RunLoop run_loop; 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask( 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::IO, FROM_HERE, 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(&RunAndQuit, closure, run_loop.QuitClosure(), 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::MessageLoopProxy::current())); 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org run_loop.Run(); 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid RunOnIOThread( 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::Callback<void(const base::Closure& continuation)>& closure) { 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::RunLoop run_loop; 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Closure quit_on_original_thread = 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask), 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::MessageLoopProxy::current().get(), 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org FROM_HERE, 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org run_loop.QuitClosure()); 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::IO, 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org FROM_HERE, 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(closure, quit_on_original_thread)); 80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org run_loop.Run(); 81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid ReceivePrepareResult(bool* is_prepared) { 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *is_prepared = true; 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgbase::Closure CreatePrepareReceiver(bool* is_prepared) { 88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return base::Bind(&ReceivePrepareResult, is_prepared); 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// Contrary to the style guide, the output parameter of this function comes 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// before input parameters so Bind can be used on it to create a FetchCallback 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// to pass to DispatchFetchEvent. 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid ReceiveFetchResult(BrowserThread::ID run_quit_thread, 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::Closure& quit, 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ChromeBlobStorageContext* blob_context, 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org FetchResult* out_result, 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerStatusCode actual_status, 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerFetchEventResult actual_result, 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const ServiceWorkerResponse& actual_response) { 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org out_result->status = actual_status; 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org out_result->result = actual_result; 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org out_result->response = actual_response; 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!actual_response.blob_uuid.empty()) { 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org out_result->blob_data_handle = 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org blob_context->context()->GetBlobDataFromUUID( 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org actual_response.blob_uuid); 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!quit.is_null()) 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit); 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgServiceWorkerVersion::FetchCallback CreateResponseReceiver( 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::ID run_quit_thread, 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::Closure& quit, 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ChromeBlobStorageContext* blob_context, 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org FetchResult* result) { 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return base::Bind(&ReceiveFetchResult, run_quit_thread, quit, 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org make_scoped_refptr<ChromeBlobStorageContext>(blob_context), 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org result); 121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid ReadResponseBody(std::string* body, 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org storage::BlobDataHandle* blob_data_handle) { 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(blob_data_handle); 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_EQ(1U, blob_data_handle->data()->items().size()); 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *body = std::string(blob_data_handle->data()->items()[0].bytes(), 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org blob_data_handle->data()->items()[0].length()); 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid ExpectResultAndRun(bool expected, 132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::Closure& continuation, 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org bool actual) { 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(expected, actual); 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org continuation.Run(); 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgclass WorkerActivatedObserver 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org : public ServiceWorkerContextObserver, 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public base::RefCountedThreadSafe<WorkerActivatedObserver> { 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public: 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org explicit WorkerActivatedObserver(ServiceWorkerContextWrapper* context) 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org : context_(context) {} 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void Init() { 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RunOnIOThread(base::Bind(&WorkerActivatedObserver::InitOnIOThread, this)); 146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // ServiceWorkerContextObserver overrides. 1483c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com virtual void OnVersionStateChanged(int64 version_id) OVERRIDE { 1493c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com DCHECK_CURRENTLY_ON(BrowserThread::IO); 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const ServiceWorkerVersion* version = 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org context_->context()->GetLiveVersion(version_id); 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (version->status() == ServiceWorkerVersion::ACTIVATED) { 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org context_->RemoveObserver(this); 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::UI, 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org FROM_HERE, 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(&WorkerActivatedObserver::Quit, this)); 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void Wait() { run_loop_.Run(); } 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 161e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org private: 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org friend class base::RefCountedThreadSafe<WorkerActivatedObserver>; 163e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org virtual ~WorkerActivatedObserver() {} 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void InitOnIOThread() { context_->AddObserver(this); } 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void Quit() { run_loop_.Quit(); } 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::RunLoop run_loop_; 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerContextWrapper* context_; 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver); 170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgscoped_ptr<net::test_server::HttpResponse> VerifyServiceWorkerHeaderInRequest( 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const net::test_server::HttpRequest& request) { 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(request.relative_url, "/service_worker/generated_sw.js"); 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org std::map<std::string, std::string>::const_iterator it = 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org request.headers.find("Service-Worker"); 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_TRUE(it != request.headers.end()); 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ("script", it->second); 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org scoped_ptr<net::test_server::BasicHttpResponse> http_response( 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org new net::test_server::BasicHttpResponse()); 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org http_response->set_content_type("text/javascript"); 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return http_response.PassAs<net::test_server::HttpResponse>(); 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// The ImportsBustMemcache test requires that the imported script 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// would naturally be cached in blink's memcache, but the embedded 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// test server doesn't produce headers that allow the blink's memcache 189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// to do that. This interceptor injects headers that give the import 190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org// an experiration far in the future. 191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgclass LongLivedResourceInterceptor : public net::URLRequestInterceptor { 192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public: 193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LongLivedResourceInterceptor(const std::string& body) 194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org : body_(body) {} 195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual ~LongLivedResourceInterceptor() {} 196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // net::URLRequestInterceptor implementation 198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual net::URLRequestJob* MaybeInterceptRequest( 199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org net::URLRequest* request, 200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org net::NetworkDelegate* network_delegate) const OVERRIDE { 201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const char kHeaders[] = 202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "HTTP/1.1 200 OK\0" 203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "Content-Type: text/javascript\0" 204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0" 2056b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org "\0"; 206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org std::string headers(kHeaders, arraysize(kHeaders)); 207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return new net::URLRequestTestJob( 208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org request, network_delegate, headers, body_, true); 209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org private: 212885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org std::string body_; 213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor); 214885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 215885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 216885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid CreateLongLivedResourceInterceptors( 217885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL& worker_url, const GURL& import_url) { 218885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 219885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org scoped_ptr<net::URLRequestInterceptor> interceptor; 220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org interceptor.reset(new LongLivedResourceInterceptor( 222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "importScripts('long_lived_import.js');")); 223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org net::URLRequestFilter::GetInstance()->AddUrlInterceptor( 224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_url, interceptor.Pass()); 225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org interceptor.reset(new LongLivedResourceInterceptor( 227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "// the imported script does nothing")); 228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org net::URLRequestFilter::GetInstance()->AddUrlInterceptor( 229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org import_url, interceptor.Pass()); 230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid CountScriptResources( 233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerContextWrapper* wrapper, 234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL& scope, 235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int* num_resources) { 236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *num_resources = -1; 237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org std::vector<ServiceWorkerRegistrationInfo> infos = 239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper->context()->GetAllLiveRegistrationInfo(); 240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (infos.empty()) 241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return; 242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int version_id; 244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org size_t index = infos.size() - 1; 245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!infos[index].installing_version.is_null) 246885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org version_id = infos[index].installing_version.version_id; 247885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (!infos[index].waiting_version.is_null) 248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org version_id = infos[1].waiting_version.version_id; 249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (!infos[index].active_version.is_null) 250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org version_id = infos[index].active_version.version_id; 251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return; 253885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 254885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerVersion* version = 255885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper->context()->GetLiveVersion(version_id); 256885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *num_resources = static_cast<int>(version->script_cache_map()->size()); 257885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 258885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 259885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} // namespace 260885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 261885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgclass ServiceWorkerBrowserTest : public ContentBrowserTest { 262885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org protected: 263885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org typedef ServiceWorkerBrowserTest self; 264e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 265885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE { 266885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org command_line->AppendSwitch( 267885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org switches::kEnableExperimentalWebPlatformFeatures); 268885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 269885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 270885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void SetUpOnMainThread() OVERRIDE { 271885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 272885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org StoragePartition* partition = BrowserContext::GetDefaultStoragePartition( 273885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org shell()->web_contents()->GetBrowserContext()); 274885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper_ = static_cast<ServiceWorkerContextWrapper*>( 275885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org partition->GetServiceWorkerContext()); 276885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 277885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // Navigate to the page to set up a renderer page (where we can embed 278885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // a worker). 279885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NavigateToURLBlockUntilNavigationsComplete( 280885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org shell(), 281885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org embedded_test_server()->GetURL("/service_worker/empty.html"), 1); 282885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 283885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RunOnIOThread(base::Bind(&self::SetUpOnIOThread, this)); 284885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 2853c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 286885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void TearDownOnMainThread() OVERRIDE { 287885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RunOnIOThread(base::Bind(&self::TearDownOnIOThread, this)); 288885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper_ = NULL; 289885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 290885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 291885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void SetUpOnIOThread() {} 292885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void TearDownOnIOThread() {} 293885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 294885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); } 295885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerContext* public_context() { return wrapper(); } 296885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 297885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void AssociateRendererProcessToPattern(const GURL& pattern) { 298885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper_->process_manager()->AddProcessReferenceToPattern( 299885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pattern, shell()->web_contents()->GetRenderProcessHost()->GetID()); 300885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 301885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 302885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org private: 303885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org scoped_refptr<ServiceWorkerContextWrapper> wrapper_; 304885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 305885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 306885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgclass EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest, 307885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public EmbeddedWorkerInstance::Listener { 308885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public: 309885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org typedef EmbeddedWorkerBrowserTest self; 310885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 311885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EmbeddedWorkerBrowserTest() 312885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org : last_worker_status_(EmbeddedWorkerInstance::STOPPED), 313885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pause_mode_(DONT_PAUSE) {} 314885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual ~EmbeddedWorkerBrowserTest() {} 315885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 316885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void TearDownOnIOThread() OVERRIDE { 317885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (worker_) { 318885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_->RemoveListener(this); 319885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_.reset(); 320885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 321885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 322885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 323885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void StartOnIOThread() { 324885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 325885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_ = wrapper()->context()->embedded_worker_registry()->CreateWorker(); 326885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status()); 327885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_->AddListener(this); 328885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 329885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 330885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const int64 service_worker_version_id = 33L; 331885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL pattern = embedded_test_server()->GetURL("/"); 332885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL script_url = embedded_test_server()->GetURL( 333885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org "/service_worker/worker.js"); 334885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org AssociateRendererProcessToPattern(pattern); 335885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID(); 336885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wrapper()->process_manager()->AddProcessReferenceToPattern( 337885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pattern, process_id); 338885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_->Start( 339885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org service_worker_version_id, 340885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pattern, 341885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org script_url, 342885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pause_mode_ != DONT_PAUSE, 343885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2, this)); 344885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 345885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void StartOnIOThread2(ServiceWorkerStatusCode status) { 346885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org last_worker_status_ = worker_->status(); 347885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(SERVICE_WORKER_OK, status); 348885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(EmbeddedWorkerInstance::STARTING, last_worker_status_); 349885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 350885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (status != SERVICE_WORKER_OK && !done_closure_.is_null()) 351885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org done_closure_.Run(); 352885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 353885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 354885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void StopOnIOThread() { 355885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 356885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker_->status()); 357885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 358885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerStatusCode status = worker_->Stop(); 359885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 360885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org last_worker_status_ = worker_->status(); 361885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(SERVICE_WORKER_OK, status); 362885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, last_worker_status_); 363885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 364885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (status != SERVICE_WORKER_OK && !done_closure_.is_null()) 365885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org done_closure_.Run(); 366885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 367885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 368885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org protected: 369885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // EmbeddedWorkerInstance::Observer overrides: 370885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void OnStarted() OVERRIDE { 371885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(worker_ != NULL); 372885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_FALSE(done_closure_.is_null()); 373885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org last_worker_status_ = worker_->status(); 374885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_); 375885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 376885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void OnStopped() OVERRIDE { 377885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(worker_ != NULL); 378885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_FALSE(done_closure_.is_null()); 379885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org last_worker_status_ = worker_->status(); 380885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_); 381885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 382885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void OnPausedAfterDownload() OVERRIDE { 383885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (pause_mode_ == PAUSE_THEN_RESUME) 384885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_->ResumeAfterDownload(); 385885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (pause_mode_ == PAUSE_THEN_STOP) 386885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_->Stop(); 387885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 388885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_TRUE(false); 389885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 390885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void OnReportException(const base::string16& error_message, 391885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int line_number, 392885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int column_number, 393885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL& source_url) OVERRIDE {} 394885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void OnReportConsoleMessage(int source_identifier, 395885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int message_level, 396885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const base::string16& message, 397885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int line_number, 398885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const GURL& source_url) OVERRIDE {} 399885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 400885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return false; 401885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 402885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 403885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org scoped_ptr<EmbeddedWorkerInstance> worker_; 404885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EmbeddedWorkerInstance::Status last_worker_status_; 405885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 406885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org enum { 407885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org DONT_PAUSE, 408885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PAUSE_THEN_RESUME, 409885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PAUSE_THEN_STOP, 410885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } pause_mode_; 411885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 412885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // Called by EmbeddedWorkerInstance::Observer overrides so that 413885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // test code can wait for the worker status notifications. 414885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Closure done_closure_; 415885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 416885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 417885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgclass ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest { 418885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org public: 419885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org typedef ServiceWorkerVersionBrowserTest self; 420885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 421885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual ~ServiceWorkerVersionBrowserTest() {} 422885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 423885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org virtual void TearDownOnIOThread() OVERRIDE { 424885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org registration_ = NULL; 425885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org version_ = NULL; 426885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 427885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 428885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void InstallTestHelper(const std::string& worker_url, 429885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerStatusCode expected_status) { 430885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this, 431885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org worker_url)); 432885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 433885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // Dispatch install on a worker. 434885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 435885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::RunLoop install_run_loop; 436885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 437885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::Bind(&self::InstallOnIOThread, this, 438885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org install_run_loop.QuitClosure(), 439885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org &status)); 440885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org install_run_loop.Run(); 441885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ASSERT_EQ(expected_status, status); 442885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 443885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org // Stop the worker. 444e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org status = SERVICE_WORKER_ERROR_FAILED; 445885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org base::RunLoop stop_run_loop; 446 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 447 base::Bind(&self::StopOnIOThread, this, 448 stop_run_loop.QuitClosure(), 449 &status)); 450 stop_run_loop.Run(); 451 ASSERT_EQ(SERVICE_WORKER_OK, status); 452 } 453 454 void ActivateTestHelper( 455 const std::string& worker_url, 456 ServiceWorkerStatusCode expected_status) { 457 RunOnIOThread( 458 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url)); 459 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 460 base::RunLoop run_loop; 461 BrowserThread::PostTask( 462 BrowserThread::IO, 463 FROM_HERE, 464 base::Bind( 465 &self::ActivateOnIOThread, this, run_loop.QuitClosure(), &status)); 466 run_loop.Run(); 467 ASSERT_EQ(expected_status, status); 468 } 469 470 void FetchOnRegisteredWorker( 471 ServiceWorkerFetchEventResult* result, 472 ServiceWorkerResponse* response, 473 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) { 474 blob_context_ = ChromeBlobStorageContext::GetFor( 475 shell()->web_contents()->GetBrowserContext()); 476 bool prepare_result = false; 477 FetchResult fetch_result; 478 fetch_result.status = SERVICE_WORKER_ERROR_FAILED; 479 base::RunLoop fetch_run_loop; 480 BrowserThread::PostTask(BrowserThread::IO, 481 FROM_HERE, 482 base::Bind(&self::FetchOnIOThread, 483 this, 484 fetch_run_loop.QuitClosure(), 485 &prepare_result, 486 &fetch_result)); 487 fetch_run_loop.Run(); 488 ASSERT_TRUE(prepare_result); 489 *result = fetch_result.result; 490 *response = fetch_result.response; 491 *blob_data_handle = fetch_result.blob_data_handle.Pass(); 492 ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status); 493 } 494 495 void FetchTestHelper(const std::string& worker_url, 496 ServiceWorkerFetchEventResult* result, 497 ServiceWorkerResponse* response, 498 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) { 499 RunOnIOThread( 500 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url)); 501 FetchOnRegisteredWorker(result, response, blob_data_handle); 502 } 503 504 void SetUpRegistrationOnIOThread(const std::string& worker_url) { 505 const GURL pattern = embedded_test_server()->GetURL("/"); 506 registration_ = new ServiceWorkerRegistration( 507 pattern, 508 wrapper()->context()->storage()->NewRegistrationId(), 509 wrapper()->context()->AsWeakPtr()); 510 version_ = new ServiceWorkerVersion( 511 registration_.get(), 512 embedded_test_server()->GetURL(worker_url), 513 wrapper()->context()->storage()->NewVersionId(), 514 wrapper()->context()->AsWeakPtr()); 515 AssociateRendererProcessToPattern(pattern); 516 } 517 518 void StartOnIOThread(const base::Closure& done, 519 ServiceWorkerStatusCode* result) { 520 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 521 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result)); 522 } 523 524 void InstallOnIOThread(const base::Closure& done, 525 ServiceWorkerStatusCode* result) { 526 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 527 version_->SetStatus(ServiceWorkerVersion::INSTALLING); 528 version_->DispatchInstallEvent( 529 -1, CreateReceiver(BrowserThread::UI, done, result)); 530 } 531 532 void ActivateOnIOThread(const base::Closure& done, 533 ServiceWorkerStatusCode* result) { 534 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 535 version_->SetStatus(ServiceWorkerVersion::ACTIVATING); 536 version_->DispatchActivateEvent( 537 CreateReceiver(BrowserThread::UI, done, result)); 538 } 539 540 void FetchOnIOThread(const base::Closure& done, 541 bool* prepare_result, 542 FetchResult* result) { 543 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 544 ServiceWorkerFetchRequest request( 545 embedded_test_server()->GetURL("/service_worker/empty.html"), 546 "GET", 547 ServiceWorkerHeaderMap(), 548 GURL(""), 549 false); 550 version_->SetStatus(ServiceWorkerVersion::ACTIVATED); 551 version_->DispatchFetchEvent( 552 request, 553 CreatePrepareReceiver(prepare_result), 554 CreateResponseReceiver( 555 BrowserThread::UI, done, blob_context_.get(), result)); 556 } 557 558 void StopOnIOThread(const base::Closure& done, 559 ServiceWorkerStatusCode* result) { 560 ASSERT_TRUE(version_.get()); 561 version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result)); 562 } 563 564 void SyncEventOnIOThread(const base::Closure& done, 565 ServiceWorkerStatusCode* result) { 566 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 567 version_->SetStatus(ServiceWorkerVersion::ACTIVATED); 568 version_->DispatchSyncEvent( 569 CreateReceiver(BrowserThread::UI, done, result)); 570 } 571 572 protected: 573 scoped_refptr<ServiceWorkerRegistration> registration_; 574 scoped_refptr<ServiceWorkerVersion> version_; 575 scoped_refptr<ChromeBlobStorageContext> blob_context_; 576}; 577 578IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) { 579 // Start a worker and wait until OnStarted() is called. 580 base::RunLoop start_run_loop; 581 done_closure_ = start_run_loop.QuitClosure(); 582 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 583 base::Bind(&self::StartOnIOThread, this)); 584 start_run_loop.Run(); 585 586 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_); 587 588 // Stop a worker and wait until OnStopped() is called. 589 base::RunLoop stop_run_loop; 590 done_closure_ = stop_run_loop.QuitClosure(); 591 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 592 base::Bind(&self::StopOnIOThread, this)); 593 stop_run_loop.Run(); 594 595 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_); 596} 597 598IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartPaused_ThenResume) { 599 pause_mode_ = PAUSE_THEN_RESUME; 600 base::RunLoop start_run_loop; 601 done_closure_ = start_run_loop.QuitClosure(); 602 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 603 base::Bind(&self::StartOnIOThread, this)); 604 start_run_loop.Run(); 605 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_); 606} 607 608IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, 609 StartPaused_ThenStop) { 610 pause_mode_ = PAUSE_THEN_STOP; 611 base::RunLoop start_run_loop; 612 done_closure_ = start_run_loop.QuitClosure(); 613 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 614 base::Bind(&self::StartOnIOThread, this)); 615 start_run_loop.Run(); 616 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_); 617} 618 619IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) { 620 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this, 621 "/service_worker/worker.js")); 622 623 // Start a worker. 624 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 625 base::RunLoop start_run_loop; 626 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 627 base::Bind(&self::StartOnIOThread, this, 628 start_run_loop.QuitClosure(), 629 &status)); 630 start_run_loop.Run(); 631 ASSERT_EQ(SERVICE_WORKER_OK, status); 632 633 // Stop the worker. 634 status = SERVICE_WORKER_ERROR_FAILED; 635 base::RunLoop stop_run_loop; 636 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 637 base::Bind(&self::StopOnIOThread, this, 638 stop_run_loop.QuitClosure(), 639 &status)); 640 stop_run_loop.Run(); 641 ASSERT_EQ(SERVICE_WORKER_OK, status); 642} 643 644IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) { 645 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this, 646 "/service_worker/nonexistent.js")); 647 648 // Start a worker for nonexistent URL. 649 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 650 base::RunLoop start_run_loop; 651 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 652 base::Bind(&self::StartOnIOThread, this, 653 start_run_loop.QuitClosure(), 654 &status)); 655 start_run_loop.Run(); 656 ASSERT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status); 657} 658 659IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) { 660 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK); 661} 662 663IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 664 InstallWithWaitUntil_Fulfilled) { 665 InstallTestHelper("/service_worker/worker_install_fulfilled.js", 666 SERVICE_WORKER_OK); 667} 668 669// Check that ServiceWorker script requests set a "Service-Worker: script" 670// header. 671IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 672 ServiceWorkerScriptHeader) { 673 embedded_test_server()->RegisterRequestHandler( 674 base::Bind(&VerifyServiceWorkerHeaderInRequest)); 675 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK); 676} 677 678IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 679 Activate_NoEventListener) { 680 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK); 681 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status()); 682} 683 684IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) { 685 ActivateTestHelper("/service_worker/worker_activate_rejected.js", 686 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED); 687} 688 689IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 690 InstallWithWaitUntil_Rejected) { 691 InstallTestHelper("/service_worker/worker_install_rejected.js", 692 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED); 693} 694 695IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) { 696 ServiceWorkerFetchEventResult result; 697 ServiceWorkerResponse response; 698 scoped_ptr<storage::BlobDataHandle> blob_data_handle; 699 FetchTestHelper("/service_worker/fetch_event.js", 700 &result, &response, &blob_data_handle); 701 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result); 702 EXPECT_EQ(301, response.status_code); 703 EXPECT_EQ("Moved Permanently", response.status_text); 704 ServiceWorkerHeaderMap expected_headers; 705 expected_headers["content-language"] = "fi"; 706 expected_headers["content-type"] = "text/html; charset=UTF-8"; 707 EXPECT_EQ(expected_headers, response.headers); 708 709 std::string body; 710 RunOnIOThread( 711 base::Bind(&ReadResponseBody, 712 &body, base::Owned(blob_data_handle.release()))); 713 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body); 714} 715 716IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 717 SyncAbortedWithoutFlag) { 718 RunOnIOThread(base::Bind( 719 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js")); 720 721 // Run the sync event. 722 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 723 base::RunLoop sync_run_loop; 724 BrowserThread::PostTask(BrowserThread::IO, 725 FROM_HERE, 726 base::Bind(&self::SyncEventOnIOThread, 727 this, 728 sync_run_loop.QuitClosure(), 729 &status)); 730 sync_run_loop.Run(); 731 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT, status); 732} 733 734IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) { 735 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 736 command_line->AppendSwitch(switches::kEnableServiceWorkerSync); 737 738 RunOnIOThread(base::Bind( 739 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js")); 740 ServiceWorkerFetchEventResult result; 741 ServiceWorkerResponse response; 742 scoped_ptr<storage::BlobDataHandle> blob_data_handle; 743 // Should 404 before sync event. 744 FetchOnRegisteredWorker(&result, &response, &blob_data_handle); 745 EXPECT_EQ(404, response.status_code); 746 747 // Run the sync event. 748 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 749 base::RunLoop sync_run_loop; 750 BrowserThread::PostTask(BrowserThread::IO, 751 FROM_HERE, 752 base::Bind(&self::SyncEventOnIOThread, 753 this, 754 sync_run_loop.QuitClosure(), 755 &status)); 756 sync_run_loop.Run(); 757 ASSERT_EQ(SERVICE_WORKER_OK, status); 758 759 // Should 200 after sync event. 760 FetchOnRegisteredWorker(&result, &response, &blob_data_handle); 761 EXPECT_EQ(200, response.status_code); 762} 763 764// ServiceWorkerBrowserTest.Reload is flaky on Android crbug.com/393486 765#if defined(OS_ANDROID) 766#define MAYBE_Reload DISABLED_Reload 767#else 768#define MAYBE_Reload Reload 769#endif 770IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, MAYBE_Reload) { 771 const std::string kPageUrl = "/service_worker/reload.html"; 772 const std::string kWorkerUrl = "/service_worker/fetch_event_reload.js"; 773 { 774 scoped_refptr<WorkerActivatedObserver> observer = 775 new WorkerActivatedObserver(wrapper()); 776 observer->Init(); 777 public_context()->RegisterServiceWorker( 778 embedded_test_server()->GetURL(kPageUrl), 779 embedded_test_server()->GetURL(kWorkerUrl), 780 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing))); 781 observer->Wait(); 782 } 783 { 784 const base::string16 title = base::ASCIIToUTF16("reload=false"); 785 TitleWatcher title_watcher(shell()->web_contents(), title); 786 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl)); 787 EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); 788 } 789 { 790 const base::string16 title = base::ASCIIToUTF16("reload=true"); 791 TitleWatcher title_watcher(shell()->web_contents(), title); 792 ReloadBlockUntilNavigationsComplete(shell(), 1); 793 EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); 794 } 795 shell()->Close(); 796 { 797 base::RunLoop run_loop; 798 public_context()->UnregisterServiceWorker( 799 embedded_test_server()->GetURL(kPageUrl), 800 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure())); 801 run_loop.Run(); 802 } 803} 804 805IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) { 806 const std::string kScopeUrl = "/service_worker/imports_bust_memcache_scope/"; 807 const std::string kPageUrl = "/service_worker/imports_bust_memcache.html"; 808 const std::string kScriptUrl = "/service_worker/worker_with_one_import.js"; 809 const std::string kImportUrl = "/service_worker/long_lived_import.js"; 810 const base::string16 kOKTitle(base::ASCIIToUTF16("OK")); 811 const base::string16 kFailTitle(base::ASCIIToUTF16("FAIL")); 812 813 RunOnIOThread( 814 base::Bind(&CreateLongLivedResourceInterceptors, 815 embedded_test_server()->GetURL(kScriptUrl), 816 embedded_test_server()->GetURL(kImportUrl))); 817 818 TitleWatcher title_watcher(shell()->web_contents(), kOKTitle); 819 title_watcher.AlsoWaitForTitle(kFailTitle); 820 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl)); 821 base::string16 title = title_watcher.WaitAndGetTitle(); 822 EXPECT_EQ(kOKTitle, title); 823 824 // Verify the number of resources in the implicit script cache is correct. 825 const int kExpectedNumResources = 2; 826 int num_resources = 0; 827 RunOnIOThread( 828 base::Bind(&CountScriptResources, 829 base::Unretained(wrapper()), 830 embedded_test_server()->GetURL(kScopeUrl), 831 &num_resources)); 832 EXPECT_EQ(kExpectedNumResources, num_resources); 833} 834 835class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest { 836 public: 837 typedef ServiceWorkerBlackBoxBrowserTest self; 838 839 void FindRegistrationOnIO(const GURL& document_url, 840 ServiceWorkerStatusCode* status, 841 const base::Closure& continuation) { 842 wrapper()->context()->storage()->FindRegistrationForDocument( 843 document_url, 844 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2, 845 this, 846 status, 847 continuation)); 848 } 849 850 void FindRegistrationOnIO2( 851 ServiceWorkerStatusCode* out_status, 852 const base::Closure& continuation, 853 ServiceWorkerStatusCode status, 854 const scoped_refptr<ServiceWorkerRegistration>& registration) { 855 *out_status = status; 856 if (!registration.get()) 857 EXPECT_NE(SERVICE_WORKER_OK, status); 858 continuation.Run(); 859 } 860}; 861 862static int CountRenderProcessHosts() { 863 int result = 0; 864 for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator()); 865 !iter.IsAtEnd(); 866 iter.Advance()) { 867 result++; 868 } 869 return result; 870} 871 872// Crashes on Android and flakes on CrOS: http://crbug.com/387045 873#if defined(OS_ANDROID) || defined(OS_CHROMEOS) 874#define MAYBE_Registration DISABLED_Registration 875#else 876#define MAYBE_Registration Registration 877#endif 878IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) { 879 // Close the only window to be sure we're not re-using its RenderProcessHost. 880 shell()->Close(); 881 EXPECT_EQ(0, CountRenderProcessHosts()); 882 883 const std::string kWorkerUrl = "/service_worker/fetch_event.js"; 884 885 // Unregistering nothing should return false. 886 { 887 base::RunLoop run_loop; 888 public_context()->UnregisterServiceWorker( 889 embedded_test_server()->GetURL("/"), 890 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure())); 891 run_loop.Run(); 892 } 893 894 // If we use a worker URL that doesn't exist, registration fails. 895 { 896 base::RunLoop run_loop; 897 public_context()->RegisterServiceWorker( 898 embedded_test_server()->GetURL("/"), 899 embedded_test_server()->GetURL("/does/not/exist"), 900 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure())); 901 run_loop.Run(); 902 } 903 EXPECT_EQ(0, CountRenderProcessHosts()); 904 905 // Register returns when the promise would be resolved. 906 { 907 base::RunLoop run_loop; 908 public_context()->RegisterServiceWorker( 909 embedded_test_server()->GetURL("/"), 910 embedded_test_server()->GetURL(kWorkerUrl), 911 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure())); 912 run_loop.Run(); 913 } 914 EXPECT_EQ(1, CountRenderProcessHosts()); 915 916 // Registering again should succeed, although the algo still 917 // might not be complete. 918 { 919 base::RunLoop run_loop; 920 public_context()->RegisterServiceWorker( 921 embedded_test_server()->GetURL("/"), 922 embedded_test_server()->GetURL(kWorkerUrl), 923 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure())); 924 run_loop.Run(); 925 } 926 927 // The registration algo might not be far enough along to have 928 // stored the registration data, so it may not be findable 929 // at this point. 930 931 // Unregistering something should return true. 932 { 933 base::RunLoop run_loop; 934 public_context()->UnregisterServiceWorker( 935 embedded_test_server()->GetURL("/"), 936 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure())); 937 run_loop.Run(); 938 } 939 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the " 940 "workers eagerly, so their RPHs " 941 "can still be running."; 942 943 // Should not be able to find it. 944 { 945 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 946 RunOnIOThread( 947 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO, 948 this, 949 embedded_test_server()->GetURL("/service_worker/empty.html"), 950 &status)); 951 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status); 952 } 953} 954 955} // namespace content 956