OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/worker_host/worker_process_host.h" | 5 #include "chrome/browser/worker_host/worker_process_host.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "chrome/browser/appcache/appcache_dispatcher_host.h" | 15 #include "chrome/browser/appcache/appcache_dispatcher_host.h" |
16 #include "chrome/browser/browser_thread.h" | 16 #include "chrome/browser/browser_thread.h" |
17 #include "chrome/browser/child_process_security_policy.h" | 17 #include "chrome/browser/child_process_security_policy.h" |
18 #include "chrome/browser/content_settings/host_content_settings_map.h" | 18 #include "chrome/browser/content_settings/host_content_settings_map.h" |
19 #include "chrome/browser/file_system/file_system_dispatcher_host.h" | 19 #include "chrome/browser/file_system/file_system_dispatcher_host.h" |
20 #include "chrome/browser/mime_registry_message_filter.h" | 20 #include "chrome/browser/mime_registry_message_filter.h" |
21 #include "chrome/browser/net/chrome_url_request_context.h" | 21 #include "chrome/browser/net/chrome_url_request_context.h" |
22 #include "chrome/browser/profiles/profile.h" | |
23 #include "chrome/browser/renderer_host/blob_message_filter.h" | 22 #include "chrome/browser/renderer_host/blob_message_filter.h" |
24 #include "chrome/browser/renderer_host/database_message_filter.h" | 23 #include "chrome/browser/renderer_host/database_message_filter.h" |
25 #include "chrome/browser/renderer_host/file_utilities_message_filter.h" | 24 #include "chrome/browser/renderer_host/file_utilities_message_filter.h" |
26 #include "chrome/browser/renderer_host/render_message_filter.h" | |
27 #include "chrome/browser/renderer_host/render_view_host.h" | 25 #include "chrome/browser/renderer_host/render_view_host.h" |
28 #include "chrome/browser/renderer_host/render_view_host_delegate.h" | 26 #include "chrome/browser/renderer_host/render_view_host_delegate.h" |
29 #include "chrome/browser/renderer_host/render_view_host_notification_task.h" | 27 #include "chrome/browser/renderer_host/render_view_host_notification_task.h" |
30 #include "chrome/browser/renderer_host/socket_stream_dispatcher_host.h" | 28 #include "chrome/browser/renderer_host/socket_stream_dispatcher_host.h" |
31 #include "chrome/browser/worker_host/message_port_dispatcher.h" | 29 #include "chrome/browser/worker_host/message_port_service.h" |
30 #include "chrome/browser/worker_host/worker_message_filter.h" | |
32 #include "chrome/browser/worker_host/worker_service.h" | 31 #include "chrome/browser/worker_host/worker_service.h" |
33 #include "chrome/common/chrome_switches.h" | 32 #include "chrome/common/chrome_switches.h" |
34 #include "chrome/common/debug_flags.h" | 33 #include "chrome/common/debug_flags.h" |
35 #include "chrome/common/notification_service.h" | |
36 #include "chrome/common/render_messages.h" | 34 #include "chrome/common/render_messages.h" |
37 #include "chrome/common/render_messages_params.h" | 35 #include "chrome/common/render_messages_params.h" |
38 #include "chrome/common/result_codes.h" | 36 #include "chrome/common/result_codes.h" |
39 #include "chrome/common/worker_messages.h" | 37 #include "chrome/common/worker_messages.h" |
40 #include "net/base/mime_util.h" | 38 #include "net/base/mime_util.h" |
41 #include "ipc/ipc_switches.h" | 39 #include "ipc/ipc_switches.h" |
42 #include "net/base/registry_controlled_domain.h" | 40 #include "net/base/registry_controlled_domain.h" |
43 #include "webkit/fileapi/file_system_path_manager.h" | 41 #include "webkit/fileapi/file_system_path_manager.h" |
44 | 42 |
45 // Notifies RenderViewHost that one or more worker objects crashed. | 43 // Notifies RenderViewHost that one or more worker objects crashed. |
(...skipping 14 matching lines...) Expand all Loading... | |
60 } | 58 } |
61 } | 59 } |
62 | 60 |
63 private: | 61 private: |
64 int render_process_unique_id_; | 62 int render_process_unique_id_; |
65 int render_view_id_; | 63 int render_view_id_; |
66 }; | 64 }; |
67 | 65 |
68 WorkerProcessHost::WorkerProcessHost( | 66 WorkerProcessHost::WorkerProcessHost( |
69 ResourceDispatcherHost* resource_dispatcher_host, | 67 ResourceDispatcherHost* resource_dispatcher_host, |
70 ChromeURLRequestContext *request_context) | 68 URLRequestContextGetter* request_context) |
71 : BrowserChildProcessHost(WORKER_PROCESS, resource_dispatcher_host), | 69 : BrowserChildProcessHost(WORKER_PROCESS, resource_dispatcher_host), |
72 request_context_(request_context) { | 70 request_context_(request_context) { |
73 next_route_id_callback_.reset(NewCallbackWithReturnValue( | |
74 WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); | |
75 } | 71 } |
76 | 72 |
77 WorkerProcessHost::~WorkerProcessHost() { | 73 WorkerProcessHost::~WorkerProcessHost() { |
78 // Let interested observers know we are being deleted. | |
79 NotificationService::current()->Notify( | |
80 NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, | |
81 Source<WorkerProcessHost>(this), | |
82 NotificationService::NoDetails()); | |
83 | |
84 // If we crashed, tell the RenderViewHosts. | 74 // If we crashed, tell the RenderViewHosts. |
85 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 75 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
86 const WorkerDocumentSet::DocumentInfoSet& parents = | 76 const WorkerDocumentSet::DocumentInfoSet& parents = |
87 i->worker_document_set()->documents(); | 77 i->worker_document_set()->documents(); |
88 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | 78 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
89 parents.begin(); parent_iter != parents.end(); ++parent_iter) { | 79 parents.begin(); parent_iter != parents.end(); ++parent_iter) { |
90 BrowserThread::PostTask( | 80 BrowserThread::PostTask( |
91 BrowserThread::UI, FROM_HERE, | 81 BrowserThread::UI, FROM_HERE, |
92 new WorkerCrashTask(parent_iter->renderer_id(), | 82 new WorkerCrashTask(parent_iter->render_process_id(), |
93 parent_iter->render_view_route_id())); | 83 parent_iter->render_view_id())); |
94 } | 84 } |
95 } | 85 } |
96 | 86 |
97 ChildProcessSecurityPolicy::GetInstance()->Remove(id()); | 87 ChildProcessSecurityPolicy::GetInstance()->Remove(id()); |
98 } | 88 } |
99 | 89 |
100 bool WorkerProcessHost::Init() { | 90 bool WorkerProcessHost::Init(int render_process_id) { |
101 if (!CreateChannel()) | 91 if (!CreateChannel()) |
102 return false; | 92 return false; |
103 | 93 |
104 FilePath exe_path = GetChildPath(true); | 94 FilePath exe_path = GetChildPath(true); |
105 if (exe_path.empty()) | 95 if (exe_path.empty()) |
106 return false; | 96 return false; |
107 | 97 |
108 CommandLine* cmd_line = new CommandLine(exe_path); | 98 CommandLine* cmd_line = new CommandLine(exe_path); |
109 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kWorkerProcess); | 99 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kWorkerProcess); |
110 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); | 100 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 | 154 |
165 ChildProcessSecurityPolicy::GetInstance()->Add(id()); | 155 ChildProcessSecurityPolicy::GetInstance()->Add(id()); |
166 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 156 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
167 switches::kDisableFileSystem)) { | 157 switches::kDisableFileSystem)) { |
168 // Grant most file permissions to this worker. | 158 // Grant most file permissions to this worker. |
169 // PLATFORM_FILE_TEMPORARY, PLATFORM_FILE_HIDDEN and | 159 // PLATFORM_FILE_TEMPORARY, PLATFORM_FILE_HIDDEN and |
170 // PLATFORM_FILE_DELETE_ON_CLOSE are not granted, because no existing API | 160 // PLATFORM_FILE_DELETE_ON_CLOSE are not granted, because no existing API |
171 // requests them. | 161 // requests them. |
172 ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( | 162 ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( |
173 id(), | 163 id(), |
174 request_context_->file_system_context()-> | 164 GetChromeURLRequestContext()->file_system_context()-> |
175 path_manager()->base_path(), | 165 path_manager()->base_path(), |
176 base::PLATFORM_FILE_OPEN | | 166 base::PLATFORM_FILE_OPEN | |
177 base::PLATFORM_FILE_CREATE | | 167 base::PLATFORM_FILE_CREATE | |
178 base::PLATFORM_FILE_OPEN_ALWAYS | | 168 base::PLATFORM_FILE_OPEN_ALWAYS | |
179 base::PLATFORM_FILE_CREATE_ALWAYS | | 169 base::PLATFORM_FILE_CREATE_ALWAYS | |
180 base::PLATFORM_FILE_READ | | 170 base::PLATFORM_FILE_READ | |
181 base::PLATFORM_FILE_WRITE | | 171 base::PLATFORM_FILE_WRITE | |
182 base::PLATFORM_FILE_EXCLUSIVE_READ | | 172 base::PLATFORM_FILE_EXCLUSIVE_READ | |
183 base::PLATFORM_FILE_EXCLUSIVE_WRITE | | 173 base::PLATFORM_FILE_EXCLUSIVE_WRITE | |
184 base::PLATFORM_FILE_ASYNC | | 174 base::PLATFORM_FILE_ASYNC | |
185 base::PLATFORM_FILE_TRUNCATE | | 175 base::PLATFORM_FILE_TRUNCATE | |
186 base::PLATFORM_FILE_WRITE_ATTRIBUTES); | 176 base::PLATFORM_FILE_WRITE_ATTRIBUTES); |
187 } | 177 } |
188 | 178 |
189 CreateMessageFilters(); | 179 CreateMessageFilters(render_process_id); |
Andrew T Wilson (Slow)
2010/12/21 03:12:21
I'm concerned that we're keeping the creator's ren
jam
2010/12/21 07:41:51
yep, it's the parent process. My goal was to not
| |
190 | 180 |
191 return true; | 181 return true; |
192 } | 182 } |
193 | 183 |
194 void WorkerProcessHost::CreateMessageFilters() { | 184 void WorkerProcessHost::CreateMessageFilters(int render_process_id) { |
195 AddFilter(new AppCacheDispatcherHost(request_context_, id())); | 185 ChromeURLRequestContext* chrome_url_context = GetChromeURLRequestContext(); |
196 AddFilter(new FileSystemDispatcherHost(request_context_)); | 186 |
187 worker_message_filter_= new WorkerMessageFilter( | |
188 render_process_id, | |
189 request_context_, | |
190 resource_dispatcher_host(), | |
191 NewCallbackWithReturnValue( | |
192 WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); | |
193 AddFilter(worker_message_filter_); | |
194 AddFilter(new AppCacheDispatcherHost(chrome_url_context, id())); | |
195 AddFilter(new FileSystemDispatcherHost(chrome_url_context)); | |
197 AddFilter(new FileUtilitiesMessageFilter(id())); | 196 AddFilter(new FileUtilitiesMessageFilter(id())); |
198 AddFilter( | 197 AddFilter( |
199 new BlobMessageFilter(id(), request_context_->blob_storage_context())); | 198 new BlobMessageFilter(id(), chrome_url_context->blob_storage_context())); |
200 AddFilter(new MimeRegistryMessageFilter()); | 199 AddFilter(new MimeRegistryMessageFilter()); |
201 AddFilter(new DatabaseMessageFilter( | 200 AddFilter(new DatabaseMessageFilter( |
202 request_context_->database_tracker(), | 201 chrome_url_context->database_tracker(), |
203 request_context_->host_content_settings_map())); | 202 chrome_url_context->host_content_settings_map())); |
204 AddFilter(new SocketStreamDispatcherHost()); | 203 AddFilter(new SocketStreamDispatcherHost()); |
205 } | 204 } |
206 | 205 |
207 void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) { | 206 void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) { |
208 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL( | 207 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL( |
209 id(), instance.url()); | 208 id(), instance.url()); |
210 | 209 |
211 instances_.push_back(instance); | 210 instances_.push_back(instance); |
212 | 211 |
213 WorkerProcessMsg_CreateWorker_Params params; | 212 WorkerProcessMsg_CreateWorker_Params params; |
214 params.url = instance.url(); | 213 params.url = instance.url(); |
215 params.is_shared = instance.shared(); | 214 params.is_shared = instance.shared(); |
216 params.name = instance.name(); | 215 params.name = instance.name(); |
217 params.route_id = instance.worker_route_id(); | 216 params.route_id = instance.worker_route_id(); |
218 params.creator_process_id = instance.parent_process_id(); | 217 params.creator_process_id = instance.parent_process_id(); |
219 params.creator_appcache_host_id = instance.parent_appcache_host_id(); | 218 params.creator_appcache_host_id = instance.parent_appcache_host_id(); |
220 params.shared_worker_appcache_id = instance.main_resource_appcache_id(); | 219 params.shared_worker_appcache_id = instance.main_resource_appcache_id(); |
221 Send(new WorkerProcessMsg_CreateWorker(params)); | 220 Send(new WorkerProcessMsg_CreateWorker(params)); |
222 | 221 |
223 UpdateTitle(); | 222 UpdateTitle(); |
224 | 223 |
225 // Walk all pending senders and let them know the worker has been created | 224 // Walk all pending filters and let them know the worker has been created |
226 // (could be more than one in the case where we had to queue up worker | 225 // (could be more than one in the case where we had to queue up worker |
227 // creation because the worker process limit was reached). | 226 // creation because the worker process limit was reached). |
228 for (WorkerInstance::SenderList::const_iterator i = | 227 for (WorkerInstance::FilterList::const_iterator i = |
229 instance.senders().begin(); | 228 instance.filters().begin(); |
230 i != instance.senders().end(); ++i) { | 229 i != instance.filters().end(); ++i) { |
231 i->first->Send(new ViewMsg_WorkerCreated(i->second)); | 230 i->first->Send(new ViewMsg_WorkerCreated(i->second)); |
232 } | 231 } |
233 } | 232 } |
234 | 233 |
235 bool WorkerProcessHost::FilterMessage(const IPC::Message& message, | 234 bool WorkerProcessHost::FilterMessage(const IPC::Message& message, |
236 IPC::Message::Sender* sender) { | 235 WorkerMessageFilter* filter) { |
237 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 236 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
238 if (!i->closed() && i->HasSender(sender, message.routing_id())) { | 237 if (!i->closed() && i->HasFilter(filter, message.routing_id())) { |
239 RelayMessage( | 238 RelayMessage(message, worker_message_filter_, i->worker_route_id()); |
240 message, this, i->worker_route_id(), next_route_id_callback_.get()); | |
241 return true; | 239 return true; |
242 } | 240 } |
243 } | 241 } |
244 | 242 |
245 return false; | 243 return false; |
246 } | 244 } |
247 | 245 |
248 // Sent to notify the browser process when a worker context invokes close(), so | 246 void WorkerProcessHost::OnProcessLaunched() { |
249 // no new connections are sent to shared workers. | |
250 void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { | |
251 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | |
252 if (i->worker_route_id() == worker_route_id) { | |
253 // Set the closed flag - this will stop any further messages from | |
254 // being sent to the worker (messages can still be sent from the worker, | |
255 // for exception reporting, etc). | |
256 i->set_closed(true); | |
257 break; | |
258 } | |
259 } | |
260 } | 247 } |
261 | 248 |
262 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { | 249 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { |
263 bool msg_is_ok = true; | 250 bool msg_is_ok = true; |
264 bool handled = | 251 bool handled = true; |
265 MessagePortDispatcher::GetInstance()->OnMessageReceived( | 252 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) |
266 message, this, next_route_id_callback_.get(), &msg_is_ok); | 253 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed, |
267 | 254 OnWorkerContextClosed) |
268 if (!handled) { | 255 IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase) |
269 handled = true; | 256 IPC_MESSAGE_UNHANDLED(handled = false) |
270 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) | |
271 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) | |
272 IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker) | |
273 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, | |
274 OnCancelCreateDedicatedWorker) | |
275 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed, | |
276 OnWorkerContextClosed); | |
277 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, | |
278 OnForwardToWorker) | |
279 IPC_MESSAGE_HANDLER_DELAY_REPLY(WorkerProcessHostMsg_AllowDatabase, | |
280 OnAllowDatabase) | |
281 IPC_MESSAGE_UNHANDLED(handled = false) | |
282 IPC_END_MESSAGE_MAP_EX() | 257 IPC_END_MESSAGE_MAP_EX() |
283 } | |
284 | 258 |
285 if (!msg_is_ok) { | 259 if (!msg_is_ok) { |
286 NOTREACHED(); | 260 NOTREACHED(); |
287 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); | 261 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); |
288 } | 262 } |
289 | 263 |
290 if (handled) | 264 if (handled) |
291 return; | 265 return; |
292 | 266 |
293 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 267 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
294 if (i->worker_route_id() == message.routing_id()) { | 268 if (i->worker_route_id() == message.routing_id()) { |
295 if (!i->shared()) { | 269 if (!i->shared()) { |
296 // Don't relay messages from shared workers (all communication is via | 270 // Don't relay messages from shared workers (all communication is via |
297 // the message port). | 271 // the message port). |
298 WorkerInstance::SenderInfo info = i->GetSender(); | 272 WorkerInstance::FilterInfo info = i->GetFilter(); |
299 CallbackWithReturnValue<int>::Type* next_route_id = | 273 RelayMessage(message, info.first, info.second); |
300 GetNextRouteIdCallback(info.first); | |
301 RelayMessage(message, info.first, info.second, next_route_id); | |
302 } | 274 } |
303 | 275 |
304 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { | 276 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { |
305 instances_.erase(i); | 277 instances_.erase(i); |
306 UpdateTitle(); | 278 UpdateTitle(); |
307 } | 279 } |
308 break; | 280 break; |
309 } | 281 } |
310 } | 282 } |
311 } | 283 } |
312 | 284 |
313 void WorkerProcessHost::OnProcessLaunched() { | 285 // Sent to notify the browser process when a worker context invokes close(), so |
286 // no new connections are sent to shared workers. | |
287 void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { | |
288 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | |
289 if (i->worker_route_id() == worker_route_id) { | |
290 // Set the closed flag - this will stop any further messages from | |
291 // being sent to the worker (messages can still be sent from the worker, | |
292 // for exception reporting, etc). | |
293 i->set_closed(true); | |
294 break; | |
295 } | |
296 } | |
314 } | 297 } |
315 | 298 |
316 CallbackWithReturnValue<int>::Type* WorkerProcessHost::GetNextRouteIdCallback( | 299 void WorkerProcessHost::OnAllowDatabase(int worker_route_id, |
317 IPC::Message::Sender* sender) { | 300 const GURL& url, |
318 // We don't keep callbacks for senders associated with workers, so figure out | 301 const string16& name, |
319 // what kind of sender this is, and cast it to the correct class to get the | 302 const string16& display_name, |
320 // callback. | 303 unsigned long estimated_size, |
321 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 304 bool* result) { |
322 !iter.Done(); ++iter) { | 305 ContentSetting content_setting = GetChromeURLRequestContext()-> |
323 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 306 host_content_settings_map()->GetContentSetting( |
324 if (static_cast<IPC::Message::Sender*>(worker) == sender) | 307 url, CONTENT_SETTINGS_TYPE_COOKIES, ""); |
325 return worker->next_route_id_callback_.get(); | 308 |
309 *result = content_setting != CONTENT_SETTING_BLOCK; | |
310 | |
311 // Find the worker instance and forward the message to all attached documents. | |
312 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | |
313 if (i->worker_route_id() != worker_route_id) | |
314 continue; | |
315 const WorkerDocumentSet::DocumentInfoSet& documents = | |
316 i->worker_document_set()->documents(); | |
317 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = | |
318 documents.begin(); doc != documents.end(); ++doc) { | |
319 CallRenderViewHostContentSettingsDelegate( | |
320 doc->render_process_id(), doc->render_view_id(), | |
321 &RenderViewHostDelegate::ContentSettings::OnWebDatabaseAccessed, | |
322 url, name, display_name, estimated_size, !*result); | |
323 } | |
324 break; | |
326 } | 325 } |
327 | |
328 // Must be a RenderMessageFilter. | |
329 return static_cast<RenderMessageFilter*>(sender)->next_route_id_callback(); | |
330 } | 326 } |
331 | 327 |
332 void WorkerProcessHost::RelayMessage( | 328 void WorkerProcessHost::RelayMessage( |
333 const IPC::Message& message, | 329 const IPC::Message& message, |
334 IPC::Message::Sender* sender, | 330 WorkerMessageFilter* filter, |
335 int route_id, | 331 int route_id) { |
336 CallbackWithReturnValue<int>::Type* next_route_id) { | |
337 | |
338 if (message.type() == WorkerMsg_PostMessage::ID) { | 332 if (message.type() == WorkerMsg_PostMessage::ID) { |
339 // We want to send the receiver a routing id for the new channel, so | 333 // We want to send the receiver a routing id for the new channel, so |
340 // crack the message first. | 334 // crack the message first. |
341 string16 msg; | 335 string16 msg; |
342 std::vector<int> sent_message_port_ids; | 336 std::vector<int> sent_message_port_ids; |
343 std::vector<int> new_routing_ids; | 337 std::vector<int> new_routing_ids; |
344 if (!WorkerMsg_PostMessage::Read( | 338 if (!WorkerMsg_PostMessage::Read( |
345 &message, &msg, &sent_message_port_ids, &new_routing_ids)) { | 339 &message, &msg, &sent_message_port_ids, &new_routing_ids)) { |
346 return; | 340 return; |
347 } | 341 } |
348 if (sent_message_port_ids.size() != new_routing_ids.size()) | 342 if (sent_message_port_ids.size() != new_routing_ids.size()) |
349 return; | 343 return; |
350 | 344 |
351 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { | 345 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { |
352 new_routing_ids[i] = next_route_id->Run(); | 346 new_routing_ids[i] = filter->GetNextRoutingID(); |
353 MessagePortDispatcher::GetInstance()->UpdateMessagePort( | 347 MessagePortService::GetInstance()->UpdateMessagePort( |
354 sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id); | 348 sent_message_port_ids[i], filter, new_routing_ids[i]); |
355 } | 349 } |
356 | 350 |
357 sender->Send(new WorkerMsg_PostMessage( | 351 filter->Send(new WorkerMsg_PostMessage( |
358 route_id, msg, sent_message_port_ids, new_routing_ids)); | 352 route_id, msg, sent_message_port_ids, new_routing_ids)); |
359 | 353 |
360 // Send any queued messages to the sent message ports. We can only do this | 354 // Send any queued messages to the sent message ports. We can only do this |
361 // after sending the above message, since it's the one that sets up the | 355 // after sending the above message, since it's the one that sets up the |
362 // message port route which the queued messages are sent to. | 356 // message port route which the queued messages are sent to. |
363 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { | 357 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { |
364 MessagePortDispatcher::GetInstance()-> | 358 MessagePortService::GetInstance()-> |
365 SendQueuedMessagesIfPossible(sent_message_port_ids[i]); | 359 SendQueuedMessagesIfPossible(sent_message_port_ids[i]); |
366 } | 360 } |
367 } else if (message.type() == WorkerMsg_Connect::ID) { | 361 } else if (message.type() == WorkerMsg_Connect::ID) { |
368 // Crack the SharedWorker Connect message to setup routing for the port. | 362 // Crack the SharedWorker Connect message to setup routing for the port. |
369 int sent_message_port_id; | 363 int sent_message_port_id; |
370 int new_routing_id; | 364 int new_routing_id; |
371 if (!WorkerMsg_Connect::Read( | 365 if (!WorkerMsg_Connect::Read( |
372 &message, &sent_message_port_id, &new_routing_id)) { | 366 &message, &sent_message_port_id, &new_routing_id)) { |
373 return; | 367 return; |
374 } | 368 } |
375 new_routing_id = next_route_id->Run(); | 369 new_routing_id = filter->GetNextRoutingID(); |
376 MessagePortDispatcher::GetInstance()->UpdateMessagePort( | 370 MessagePortService::GetInstance()->UpdateMessagePort( |
377 sent_message_port_id, sender, new_routing_id, next_route_id); | 371 sent_message_port_id, filter, new_routing_id); |
378 | 372 |
379 // Resend the message with the new routing id. | 373 // Resend the message with the new routing id. |
380 sender->Send(new WorkerMsg_Connect( | 374 filter->Send(new WorkerMsg_Connect( |
381 route_id, sent_message_port_id, new_routing_id)); | 375 route_id, sent_message_port_id, new_routing_id)); |
382 | 376 |
383 // Send any queued messages for the sent port. | 377 // Send any queued messages for the sent port. |
384 MessagePortDispatcher::GetInstance()->SendQueuedMessagesIfPossible( | 378 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( |
385 sent_message_port_id); | 379 sent_message_port_id); |
386 } else { | 380 } else { |
387 IPC::Message* new_message = new IPC::Message(message); | 381 IPC::Message* new_message = new IPC::Message(message); |
388 new_message->set_routing_id(route_id); | 382 new_message->set_routing_id(route_id); |
389 sender->Send(new_message); | 383 filter->Send(new_message); |
390 return; | 384 return; |
391 } | 385 } |
392 } | 386 } |
393 | 387 |
394 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { | 388 void WorkerProcessHost::FilterShutdown(WorkerMessageFilter* filter) { |
395 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | 389 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { |
396 bool shutdown = false; | 390 bool shutdown = false; |
397 i->RemoveSenders(sender); | 391 i->RemoveFilters(filter); |
398 if (i->shared()) { | 392 if (i->shared()) { |
399 i->worker_document_set()->RemoveAll(sender); | 393 i->worker_document_set()->RemoveAll(filter); |
400 if (i->worker_document_set()->IsEmpty()) { | 394 if (i->worker_document_set()->IsEmpty()) { |
401 shutdown = true; | 395 shutdown = true; |
402 } | 396 } |
403 } else if (i->NumSenders() == 0) { | 397 } else if (i->NumFilters() == 0) { |
404 shutdown = true; | 398 shutdown = true; |
405 } | 399 } |
406 if (shutdown) { | 400 if (shutdown) { |
407 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); | 401 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); |
408 i = instances_.erase(i); | 402 i = instances_.erase(i); |
409 } else { | 403 } else { |
410 ++i; | 404 ++i; |
411 } | 405 } |
412 } | 406 } |
413 } | 407 } |
414 | 408 |
415 bool WorkerProcessHost::CanShutdown() { | 409 bool WorkerProcessHost::CanShutdown() { |
416 return instances_.empty(); | 410 return instances_.empty(); |
417 } | 411 } |
418 | 412 |
419 void WorkerProcessHost::UpdateTitle() { | 413 void WorkerProcessHost::UpdateTitle() { |
420 std::set<std::string> titles; | 414 std::set<std::string> titles; |
421 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 415 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
422 std::string title = | 416 std::string title = |
423 net::RegistryControlledDomainService::GetDomainAndRegistry(i->url()); | 417 net::RegistryControlledDomainService::GetDomainAndRegistry(i->url()); |
424 // Use the host name if the domain is empty, i.e. localhost or IP address. | 418 // Use the host name if the domain is empty, i.e. localhost or IP address. |
425 if (title.empty()) | 419 if (title.empty()) |
426 title = i->url().host(); | 420 title = i->url().host(); |
427 | 421 |
428 // Check if it's an extension-created worker, in which case we want to use | 422 // Check if it's an extension-created worker, in which case we want to use |
429 // the name of the extension. | 423 // the name of the extension. |
430 std::string extension_name = static_cast<ChromeURLRequestContext*>( | 424 std::string extension_name = GetChromeURLRequestContext()-> |
431 Profile::GetDefaultRequestContext()->GetURLRequestContext())-> | |
432 extension_info_map()->GetNameForExtension(title); | 425 extension_info_map()->GetNameForExtension(title); |
433 if (!extension_name.empty()) { | 426 if (!extension_name.empty()) { |
434 titles.insert(extension_name); | 427 titles.insert(extension_name); |
435 continue; | 428 continue; |
436 } | 429 } |
437 | 430 |
438 // If the host name is empty, i.e. file url, use the path. | 431 // If the host name is empty, i.e. file url, use the path. |
439 if (title.empty()) | 432 if (title.empty()) |
440 title = i->url().path(); | 433 title = i->url().path(); |
441 titles.insert(title); | 434 titles.insert(title); |
442 } | 435 } |
443 | 436 |
444 std::string display_title; | 437 std::string display_title; |
445 for (std::set<std::string>::iterator i = titles.begin(); | 438 for (std::set<std::string>::iterator i = titles.begin(); |
446 i != titles.end(); ++i) { | 439 i != titles.end(); ++i) { |
447 if (!display_title.empty()) | 440 if (!display_title.empty()) |
448 display_title += ", "; | 441 display_title += ", "; |
449 display_title += *i; | 442 display_title += *i; |
450 } | 443 } |
451 | 444 |
452 set_name(ASCIIToWide(display_title)); | 445 set_name(ASCIIToWide(display_title)); |
453 } | 446 } |
454 | 447 |
455 void WorkerProcessHost::OnLookupSharedWorker( | 448 ChromeURLRequestContext* WorkerProcessHost::GetChromeURLRequestContext() { |
456 const ViewHostMsg_CreateWorker_Params& params, | 449 return static_cast<ChromeURLRequestContext*>( |
457 bool* exists, | 450 request_context_->GetURLRequestContext()); |
458 int* route_id, | |
459 bool* url_mismatch) { | |
460 *route_id = WorkerService::GetInstance()->next_worker_route_id(); | |
461 // TODO(atwilson): Add code to pass in the current worker's document set for | |
462 // these nested workers. Code below will not work for SharedWorkers as it | |
463 // only looks at a single parent. | |
464 DCHECK(instances_.front().worker_document_set()->documents().size() == 1); | |
465 WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = | |
466 instances_.front().worker_document_set()->documents().begin(); | |
467 *exists = WorkerService::GetInstance()->LookupSharedWorker( | |
468 params.url, params.name, instances_.front().off_the_record(), | |
469 params.document_id, first_parent->renderer_id(), | |
470 first_parent->render_view_route_id(), this, *route_id, url_mismatch); | |
471 } | 451 } |
472 | 452 |
473 void WorkerProcessHost::OnCreateWorker( | 453 void WorkerProcessHost::DocumentDetached(WorkerMessageFilter* filter, |
474 const ViewHostMsg_CreateWorker_Params& params, int* route_id) { | |
475 DCHECK(instances_.size() == 1); // Only called when one process per worker. | |
476 // TODO(atwilson): Add code to pass in the current worker's document set for | |
477 // these nested workers. Code below will not work for SharedWorkers as it | |
478 // only looks at a single parent. | |
479 DCHECK(instances_.front().worker_document_set()->documents().size() == 1); | |
480 WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = | |
481 instances_.front().worker_document_set()->documents().begin(); | |
482 *route_id = params.route_id == MSG_ROUTING_NONE ? | |
483 WorkerService::GetInstance()->next_worker_route_id() : params.route_id; | |
484 | |
485 if (params.is_shared) | |
486 WorkerService::GetInstance()->CreateSharedWorker( | |
487 params.url, instances_.front().off_the_record(), | |
488 params.name, params.document_id, first_parent->renderer_id(), | |
489 first_parent->render_view_route_id(), this, *route_id, | |
490 params.script_resource_appcache_id, request_context_); | |
491 else | |
492 WorkerService::GetInstance()->CreateDedicatedWorker( | |
493 params.url, instances_.front().off_the_record(), | |
494 params.document_id, first_parent->renderer_id(), | |
495 first_parent->render_view_route_id(), this, *route_id, | |
496 id(), params.parent_appcache_host_id, request_context_); | |
497 } | |
498 | |
499 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { | |
500 WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); | |
501 } | |
502 | |
503 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { | |
504 WorkerService::GetInstance()->ForwardMessage(message, this); | |
505 } | |
506 | |
507 void WorkerProcessHost::OnAllowDatabase(const GURL& url, | |
508 const string16& name, | |
509 const string16& display_name, | |
510 unsigned long estimated_size, | |
511 IPC::Message* reply_msg) { | |
512 ContentSetting content_setting = | |
513 request_context_->host_content_settings_map()->GetContentSetting( | |
514 url, CONTENT_SETTINGS_TYPE_COOKIES, ""); | |
515 | |
516 bool allowed = content_setting != CONTENT_SETTING_BLOCK; | |
517 | |
518 // Find the worker instance and forward the message to all attached documents. | |
519 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | |
520 if (i->worker_route_id() != reply_msg->routing_id()) | |
521 continue; | |
522 const WorkerDocumentSet::DocumentInfoSet& documents = | |
523 i->worker_document_set()->documents(); | |
524 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = | |
525 documents.begin(); doc != documents.end(); ++doc) { | |
526 CallRenderViewHostContentSettingsDelegate( | |
527 doc->renderer_id(), doc->render_view_route_id(), | |
528 &RenderViewHostDelegate::ContentSettings::OnWebDatabaseAccessed, | |
529 url, name, display_name, estimated_size, !allowed); | |
530 } | |
531 break; | |
532 } | |
533 WorkerProcessHostMsg_AllowDatabase::WriteReplyParams(reply_msg, allowed); | |
534 Send(reply_msg); | |
535 } | |
536 | |
537 void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent, | |
538 unsigned long long document_id) { | 454 unsigned long long document_id) { |
539 // Walk all instances and remove the document from their document set. | 455 // Walk all instances and remove the document from their document set. |
540 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | 456 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { |
541 if (!i->shared()) { | 457 if (!i->shared()) { |
542 ++i; | 458 ++i; |
543 } else { | 459 } else { |
544 i->worker_document_set()->Remove(parent, document_id); | 460 i->worker_document_set()->Remove(filter, document_id); |
545 if (i->worker_document_set()->IsEmpty()) { | 461 if (i->worker_document_set()->IsEmpty()) { |
546 // This worker has no more associated documents - shut it down. | 462 // This worker has no more associated documents - shut it down. |
547 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); | 463 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); |
548 i = instances_.erase(i); | 464 i = instances_.erase(i); |
549 } else { | 465 } else { |
550 ++i; | 466 ++i; |
551 } | 467 } |
552 } | 468 } |
553 } | 469 } |
554 } | 470 } |
555 | 471 |
556 WorkerProcessHost::WorkerInstance::WorkerInstance( | 472 WorkerProcessHost::WorkerInstance::WorkerInstance( |
557 const GURL& url, | 473 const GURL& url, |
558 bool shared, | 474 bool shared, |
559 bool off_the_record, | 475 bool off_the_record, |
560 const string16& name, | 476 const string16& name, |
561 int worker_route_id, | 477 int worker_route_id, |
562 int parent_process_id, | 478 int parent_process_id, |
563 int parent_appcache_host_id, | 479 int parent_appcache_host_id, |
564 int64 main_resource_appcache_id, | 480 int64 main_resource_appcache_id, |
565 ChromeURLRequestContext* request_context) | 481 URLRequestContextGetter* request_context) |
566 : url_(url), | 482 : url_(url), |
567 shared_(shared), | 483 shared_(shared), |
568 off_the_record_(off_the_record), | 484 off_the_record_(off_the_record), |
569 closed_(false), | 485 closed_(false), |
570 name_(name), | 486 name_(name), |
571 worker_route_id_(worker_route_id), | 487 worker_route_id_(worker_route_id), |
572 parent_process_id_(parent_process_id), | 488 parent_process_id_(parent_process_id), |
573 parent_appcache_host_id_(parent_appcache_host_id), | 489 parent_appcache_host_id_(parent_appcache_host_id), |
574 main_resource_appcache_id_(main_resource_appcache_id), | 490 main_resource_appcache_id_(main_resource_appcache_id), |
575 request_context_(request_context), | 491 request_context_(request_context), |
576 worker_document_set_(new WorkerDocumentSet()) { | 492 worker_document_set_(new WorkerDocumentSet()) { |
577 DCHECK(!request_context || | |
578 (off_the_record == request_context->is_off_the_record())); | |
579 } | 493 } |
580 | 494 |
581 WorkerProcessHost::WorkerInstance::~WorkerInstance() { | 495 WorkerProcessHost::WorkerInstance::~WorkerInstance() { |
582 } | 496 } |
583 | 497 |
584 // Compares an instance based on the algorithm in the WebWorkers spec - an | 498 // Compares an instance based on the algorithm in the WebWorkers spec - an |
585 // instance matches if the origins of the URLs match, and: | 499 // instance matches if the origins of the URLs match, and: |
586 // a) the names are non-empty and equal | 500 // a) the names are non-empty and equal |
587 // -or- | 501 // -or- |
588 // b) the names are both empty, and the urls are equal | 502 // b) the names are both empty, and the urls are equal |
(...skipping 10 matching lines...) Expand all Loading... | |
599 | 513 |
600 if (url_.GetOrigin() != match_url.GetOrigin()) | 514 if (url_.GetOrigin() != match_url.GetOrigin()) |
601 return false; | 515 return false; |
602 | 516 |
603 if (name_.empty() && match_name.empty()) | 517 if (name_.empty() && match_name.empty()) |
604 return url_ == match_url; | 518 return url_ == match_url; |
605 | 519 |
606 return name_ == match_name; | 520 return name_ == match_name; |
607 } | 521 } |
608 | 522 |
609 void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender, | 523 void WorkerProcessHost::WorkerInstance::AddFilter(WorkerMessageFilter* filter, |
610 int sender_route_id) { | 524 int route_id) { |
611 if (!HasSender(sender, sender_route_id)) { | 525 if (!HasFilter(filter, route_id)) { |
612 SenderInfo info(sender, sender_route_id); | 526 FilterInfo info(filter, route_id); |
613 senders_.push_back(info); | 527 filters_.push_back(info); |
614 } | 528 } |
615 // Only shared workers can have more than one associated sender. | 529 // Only shared workers can have more than one associated filter. |
616 DCHECK(shared_ || senders_.size() == 1); | 530 DCHECK(shared_ || filters_.size() == 1); |
617 } | 531 } |
618 | 532 |
619 void WorkerProcessHost::WorkerInstance::RemoveSender( | 533 void WorkerProcessHost::WorkerInstance::RemoveFilter( |
620 IPC::Message::Sender* sender, int sender_route_id) { | 534 WorkerMessageFilter* filter, int route_id) { |
621 for (SenderList::iterator i = senders_.begin(); i != senders_.end();) { | 535 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { |
622 if (i->first == sender && i->second == sender_route_id) | 536 if (i->first == filter && i->second == route_id) |
623 i = senders_.erase(i); | 537 i = filters_.erase(i); |
624 else | 538 else |
625 ++i; | 539 ++i; |
626 } | 540 } |
627 // Should not be duplicate copies in the sender set. | 541 // Should not be duplicate copies in the filter set. |
628 DCHECK(!HasSender(sender, sender_route_id)); | 542 DCHECK(!HasFilter(filter, route_id)); |
629 } | 543 } |
630 | 544 |
631 void WorkerProcessHost::WorkerInstance::RemoveSenders( | 545 void WorkerProcessHost::WorkerInstance::RemoveFilters( |
632 IPC::Message::Sender* sender) { | 546 WorkerMessageFilter* filter) { |
633 for (SenderList::iterator i = senders_.begin(); i != senders_.end();) { | 547 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { |
634 if (i->first == sender) | 548 if (i->first == filter) |
635 i = senders_.erase(i); | 549 i = filters_.erase(i); |
636 else | 550 else |
637 ++i; | 551 ++i; |
638 } | 552 } |
639 } | 553 } |
640 | 554 |
641 bool WorkerProcessHost::WorkerInstance::HasSender( | 555 bool WorkerProcessHost::WorkerInstance::HasFilter( |
642 IPC::Message::Sender* sender, int sender_route_id) const { | 556 WorkerMessageFilter* filter, int route_id) const { |
643 for (SenderList::const_iterator i = senders_.begin(); i != senders_.end(); | 557 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); |
644 ++i) { | 558 ++i) { |
645 if (i->first == sender && i->second == sender_route_id) | 559 if (i->first == filter && i->second == route_id) |
646 return true; | 560 return true; |
647 } | 561 } |
648 return false; | 562 return false; |
649 } | 563 } |
650 | 564 |
651 bool WorkerProcessHost::WorkerInstance::RendererIsParent( | 565 bool WorkerProcessHost::WorkerInstance::RendererIsParent( |
652 int renderer_id, int render_view_route_id) const { | 566 int render_process_id, int render_view_id) const { |
653 const WorkerDocumentSet::DocumentInfoSet& parents = | 567 const WorkerDocumentSet::DocumentInfoSet& parents = |
654 worker_document_set()->documents(); | 568 worker_document_set()->documents(); |
655 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | 569 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
656 parents.begin(); | 570 parents.begin(); |
657 parent_iter != parents.end(); ++parent_iter) { | 571 parent_iter != parents.end(); ++parent_iter) { |
658 if (parent_iter->renderer_id() == renderer_id && | 572 if (parent_iter->render_process_id() == render_process_id && |
659 parent_iter->render_view_route_id() == render_view_route_id) { | 573 parent_iter->render_view_id() == render_view_id) { |
660 return true; | 574 return true; |
661 } | 575 } |
662 } | 576 } |
663 return false; | 577 return false; |
664 } | 578 } |
665 | 579 |
666 WorkerProcessHost::WorkerInstance::SenderInfo | 580 WorkerProcessHost::WorkerInstance::FilterInfo |
667 WorkerProcessHost::WorkerInstance::GetSender() const { | 581 WorkerProcessHost::WorkerInstance::GetFilter() const { |
668 DCHECK(NumSenders() == 1); | 582 DCHECK(NumFilters() == 1); |
669 return *senders_.begin(); | 583 return *filters_.begin(); |
670 } | 584 } |
OLD | NEW |