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

Side by Side Diff: chrome/browser/extensions/extension_event_router.cc

Issue 7672009: Lazy creating of background pages --enable-lazy-background-pages) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Move implementation to ExtensionEventRouter and store pending events in a queue Created 9 years, 4 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_event_router.h" 5 #include "chrome/browser/extensions/extension_event_router.h"
6 6
7 #include "base/command_line.h"
7 #include "base/values.h" 8 #include "base/values.h"
8 #include "chrome/browser/extensions/extension_devtools_manager.h" 9 #include "chrome/browser/extensions/extension_devtools_manager.h"
10 #include "chrome/browser/extensions/extension_host.h"
9 #include "chrome/browser/extensions/extension_processes_api.h" 11 #include "chrome/browser/extensions/extension_processes_api.h"
10 #include "chrome/browser/extensions/extension_processes_api_constants.h" 12 #include "chrome/browser/extensions/extension_processes_api_constants.h"
11 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_tabs_module.h" 14 #include "chrome/browser/extensions/extension_tabs_module.h"
13 #include "chrome/browser/extensions/extension_webrequest_api.h" 15 #include "chrome/browser/extensions/extension_webrequest_api.h"
14 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/extensions/extension.h" 18 #include "chrome/common/extensions/extension.h"
16 #include "chrome/common/extensions/extension_messages.h" 19 #include "chrome/common/extensions/extension_messages.h"
17 #include "content/browser/child_process_security_policy.h" 20 #include "content/browser/child_process_security_policy.h"
18 #include "content/browser/renderer_host/render_process_host.h" 21 #include "content/browser/renderer_host/render_process_host.h"
19 #include "content/common/notification_service.h" 22 #include "content/common/notification_service.h"
20 23
21 namespace { 24 namespace {
22 25
23 const char kDispatchEvent[] = "Event.dispatchJSON"; 26 const char kDispatchEvent[] = "Event.dispatchJSON";
24 27
(...skipping 16 matching lines...) Expand all
41 44
42 bool operator<(const EventListener& that) const { 45 bool operator<(const EventListener& that) const {
43 if (process < that.process) 46 if (process < that.process)
44 return true; 47 return true;
45 if (process == that.process && extension_id < that.extension_id) 48 if (process == that.process && extension_id < that.extension_id)
46 return true; 49 return true;
47 return false; 50 return false;
48 } 51 }
49 }; 52 };
50 53
54 struct ExtensionEventRouter::PendingEvent {
55 std::string name;
56 std::string args;
57 Profile* restrict_to_profile;
58 std::string cross_incognito_args;
59 GURL url;
60
61 PendingEvent(const std::string& name, const std::string& args,
62 Profile* restrict_to_profile,
63 const std::string& cross_incognito_args, const GURL& url)
64 : name(name), args(args), restrict_to_profile(restrict_to_profile),
65 cross_incognito_args(cross_incognito_args), url(url) {}
66 };
67
51 // static 68 // static
52 void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender, 69 void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender,
53 const std::string& extension_id, 70 const std::string& extension_id,
54 const std::string& event_name, 71 const std::string& event_name,
55 const std::string& event_args, 72 const std::string& event_args,
56 const GURL& event_url) { 73 const GURL& event_url) {
57 ListValue args; 74 ListValue args;
58 args.Set(0, Value::CreateStringValue(event_name)); 75 args.Set(0, Value::CreateStringValue(event_name));
59 args.Set(1, Value::CreateStringValue(event_args)); 76 args.Set(1, Value::CreateStringValue(event_args));
60 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, 77 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL,
61 extension_id, kDispatchEvent, args, event_url)); 78 extension_id, kDispatchEvent, args, event_url));
62 } 79 }
63 80
64 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) 81 ExtensionEventRouter::ExtensionEventRouter(Profile* profile)
65 : profile_(profile), 82 : profile_(profile),
66 extension_devtools_manager_(profile->GetExtensionDevToolsManager()) { 83 extension_devtools_manager_(profile->GetExtensionDevToolsManager()) {
67 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 84 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
68 NotificationService::AllSources()); 85 NotificationService::AllSources());
69 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 86 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
70 NotificationService::AllSources()); 87 NotificationService::AllSources());
88 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
89 Source<Profile>(profile_));
90 // TODO(tessamac): also get notified for background page crash/failure.
71 } 91 }
72 92
73 ExtensionEventRouter::~ExtensionEventRouter() { 93 ExtensionEventRouter::~ExtensionEventRouter() {
74 } 94 }
75 95
76 void ExtensionEventRouter::AddEventListener( 96 void ExtensionEventRouter::AddEventListener(
77 const std::string& event_name, 97 const std::string& event_name,
78 RenderProcessHost* process, 98 RenderProcessHost* process,
79 const std::string& extension_id) { 99 const std::string& extension_id) {
80 EventListener listener(process, extension_id); 100 EventListener listener(process, extension_id);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 return true; 155 return true;
136 } 156 }
137 return false; 157 return false;
138 } 158 }
139 159
140 void ExtensionEventRouter::DispatchEventToRenderers( 160 void ExtensionEventRouter::DispatchEventToRenderers(
141 const std::string& event_name, 161 const std::string& event_name,
142 const std::string& event_args, 162 const std::string& event_args,
143 Profile* restrict_to_profile, 163 Profile* restrict_to_profile,
144 const GURL& event_url) { 164 const GURL& event_url) {
145 DispatchEventImpl("", event_name, event_args, restrict_to_profile, "", 165 MaybeDispatchEventImpl("", event_name, event_args, restrict_to_profile, "",
146 event_url); 166 event_url);
147 } 167 }
148 168
149 void ExtensionEventRouter::DispatchEventToExtension( 169 void ExtensionEventRouter::DispatchEventToExtension(
150 const std::string& extension_id, 170 const std::string& extension_id,
151 const std::string& event_name, 171 const std::string& event_name,
152 const std::string& event_args, 172 const std::string& event_args,
153 Profile* restrict_to_profile, 173 Profile* restrict_to_profile,
154 const GURL& event_url) { 174 const GURL& event_url) {
155 DCHECK(!extension_id.empty()); 175 DCHECK(!extension_id.empty());
156 DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile, 176 MaybeDispatchEventImpl(extension_id, event_name, event_args,
157 "", event_url); 177 restrict_to_profile, "", event_url);
158 } 178 }
159 179
160 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( 180 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
161 const std::string& event_name, 181 const std::string& event_name,
162 const std::string& event_args, 182 const std::string& event_args,
163 Profile* restrict_to_profile, 183 Profile* restrict_to_profile,
164 const std::string& cross_incognito_args, 184 const std::string& cross_incognito_args,
165 const GURL& event_url) { 185 const GURL& event_url) {
166 DispatchEventImpl("", event_name, event_args, restrict_to_profile, 186 MaybeDispatchEventImpl("", event_name, event_args, restrict_to_profile,
187 cross_incognito_args, event_url);
188 }
189
190 void ExtensionEventRouter::MaybeDispatchEventImpl(
Aaron Boodman 2011/08/18 19:25:55 Another 'maybe' function. You could eliminate this
Tessa MacDuff 2011/08/23 18:18:42 Done.
191 const std::string& extension_id,
192 const std::string& event_name,
193 const std::string& event_args,
194 Profile* restrict_to_profile,
195 const std::string& cross_incognito_args,
196 const GURL& event_url) {
197 if (!profile_)
198 return;
199
200 if (CommandLine::ForCurrentProcess()->HasSwitch(
201 switches::kEnableLazyBackgroundPages) &&
202 !extension_id.empty()) {
203 // TODO(tessamac): Decide what to when there's no extension id.
204 // Create all background pages?
Aaron Boodman 2011/08/18 19:25:55 I think creating all background pages is the right
Tessa MacDuff 2011/08/23 18:18:42 I think I'll do this in a separate CL as since it
205 const Extension* extension = profile_->GetExtensionService()->
206 GetExtensionById(extension_id, false); // exclude disable extensions
207 if (extension && extension->background_url().is_valid()) {
208 ExtensionProcessManager* pm = profile_->GetExtensionProcessManager();
209 if (pm->GetBackgroundHostForExtension(extension) == NULL) {
210 EnqueueEvent(extension_id, event_name, event_args, restrict_to_profile,
211 cross_incognito_args, event_url);
212 pm->CreateBackgroundHost(extension, extension->background_url());
213 return;
214 }
215 }
216
217 }
218
219 DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile,
167 cross_incognito_args, event_url); 220 cross_incognito_args, event_url);
168 } 221 }
169 222
170 void ExtensionEventRouter::DispatchEventImpl( 223 void ExtensionEventRouter::DispatchEventImpl(
171 const std::string& extension_id, 224 const std::string& extension_id,
172 const std::string& event_name, 225 const std::string& event_name,
173 const std::string& event_args, 226 const std::string& event_args,
174 Profile* restrict_to_profile, 227 Profile* restrict_to_profile,
175 const std::string& cross_incognito_args, 228 const std::string& cross_incognito_args,
176 const GURL& event_url) { 229 const GURL& event_url) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 event_name, cross_incognito_args, event_url); 266 event_name, cross_incognito_args, event_url);
214 } 267 }
215 continue; 268 continue;
216 } 269 }
217 270
218 DispatchEvent(listener->process, listener->extension_id, 271 DispatchEvent(listener->process, listener->extension_id,
219 event_name, event_args, event_url); 272 event_name, event_args, event_url);
220 } 273 }
221 } 274 }
222 275
276 void ExtensionEventRouter::EnqueueEvent(const std::string &extension_id,
277 const std::string& event_name,
278 const std::string& event_args,
279 Profile* restrict_to_profile,
280 const std::string& cross_incognito_args,
281 const GURL& event_url) {
282 PendingEvent event(event_name, event_args, restrict_to_profile,
283 cross_incognito_args, event_url);
284 // TODO: use insert instead of [].
285 pending_events_[extension_id].push_back(event);
Aaron Boodman 2011/08/18 19:25:55 I'm fine with this for now, but just so you know t
Tessa MacDuff 2011/08/23 18:18:42 Done.
286 }
287
288 void ExtensionEventRouter::ClearPendingEvents(const std::string &extension_id) {
289 pending_events_[extension_id].clear();
Aaron Boodman 2011/08/18 19:29:06 Little nit: If these one-liner methods aren't call
Tessa MacDuff 2011/08/23 18:18:42 Done. I had to add an additional NewRunnableMetho
290 }
291
292 void ExtensionEventRouter::DispatchPendingEvents(
293 const std::string &extension_id) {
294 const PendingEventsQueue& queue = pending_events_[extension_id];
295 for (PendingEventsQueue::const_iterator it = queue.begin();
296 it != queue.end(); ++it) {
297 // Don't call MaybeDispatchEventImpl() to guard against these events
298 // being re-enqueued if the Background Page still isn't all set.
Aaron Boodman 2011/08/18 19:29:06 Oh, I see. I don't think it's a big deal if they g
Tessa MacDuff 2011/08/18 20:49:39 I was worried about what would happen if we were a
Aaron Boodman 2011/08/18 21:19:23 ok (to extra arg).
Tessa MacDuff 2011/08/23 18:18:42 Done.
299 DispatchEventImpl(extension_id, it->name, it->args, it->restrict_to_profile,
300 it->cross_incognito_args, it->url);
301 }
302 ClearPendingEvents(extension_id);
303 }
304
223 void ExtensionEventRouter::Observe(int type, 305 void ExtensionEventRouter::Observe(int type,
224 const NotificationSource& source, 306 const NotificationSource& source,
225 const NotificationDetails& details) { 307 const NotificationDetails& details) {
226 switch (type) { 308 switch (type) {
227 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 309 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
228 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 310 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
229 RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr(); 311 RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr();
230 // Remove all event listeners associated with this renderer 312 // Remove all event listeners associated with this renderer
231 for (ListenerMap::iterator it = listeners_.begin(); 313 for (ListenerMap::iterator it = listeners_.begin();
232 it != listeners_.end(); ) { 314 it != listeners_.end(); ) {
233 ListenerMap::iterator current_it = it++; 315 ListenerMap::iterator current_it = it++;
234 for (std::set<EventListener>::iterator jt = current_it->second.begin(); 316 for (std::set<EventListener>::iterator jt = current_it->second.begin();
235 jt != current_it->second.end(); ) { 317 jt != current_it->second.end(); ) {
236 std::set<EventListener>::iterator current_jt = jt++; 318 std::set<EventListener>::iterator current_jt = jt++;
237 if (current_jt->process == renderer) { 319 if (current_jt->process == renderer) {
238 RemoveEventListener(current_it->first, 320 RemoveEventListener(current_it->first,
239 current_jt->process, 321 current_jt->process,
240 current_jt->extension_id); 322 current_jt->extension_id);
241 } 323 }
242 } 324 }
243 } 325 }
244 break; 326 break;
245 } 327 }
328 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
329 // TODO: dispatch events in queue. ExtensionHost is in the details.
330 ExtensionHost* eh = Details<ExtensionHost>(details).ptr();
331 DispatchPendingEvents(eh->extension_id());
332 break;
333 }
334 // TODO(tessamac): if background page crashed/failed clear queue.
246 default: 335 default:
247 NOTREACHED(); 336 NOTREACHED();
248 return; 337 return;
249 } 338 }
250 } 339 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698