1 // Copyright 2013 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 "content/browser/service_worker/service_worker_context_wrapper.h" 6 7 #include "base/files/file_path.h" 8 #include "base/threading/sequenced_worker_pool.h" 9 #include "content/browser/service_worker/service_worker_context_core.h" 10 #include "content/browser/service_worker/service_worker_context_observer.h" 11 #include "content/browser/service_worker/service_worker_process_manager.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "webkit/browser/quota/quota_manager_proxy.h" 14 15 namespace content { 16 17 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper( 18 BrowserContext* browser_context) 19 : observer_list_( 20 new ObserverListThreadSafe<ServiceWorkerContextObserver>()), 21 process_manager_(new ServiceWorkerProcessManager(browser_context)) { 22 } 23 24 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() { 25 } 26 27 void ServiceWorkerContextWrapper::Init( 28 const base::FilePath& user_data_directory, 29 quota::QuotaManagerProxy* quota_manager_proxy) { 30 scoped_refptr<base::SequencedTaskRunner> database_task_runner = 31 BrowserThread::GetBlockingPool()-> 32 GetSequencedTaskRunnerWithShutdownBehavior( 33 BrowserThread::GetBlockingPool()->GetSequenceToken(), 34 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 35 scoped_refptr<base::MessageLoopProxy> disk_cache_thread = 36 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE); 37 InitInternal(user_data_directory, database_task_runner, 38 disk_cache_thread, quota_manager_proxy); 39 } 40 41 void ServiceWorkerContextWrapper::Shutdown() { 42 DCHECK_CURRENTLY_ON(BrowserThread::UI); 43 process_manager_->Shutdown(); 44 BrowserThread::PostTask( 45 BrowserThread::IO, 46 FROM_HERE, 47 base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this)); 48 } 49 50 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() { 51 DCHECK_CURRENTLY_ON(BrowserThread::IO); 52 return context_core_.get(); 53 } 54 55 static void FinishRegistrationOnIO( 56 const ServiceWorkerContext::ResultCallback& continuation, 57 ServiceWorkerStatusCode status, 58 int64 registration_id, 59 int64 version_id) { 60 DCHECK_CURRENTLY_ON(BrowserThread::IO); 61 BrowserThread::PostTask( 62 BrowserThread::UI, 63 FROM_HERE, 64 base::Bind(continuation, status == SERVICE_WORKER_OK)); 65 } 66 67 void ServiceWorkerContextWrapper::RegisterServiceWorker( 68 const GURL& pattern, 69 const GURL& script_url, 70 const ResultCallback& continuation) { 71 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 72 BrowserThread::PostTask( 73 BrowserThread::IO, 74 FROM_HERE, 75 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker, 76 this, 77 pattern, 78 script_url, 79 continuation)); 80 return; 81 } 82 83 context()->RegisterServiceWorker( 84 pattern, 85 script_url, 86 -1, 87 NULL /* provider_host */, 88 base::Bind(&FinishRegistrationOnIO, continuation)); 89 } 90 91 static void FinishUnregistrationOnIO( 92 const ServiceWorkerContext::ResultCallback& continuation, 93 ServiceWorkerStatusCode status) { 94 DCHECK_CURRENTLY_ON(BrowserThread::IO); 95 BrowserThread::PostTask( 96 BrowserThread::UI, 97 FROM_HERE, 98 base::Bind(continuation, status == SERVICE_WORKER_OK)); 99 } 100 101 void ServiceWorkerContextWrapper::UnregisterServiceWorker( 102 const GURL& pattern, 103 const ResultCallback& continuation) { 104 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 105 BrowserThread::PostTask( 106 BrowserThread::IO, 107 FROM_HERE, 108 base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker, 109 this, 110 pattern, 111 continuation)); 112 return; 113 } 114 115 context()->UnregisterServiceWorker( 116 pattern, 117 base::Bind(&FinishUnregistrationOnIO, continuation)); 118 } 119 120 void ServiceWorkerContextWrapper::Terminate() { 121 DCHECK_CURRENTLY_ON(BrowserThread::UI); 122 process_manager_->Shutdown(); 123 } 124 125 void ServiceWorkerContextWrapper::AddObserver( 126 ServiceWorkerContextObserver* observer) { 127 observer_list_->AddObserver(observer); 128 } 129 130 void ServiceWorkerContextWrapper::RemoveObserver( 131 ServiceWorkerContextObserver* observer) { 132 observer_list_->RemoveObserver(observer); 133 } 134 135 void ServiceWorkerContextWrapper::InitInternal( 136 const base::FilePath& user_data_directory, 137 base::SequencedTaskRunner* database_task_runner, 138 base::MessageLoopProxy* disk_cache_thread, 139 quota::QuotaManagerProxy* quota_manager_proxy) { 140 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 141 BrowserThread::PostTask( 142 BrowserThread::IO, 143 FROM_HERE, 144 base::Bind(&ServiceWorkerContextWrapper::InitInternal, 145 this, 146 user_data_directory, 147 make_scoped_refptr(database_task_runner), 148 make_scoped_refptr(disk_cache_thread), 149 make_scoped_refptr(quota_manager_proxy))); 150 return; 151 } 152 DCHECK(!context_core_); 153 context_core_.reset(new ServiceWorkerContextCore(user_data_directory, 154 database_task_runner, 155 disk_cache_thread, 156 quota_manager_proxy, 157 observer_list_, 158 this)); 159 } 160 161 void ServiceWorkerContextWrapper::ShutdownOnIO() { 162 DCHECK_CURRENTLY_ON(BrowserThread::IO); 163 context_core_.reset(); 164 } 165 166 } // namespace content 167