Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: extensions/browser/service_worker_manager.cc

Issue 182253010: Register a Service Worker when an extension is enabled. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test passes! Don't know if it's right though Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « extensions/browser/service_worker_manager.h ('k') | extensions/extensions.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "extensions/browser/service_worker_manager.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "chrome/browser/extensions/extension_host.h"
10 #include "components/keyed_service/content/browser_context_dependency_manager.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/service_worker_context.h"
15 #include "content/public/browser/storage_partition.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/browser/extensions_browser_client.h"
18 #include "extensions/browser/process_manager.h"
19 #include "extensions/common/manifest_handlers/background_info.h"
20
21 namespace extensions {
22
23 using base::Callback;
24 using base::Closure;
25 using base::WeakPtr;
26 using content::BrowserContext;
27 using content::BrowserThread;
28 using content::ServiceWorkerStatusCode;
29
30 ServiceWorkerManager::State::State() {}
31 ServiceWorkerManager::State::~State() {}
32
33 ServiceWorkerManager::ServiceWorkerManager(BrowserContext* context)
34 : context_(context), weak_this_factory_(this) {}
35 ServiceWorkerManager::~ServiceWorkerManager() {}
36
37 ServiceWorkerManager* ServiceWorkerManager::Get(
38 content::BrowserContext* context) {
39 return ServiceWorkerManagerFactory::GetForBrowserContext(context);
40 }
41
42 content::StoragePartition* ServiceWorkerManager::GetStoragePartition(
43 const ExtensionId& ext_id) const {
44 return content::BrowserContext::GetStoragePartitionForSite(
45 context_, Extension::GetBaseURLFromExtensionId(ext_id));
46 }
47
48 content::ServiceWorkerContext* ServiceWorkerManager::GetSWContext(
49 const ExtensionId& ext_id) const {
50 return GetStoragePartition(ext_id)->GetServiceWorkerContext();
51 }
52
53 // alecflett says that if we send a series of RegisterServiceWorker and
54 // UnregisterServiceWorker calls on the same scope to a
55 // ServiceWorkerContextCore, we're guaranteed that the callbacks come back in
56 // the same order, and that the last one will be the final state.
57 void ServiceWorkerManager::RegisterExtension(const Extension* extension) {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI);
59 CHECK(BackgroundInfo::HasServiceWorker(extension));
60 State& ext_state = states_[extension->id()];
61 if (ext_state.registration == REGISTERING ||
62 ext_state.registration == REGISTERED)
63 return;
64 ext_state.registration = REGISTERING;
65 ++ext_state.outstanding_state_changes;
66 const GURL service_worker_script = extension->GetResourceURL(
67 BackgroundInfo::GetServiceWorkerScript(extension));
68 // TODO(jyasskin): Create the extension process in a cleaner way. We don't
69 // need a view, for instance. Using the service_worker_script as the
70 // background host is just totally horrible.
71 extensions::ProcessManager* process_manager =
72 ExtensionSystem::Get(context_)->process_manager();
73 CHECK(process_manager->CreateBackgroundHost(
74 extension,
75 service_worker_script,
76 base::Bind(&ServiceWorkerManager::ContinueRegistrationWithExtensionHost,
77 WeakThis(),
78 extension->id(),
79 extension->GetResourceURL("/*"),
80 service_worker_script)));
81 }
82
83 void ServiceWorkerManager::ContinueRegistrationWithExtensionHost(
84 const ExtensionId& extension_id,
85 const GURL& scope,
86 const GURL& service_worker_script) {
87 extensions::ProcessManager* process_manager =
88 ExtensionSystem::Get(context_)->process_manager();
89 ExtensionHost* host =
90 process_manager->GetBackgroundHostForExtension(extension_id);
91
92 GetSWContext(extension_id)->RegisterServiceWorker(
93 scope,
94 service_worker_script,
95 host->render_process_host()->GetID(),
96 base::Bind(
97 &ServiceWorkerManager::FinishRegistration, WeakThis(), extension_id));
98 }
99
100 void ServiceWorkerManager::FinishRegistration(const ExtensionId& extension_id,
101 ServiceWorkerStatusCode result) {
102 DCHECK_CURRENTLY_ON(BrowserThread::UI);
103 State& ext_state = states_[extension_id];
104 --ext_state.outstanding_state_changes;
105 DCHECK_GE(ext_state.outstanding_state_changes, 0);
106 if (ext_state.outstanding_state_changes > 0)
107 return;
108
109 DCHECK_EQ(ext_state.registration, REGISTERING);
110 std::vector<Closure> to_run;
111 switch (result) {
112 case content::SERVICE_WORKER_OK:
113 ext_state.registration = REGISTERED;
114 to_run.swap(ext_state.registration_succeeded);
115 ext_state.registration_failed.clear();
116 break;
117 default:
118 LOG(ERROR) << "Service Worker Registration failed for extension "
119 << extension_id << ": "
120 << content::ServiceWorkerStatusToString(result);
121 to_run.swap(ext_state.registration_failed);
122 states_.erase(extension_id);
123 break;
124 }
125
126 for (size_t i = 0; i < to_run.size(); ++i) {
127 to_run[i].Run();
128 }
129 }
130
131 void ServiceWorkerManager::UnregisterExtension(const Extension* extension) {
132 DCHECK_CURRENTLY_ON(BrowserThread::UI);
133 CHECK(BackgroundInfo::HasServiceWorker(extension));
134
135 base::hash_map<ExtensionId, State>::iterator it =
136 states_.find(extension->id());
137 if (it == states_.end()) {
138 // Extension isn't registered.
139 return;
140 }
141 State& ext_state = it->second;
142 if (ext_state.registration == UNREGISTERING)
143 return;
144
145 ext_state.registration = UNREGISTERING;
146 ++ext_state.outstanding_state_changes;
147
148 const GURL service_worker_script = extension->GetResourceURL(
149 BackgroundInfo::GetServiceWorkerScript(extension));
150 // TODO(jyasskin): Create the extension process in a cleaner way. We don't
151 // need a view, for instance. Using the service_worker_script as the
152 // background host is just totally horrible.
153 extensions::ProcessManager* process_manager =
154 ExtensionSystem::Get(context_)->process_manager();
155 CHECK(process_manager->CreateBackgroundHost(
156 extension,
157 service_worker_script,
158 base::Bind(&ServiceWorkerManager::ContinueUnregistrationWithExtensionHost,
159 WeakThis(),
160 extension->id(),
161 extension->GetResourceURL("/*"))));
162 }
163
164 void ServiceWorkerManager::ContinueUnregistrationWithExtensionHost(
165 const ExtensionId& extension_id,
166 const GURL& scope) {
167 extensions::ProcessManager* process_manager =
168 ExtensionSystem::Get(context_)->process_manager();
169 ExtensionHost* host =
170 process_manager->GetBackgroundHostForExtension(extension_id);
171
172 GetSWContext(extension_id)->UnregisterServiceWorker(
173 scope,
174 host->render_process_host()->GetID(),
175 base::Bind(&ServiceWorkerManager::FinishUnregistration,
176 WeakThis(),
177 extension_id));
178 }
179
180 void ServiceWorkerManager::FinishUnregistration(
181 const ExtensionId& extension_id,
182 ServiceWorkerStatusCode result) {
183 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 State& ext_state = states_[extension_id];
185 --ext_state.outstanding_state_changes;
186 DCHECK_GE(ext_state.outstanding_state_changes, 0);
187 if (ext_state.outstanding_state_changes > 0)
188 return;
189
190 DCHECK_EQ(ext_state.registration, UNREGISTERING);
191 std::vector<Closure> to_run;
192 switch (result) {
193 case content::SERVICE_WORKER_OK:
194 to_run.swap(ext_state.unregistration_succeeded);
195 states_.erase(extension_id);
196 break;
197 default:
198 LOG(ERROR) << "Service Worker Unregistration failed for extension "
199 << extension_id << ": "
200 << content::ServiceWorkerStatusToString(result);
201 ext_state.registration = REGISTERED;
202 to_run.swap(ext_state.unregistration_failed);
203 ext_state.unregistration_succeeded.clear();
204 break;
205 }
206
207 for (size_t i = 0; i < to_run.size(); ++i) {
208 to_run[i].Run();
209 }
210 }
211
212 WeakPtr<ServiceWorkerManager> ServiceWorkerManager::WeakThis() {
213 return weak_this_factory_.GetWeakPtr();
214 }
215
216 // ServiceWorkerManagerFactory
217
218 ServiceWorkerManager* ServiceWorkerManagerFactory::GetForBrowserContext(
219 content::BrowserContext* context) {
220 return static_cast<ServiceWorkerManager*>(
221 GetInstance()->GetServiceForBrowserContext(context, true));
222 }
223
224 ServiceWorkerManagerFactory* ServiceWorkerManagerFactory::GetInstance() {
225 return Singleton<ServiceWorkerManagerFactory>::get();
226 }
227
228 void ServiceWorkerManagerFactory::SetInstanceForTesting(
229 content::BrowserContext* context,
230 ServiceWorkerManager* manager) {
231 Associate(context, manager);
232 }
233
234 ServiceWorkerManagerFactory::ServiceWorkerManagerFactory()
235 : BrowserContextKeyedServiceFactory(
236 "ServiceWorkerManager",
237 BrowserContextDependencyManager::GetInstance()) {}
238
239 ServiceWorkerManagerFactory::~ServiceWorkerManagerFactory() {}
240
241 KeyedService* ServiceWorkerManagerFactory::BuildServiceInstanceFor(
242 content::BrowserContext* context) const {
243 return new ServiceWorkerManager(context);
244 }
245
246 // TODO(jyasskin): Deal with incognito mode.
247 content::BrowserContext* ServiceWorkerManagerFactory::GetBrowserContextToUse(
248 content::BrowserContext* context) const {
249 return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
250 }
251
252 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/service_worker_manager.h ('k') | extensions/extensions.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698