OLD | NEW |
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/renderer/extensions/extension_dispatcher.h" | 5 #include "chrome/renderer/extensions/extension_dispatcher.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "chrome/common/child_process_logging.h" | 8 #include "chrome/common/child_process_logging.h" |
9 #include "chrome/common/chrome_switches.h" | 9 #include "chrome/common/chrome_switches.h" |
10 #include "chrome/common/extensions/extension.h" | 10 #include "chrome/common/extensions/extension.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "chrome/renderer/extensions/file_browser_private_bindings.h" | 22 #include "chrome/renderer/extensions/file_browser_private_bindings.h" |
23 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | 23 #include "chrome/renderer/extensions/renderer_extension_bindings.h" |
24 #include "chrome/renderer/extensions/user_script_slave.h" | 24 #include "chrome/renderer/extensions/user_script_slave.h" |
25 #include "content/public/renderer/render_thread.h" | 25 #include "content/public/renderer/render_thread.h" |
26 #include "grit/renderer_resources.h" | 26 #include "grit/renderer_resources.h" |
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" |
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h" | 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h" |
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" | 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" |
| 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 33 #include "ui/base/resource/resource_bundle.h" |
32 #include "v8/include/v8.h" | 34 #include "v8/include/v8.h" |
33 | 35 |
34 namespace { | 36 namespace { |
35 static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; | 37 static const double kInitialExtensionIdleHandlerDelayS = 5.0 /* seconds */; |
36 static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; | 38 static const int64 kMaxExtensionIdleHandlerDelayS = 5*60 /* seconds */; |
37 } | 39 } |
38 | 40 |
39 using WebKit::WebDataSource; | 41 using WebKit::WebDataSource; |
40 using WebKit::WebFrame; | 42 using WebKit::WebFrame; |
41 using WebKit::WebSecurityPolicy; | 43 using WebKit::WebSecurityPolicy; |
42 using WebKit::WebString; | 44 using WebKit::WebString; |
| 45 using WebKit::WebVector; |
| 46 using WebKit::WebView; |
43 using content::RenderThread; | 47 using content::RenderThread; |
44 | 48 |
45 ExtensionDispatcher::ExtensionDispatcher() | 49 ExtensionDispatcher::ExtensionDispatcher() |
46 : is_webkit_initialized_(false), | 50 : is_webkit_initialized_(false), |
47 webrequest_adblock_(false), | 51 webrequest_adblock_(false), |
48 webrequest_adblock_plus_(false), | 52 webrequest_adblock_plus_(false), |
49 webrequest_other_(false) { | 53 webrequest_other_(false), |
| 54 is_batch_load_in_progress_(false) { |
50 const CommandLine& command_line = *(CommandLine::ForCurrentProcess()); | 55 const CommandLine& command_line = *(CommandLine::ForCurrentProcess()); |
51 is_extension_process_ = | 56 is_extension_process_ = |
52 command_line.HasSwitch(switches::kExtensionProcess) || | 57 command_line.HasSwitch(switches::kExtensionProcess) || |
53 command_line.HasSwitch(switches::kSingleProcess); | 58 command_line.HasSwitch(switches::kSingleProcess); |
54 | 59 |
55 if (is_extension_process_) { | 60 if (is_extension_process_) { |
56 RenderThread::Get()->SetIdleNotificationDelayInS( | 61 RenderThread::Get()->SetIdleNotificationDelayInS( |
57 kInitialExtensionIdleHandlerDelayS); | 62 kInitialExtensionIdleHandlerDelayS); |
58 } | 63 } |
59 | 64 |
60 user_script_slave_.reset(new UserScriptSlave(&extensions_)); | 65 user_script_slave_.reset(new UserScriptSlave(&extensions_)); |
61 } | 66 } |
62 | 67 |
63 ExtensionDispatcher::~ExtensionDispatcher() { | 68 ExtensionDispatcher::~ExtensionDispatcher() { |
64 } | 69 } |
65 | 70 |
66 bool ExtensionDispatcher::OnControlMessageReceived( | 71 bool ExtensionDispatcher::OnControlMessageReceived( |
67 const IPC::Message& message) { | 72 const IPC::Message& message) { |
68 bool handled = true; | 73 bool handled = true; |
69 IPC_BEGIN_MESSAGE_MAP(ExtensionDispatcher, message) | 74 IPC_BEGIN_MESSAGE_MAP(ExtensionDispatcher, message) |
70 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnMessageInvoke) | 75 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnMessageInvoke) |
71 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage) | 76 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage) |
72 IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames, OnSetFunctionNames) | 77 IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames, OnSetFunctionNames) |
73 IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnLoaded) | 78 IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnLoaded) |
| 79 IPC_MESSAGE_HANDLER(ExtensionMsg_StartBatchLoad, OnStartBatchLoad) |
| 80 IPC_MESSAGE_HANDLER(ExtensionMsg_EndBatchLoad, OnEndBatchLoad) |
74 IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnUnloaded) | 81 IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnUnloaded) |
75 IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist, | 82 IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist, |
76 OnSetScriptingWhitelist) | 83 OnSetScriptingWhitelist) |
77 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateExtension, OnActivateExtension) | 84 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateExtension, OnActivateExtension) |
78 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateApplication, OnActivateApplication) | 85 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateApplication, OnActivateApplication) |
79 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions, OnUpdatePermissions) | 86 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions, OnUpdatePermissions) |
80 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) | 87 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) |
81 IPC_MESSAGE_HANDLER(ExtensionMsg_UsingWebRequestAPI, OnUsingWebRequestAPI) | 88 IPC_MESSAGE_HANDLER(ExtensionMsg_UsingWebRequestAPI, OnUsingWebRequestAPI) |
82 IPC_MESSAGE_UNHANDLED(handled = false) | 89 IPC_MESSAGE_UNHANDLED(handled = false) |
83 IPC_END_MESSAGE_MAP() | 90 IPC_END_MESSAGE_MAP() |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 scoped_refptr<const Extension> extension(params.ConvertToExtension()); | 189 scoped_refptr<const Extension> extension(params.ConvertToExtension()); |
183 if (!extension) { | 190 if (!extension) { |
184 // This can happen if extension parsing fails for any reason. One reason | 191 // This can happen if extension parsing fails for any reason. One reason |
185 // this can legitimately happen is if the | 192 // this can legitimately happen is if the |
186 // --enable-experimental-extension-apis changes at runtime, which happens | 193 // --enable-experimental-extension-apis changes at runtime, which happens |
187 // during browser tests. Existing renderers won't know about the change. | 194 // during browser tests. Existing renderers won't know about the change. |
188 return; | 195 return; |
189 } | 196 } |
190 | 197 |
191 extensions_.Insert(extension); | 198 extensions_.Insert(extension); |
| 199 |
| 200 if (extension->is_platform_app()) { |
| 201 extensions_needing_stylesheet_.Insert(extension); |
| 202 if (is_batch_load_in_progress_) { |
| 203 // Do nothing; we'll expect the ExtensionMsg_EndBatchLoad message as our |
| 204 // signal to do the cleanup work of creating a single stylesheet matching |
| 205 // all the platform-app URL patterns observed in the batch. |
| 206 } else { |
| 207 DCHECK(extensions_needing_stylesheet_.size() == 1u); |
| 208 // This ExtensionMsg_Loaded was not sent as part of a batch. But to |
| 209 // simplify, let's treat it as a synthetic batch of one, then run the |
| 210 // batch-ending code. |
| 211 is_batch_load_in_progress_ = true; |
| 212 OnEndBatchLoad(); |
| 213 } |
| 214 } |
| 215 } |
| 216 |
| 217 void ExtensionDispatcher::OnStartBatchLoad() { |
| 218 DCHECK(extensions_needing_stylesheet_.size() == 0u); |
| 219 DCHECK(!is_batch_load_in_progress_); |
| 220 is_batch_load_in_progress_ = true; |
| 221 } |
| 222 |
| 223 void ExtensionDispatcher::OnEndBatchLoad() { |
| 224 DCHECK(is_batch_load_in_progress_); |
| 225 |
| 226 // We have collected a set of platform-app extensions, so let's tell WebKit |
| 227 // about them so that it can provide a default stylesheet for them. |
| 228 // |
| 229 // TODO: consider enhancing WebView to allow removing single stylesheets, or |
| 230 // else to edit the pattern set associated with one. |
| 231 std::vector<WebString> temp_patterns; |
| 232 for (ExtensionSet::const_iterator i = extensions_needing_stylesheet_.begin(); |
| 233 i != extensions_needing_stylesheet_.end(); ++i) { |
| 234 temp_patterns.push_back( |
| 235 WebString::fromUTF8(i->second->url().spec() + "*")); |
| 236 } |
| 237 WebVector<WebString> patterns; |
| 238 patterns.assign(temp_patterns); |
| 239 if (patterns.size() > 0) { |
| 240 WebView::addUserStyleSheet( |
| 241 WebString::fromUTF8(ResourceBundle::GetSharedInstance(). |
| 242 GetRawDataResource(IDR_PLATFORM_APP_CSS)), |
| 243 patterns, |
| 244 WebView::UserContentInjectInAllFrames, |
| 245 WebView::UserStyleInjectInExistingDocuments); |
| 246 } |
| 247 |
| 248 // We have fully processed the batch. Clean things up for the next one. |
| 249 extensions_needing_stylesheet_.Clear(); |
| 250 is_batch_load_in_progress_ = false; |
192 } | 251 } |
193 | 252 |
194 void ExtensionDispatcher::OnUnloaded(const std::string& id) { | 253 void ExtensionDispatcher::OnUnloaded(const std::string& id) { |
195 extensions_.Remove(id); | 254 extensions_.Remove(id); |
196 // If the extension is later reloaded with a different set of permissions, | 255 // If the extension is later reloaded with a different set of permissions, |
197 // we'd like it to get a new isolated world ID, so that it can pick up the | 256 // we'd like it to get a new isolated world ID, so that it can pick up the |
198 // changed origin whitelist. | 257 // changed origin whitelist. |
199 user_script_slave_->RemoveIsolatedWorld(id); | 258 user_script_slave_->RemoveIsolatedWorld(id); |
| 259 |
| 260 // We don't do anything with existing platform-app stylesheets. They will |
| 261 // stay resident, but the URL pattern corresponding to the unloaded |
| 262 // extension's URL just won't match anything anymore. |
200 } | 263 } |
201 | 264 |
202 void ExtensionDispatcher::OnSetScriptingWhitelist( | 265 void ExtensionDispatcher::OnSetScriptingWhitelist( |
203 const Extension::ScriptingWhitelist& extension_ids) { | 266 const Extension::ScriptingWhitelist& extension_ids) { |
204 Extension::SetScriptingWhitelist(extension_ids); | 267 Extension::SetScriptingWhitelist(extension_ids); |
205 } | 268 } |
206 | 269 |
207 bool ExtensionDispatcher::IsApplicationActive( | 270 bool ExtensionDispatcher::IsApplicationActive( |
208 const std::string& extension_id) const { | 271 const std::string& extension_id) const { |
209 return active_application_ids_.find(extension_id) != | 272 return active_application_ids_.find(extension_id) != |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 | 470 |
408 RenderThread::Get()->RegisterExtension(extension); | 471 RenderThread::Get()->RegisterExtension(extension); |
409 } | 472 } |
410 | 473 |
411 void ExtensionDispatcher::OnUsingWebRequestAPI( | 474 void ExtensionDispatcher::OnUsingWebRequestAPI( |
412 bool adblock, bool adblock_plus, bool other) { | 475 bool adblock, bool adblock_plus, bool other) { |
413 webrequest_adblock_ = adblock; | 476 webrequest_adblock_ = adblock; |
414 webrequest_adblock_plus_ = adblock_plus; | 477 webrequest_adblock_plus_ = adblock_plus; |
415 webrequest_other_ = other; | 478 webrequest_other_ = other; |
416 } | 479 } |
OLD | NEW |