OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "extensions/browser/api/guest_view/web_view/web_view_internal_api.h" | 5 #include "extensions/browser/api/guest_view/web_view/web_view_internal_api.h" |
6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" |
7 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
8 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
9 #include "content/public/browser/render_process_host.h" | 10 #include "content/public/browser/render_process_host.h" |
10 #include "content/public/browser/render_view_host.h" | 11 #include "content/public/browser/render_view_host.h" |
11 #include "content/public/browser/storage_partition.h" | 12 #include "content/public/browser/storage_partition.h" |
12 #include "content/public/browser/web_contents.h" | 13 #include "content/public/browser/web_contents.h" |
13 #include "content/public/common/stop_find_action.h" | 14 #include "content/public/common/stop_find_action.h" |
| 15 #include "extensions/browser/guest_view/web_view/web_view_content_script_manager
.h" |
14 #include "extensions/common/api/web_view_internal.h" | 16 #include "extensions/common/api/web_view_internal.h" |
| 17 #include "extensions/common/error_utils.h" |
| 18 #include "extensions/common/manifest_constants.h" |
| 19 #include "extensions/common/user_script.h" |
15 #include "third_party/WebKit/public/web/WebFindOptions.h" | 20 #include "third_party/WebKit/public/web/WebFindOptions.h" |
16 | 21 |
17 using content::WebContents; | 22 using content::WebContents; |
18 using extensions::core_api::web_view_internal::SetPermission::Params; | 23 using extensions::core_api::web_view_internal::SetPermission::Params; |
19 using extensions::core_api::extension_types::InjectDetails; | 24 using extensions::core_api::extension_types::InjectDetails; |
| 25 using extensions::core_api::web_view_internal::ContentScriptDetails; |
| 26 using extensions::ExtensionResource; |
| 27 using extensions::UserScript; |
20 namespace webview = extensions::core_api::web_view_internal; | 28 namespace webview = extensions::core_api::web_view_internal; |
| 29 // error messages for content scripts: |
| 30 namespace errors = extensions::manifest_errors; |
21 | 31 |
22 namespace { | 32 namespace { |
23 | 33 |
24 const char kAppCacheKey[] = "appcache"; | 34 const char kAppCacheKey[] = "appcache"; |
25 const char kCookiesKey[] = "cookies"; | 35 const char kCookiesKey[] = "cookies"; |
26 const char kFileSystemsKey[] = "fileSystems"; | 36 const char kFileSystemsKey[] = "fileSystems"; |
27 const char kIndexedDBKey[] = "indexedDB"; | 37 const char kIndexedDBKey[] = "indexedDB"; |
28 const char kLocalStorageKey[] = "localStorage"; | 38 const char kLocalStorageKey[] = "localStorage"; |
29 const char kWebSQLKey[] = "webSQL"; | 39 const char kWebSQLKey[] = "webSQL"; |
30 const char kSinceKey[] = "since"; | 40 const char kSinceKey[] = "since"; |
31 | 41 |
32 int MaskForKey(const char* key) { | 42 int MaskForKey(const char* key) { |
33 if (strcmp(key, kAppCacheKey) == 0) | 43 if (strcmp(key, kAppCacheKey) == 0) |
34 return content::StoragePartition::REMOVE_DATA_MASK_APPCACHE; | 44 return content::StoragePartition::REMOVE_DATA_MASK_APPCACHE; |
35 if (strcmp(key, kCookiesKey) == 0) | 45 if (strcmp(key, kCookiesKey) == 0) |
36 return content::StoragePartition::REMOVE_DATA_MASK_COOKIES; | 46 return content::StoragePartition::REMOVE_DATA_MASK_COOKIES; |
37 if (strcmp(key, kFileSystemsKey) == 0) | 47 if (strcmp(key, kFileSystemsKey) == 0) |
38 return content::StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS; | 48 return content::StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS; |
39 if (strcmp(key, kIndexedDBKey) == 0) | 49 if (strcmp(key, kIndexedDBKey) == 0) |
40 return content::StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; | 50 return content::StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; |
41 if (strcmp(key, kLocalStorageKey) == 0) | 51 if (strcmp(key, kLocalStorageKey) == 0) |
42 return content::StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE; | 52 return content::StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE; |
43 if (strcmp(key, kWebSQLKey) == 0) | 53 if (strcmp(key, kWebSQLKey) == 0) |
44 return content::StoragePartition::REMOVE_DATA_MASK_WEBSQL; | 54 return content::StoragePartition::REMOVE_DATA_MASK_WEBSQL; |
45 return 0; | 55 return 0; |
46 } | 56 } |
47 | 57 |
| 58 HostID GenerateHostID(const extensions::Extension* extension, |
| 59 const content::WebContents* web_contents, |
| 60 const content::RenderViewHost* rvh) { |
| 61 if (extension) |
| 62 return HostID(HostID::EXTENSIONS, extension->id()); |
| 63 |
| 64 if (web_contents && web_contents->GetWebUI()) { |
| 65 const GURL& url = rvh->GetSiteInstance()->GetSiteURL(); |
| 66 return HostID(HostID::WEBUI, url.spec()); |
| 67 } |
| 68 NOTREACHED(); |
| 69 return HostID(); |
| 70 } |
| 71 |
| 72 bool Parse(const ContentScriptDetails& script_value, |
| 73 const extensions::Extension* extension, |
| 74 const GURL& owner_base_url, |
| 75 UserScript* script, |
| 76 std::string* error) { |
| 77 // matches (required): |
| 78 const std::vector<std::string>& matches = script_value.matches; |
| 79 if (matches.size() == 0) { |
| 80 return false; |
| 81 } |
| 82 |
| 83 for (const std::string& match : matches) { |
| 84 URLPattern pattern(UserScript::ValidUserScriptSchemes( |
| 85 true /* canExecuteScriptEverywhere */)); |
| 86 if (pattern.Parse(match) != URLPattern::PARSE_SUCCESS) { |
| 87 *error = errors::kInvalidMatches; |
| 88 return false; |
| 89 } |
| 90 script->add_url_pattern(pattern); |
| 91 } |
| 92 |
| 93 // exclude_matches: |
| 94 if (script_value.exclude_matches) { |
| 95 const std::vector<std::string>& exclude_matches = |
| 96 *(script_value.exclude_matches.get()); |
| 97 for (const std::string& exclude_match : exclude_matches) { |
| 98 URLPattern pattern(UserScript::ValidUserScriptSchemes( |
| 99 true /* canExecuteScriptEverywhere */)); |
| 100 |
| 101 if (pattern.Parse(exclude_match) != URLPattern::PARSE_SUCCESS) { |
| 102 *error = errors::kInvalidExcludeMatches; |
| 103 return false; |
| 104 } |
| 105 script->add_exclude_url_pattern(pattern); |
| 106 } |
| 107 } |
| 108 // run_at: |
| 109 if (script_value.run_at) { |
| 110 UserScript::RunLocation run_at = UserScript::UNDEFINED; |
| 111 switch (script_value.run_at) { |
| 112 case ContentScriptDetails::RUN_AT_NONE: |
| 113 case ContentScriptDetails::RUN_AT_DOCUMENT_IDLE: |
| 114 run_at = UserScript::DOCUMENT_IDLE; |
| 115 break; |
| 116 case ContentScriptDetails::RUN_AT_DOCUMENT_START: |
| 117 run_at = UserScript::DOCUMENT_START; |
| 118 break; |
| 119 case ContentScriptDetails::RUN_AT_DOCUMENT_END: |
| 120 run_at = UserScript::DOCUMENT_END; |
| 121 break; |
| 122 } |
| 123 script->set_run_location(run_at); |
| 124 } |
| 125 |
| 126 // match_about_blank: |
| 127 if (script_value.match_about_blank) |
| 128 script->set_match_about_blank(*script_value.match_about_blank); |
| 129 |
| 130 // css: |
| 131 if (script_value.css) { |
| 132 const std::vector<std::string>& css_files = *(script_value.css.get()); |
| 133 for (const std::string& relative : css_files) { |
| 134 GURL url = owner_base_url.Resolve(relative); |
| 135 if (extension) { |
| 136 ExtensionResource resource = extension->GetResource(relative); |
| 137 script->css_scripts().push_back(UserScript::File( |
| 138 resource.extension_root(), resource.relative_path(), url)); |
| 139 } else { |
| 140 script->css_scripts().push_back(extensions::UserScript::File( |
| 141 base::FilePath(), base::FilePath(), url)); |
| 142 } |
| 143 } |
| 144 } |
| 145 |
| 146 // js: |
| 147 if (script_value.js) { |
| 148 const std::vector<std::string>& js_files = *(script_value.js.get()); |
| 149 for (const std::string& relative : js_files) { |
| 150 GURL url = owner_base_url.Resolve(relative); |
| 151 if (extension) { |
| 152 ExtensionResource resource = extension->GetResource(relative); |
| 153 script->js_scripts().push_back(UserScript::File( |
| 154 resource.extension_root(), resource.relative_path(), url)); |
| 155 } else { |
| 156 script->js_scripts().push_back(extensions::UserScript::File( |
| 157 base::FilePath(), base::FilePath(), url)); |
| 158 } |
| 159 } |
| 160 } |
| 161 |
| 162 // all_frames: |
| 163 if (script_value.all_frames) { |
| 164 script->set_match_all_frames(*(script_value.all_frames)); |
| 165 } |
| 166 |
| 167 // include_globs: |
| 168 if (script_value.include_globs) { |
| 169 const std::vector<std::string>& include_globs = |
| 170 *(script_value.include_globs.get()); |
| 171 for (const std::string& glob : include_globs) |
| 172 script->add_glob(glob); |
| 173 } |
| 174 |
| 175 // exclude_globs: |
| 176 if (script_value.exclude_globs) { |
| 177 const std::vector<std::string>& exclude_globs = |
| 178 *(script_value.exclude_globs.get()); |
| 179 for (const std::string& glob : exclude_globs) |
| 180 script->add_exclude_glob(glob); |
| 181 } |
| 182 |
| 183 return true; |
| 184 } |
| 185 |
| 186 bool Parse(std::vector<linked_ptr<ContentScriptDetails>> content_script_list, |
| 187 const extensions::Extension* extension, |
| 188 const GURL& owner_base_url, |
| 189 std::map<std::string, UserScript>* result, |
| 190 std::string* error) { |
| 191 if (content_script_list.size() == 0) |
| 192 return false; |
| 193 for (size_t i = 0; i < content_script_list.size(); ++i) { |
| 194 const ContentScriptDetails& script_value = *content_script_list[i]; |
| 195 const std::string& name = script_value.name; |
| 196 UserScript script; |
| 197 if (!Parse(script_value, extension, owner_base_url, &script, error)) |
| 198 return false; |
| 199 else |
| 200 result->insert(std::pair<std::string, UserScript>(name, script)); |
| 201 } |
| 202 return true; |
| 203 } |
| 204 |
| 205 // Initialize the user script. |
| 206 void InitUserScript(UserScript* script, std::string name, HostID host_id) { |
| 207 if (!script) |
| 208 return; |
| 209 script->set_id(UserScript::GenerateUserScriptID()); |
| 210 script->set_name(name); |
| 211 script->set_host_id(host_id); |
| 212 script->set_consumer_instance_type(UserScript::WEBVIEW); |
| 213 } |
| 214 |
48 } // namespace | 215 } // namespace |
49 | 216 |
50 namespace extensions { | 217 namespace extensions { |
51 | 218 |
52 bool WebViewInternalExtensionFunction::RunAsync() { | 219 bool WebViewInternalExtensionFunction::RunAsync() { |
53 int instance_id = 0; | 220 int instance_id = 0; |
54 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id)); | 221 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id)); |
55 WebViewGuest* guest = WebViewGuest::From( | 222 WebViewGuest* guest = WebViewGuest::From( |
56 render_view_host()->GetProcess()->GetID(), instance_id); | 223 render_view_host()->GetProcess()->GetID(), instance_id); |
57 if (!guest) | 224 if (!guest) |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 error, on_url, result); | 325 error, on_url, result); |
159 } | 326 } |
160 | 327 |
161 WebViewInternalInsertCSSFunction::WebViewInternalInsertCSSFunction() { | 328 WebViewInternalInsertCSSFunction::WebViewInternalInsertCSSFunction() { |
162 } | 329 } |
163 | 330 |
164 bool WebViewInternalInsertCSSFunction::ShouldInsertCSS() const { | 331 bool WebViewInternalInsertCSSFunction::ShouldInsertCSS() const { |
165 return true; | 332 return true; |
166 } | 333 } |
167 | 334 |
| 335 WebViewInternalAddContentScriptsFunction:: |
| 336 WebViewInternalAddContentScriptsFunction() { |
| 337 if (extension()) { |
| 338 set_host_id(HostID(HostID::EXTENSIONS, extension()->id())); |
| 339 return; |
| 340 } |
| 341 |
| 342 WebContents* web_contents = GetSenderWebContents(); |
| 343 if (web_contents && web_contents->GetWebUI()) { |
| 344 const GURL& url = render_view_host()->GetSiteInstance()->GetSiteURL(); |
| 345 set_host_id(HostID(HostID::WEBUI, url.spec())); |
| 346 } |
| 347 } |
| 348 |
| 349 WebViewInternalAddContentScriptsFunction:: |
| 350 ~WebViewInternalAddContentScriptsFunction() { |
| 351 } |
| 352 |
| 353 bool WebViewInternalAddContentScriptsFunction::RunAsync() { |
| 354 scoped_ptr<webview::AddContentScripts::Params> params( |
| 355 webview::AddContentScripts::Params::Create(*args_)); |
| 356 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 357 |
| 358 int guest_view_instance_id = 0; |
| 359 if (!args_->GetInteger(0, &guest_view_instance_id) || |
| 360 !guest_view_instance_id) { |
| 361 SendResponse(false); |
| 362 return false; |
| 363 } |
| 364 |
| 365 if (!render_view_host() || !render_view_host()->GetProcess()) { |
| 366 SendResponse(false); |
| 367 return false; |
| 368 } |
| 369 |
| 370 GURL owner_base_url( |
| 371 render_view_host()->GetSiteInstance()->GetSiteURL().GetWithEmptyPath()); |
| 372 std::map<std::string, UserScript> result; |
| 373 if (!Parse(params->content_script_list, extension(), owner_base_url, &result, |
| 374 &error_)) { |
| 375 SendResponse(false); |
| 376 return false; |
| 377 } |
| 378 |
| 379 WebViewContentScriptManager* manager = |
| 380 WebViewContentScriptManager::Get(browser_context()); |
| 381 if (!manager) { |
| 382 SendResponse(false); |
| 383 return false; |
| 384 } |
| 385 |
| 386 int embedder_process_id = render_view_host()->GetProcess()->GetID(); |
| 387 HostID host_id = |
| 388 GenerateHostID(extension(), GetSenderWebContents(), render_view_host()); |
| 389 for (auto& iter : result) |
| 390 InitUserScript(&iter.second, iter.first, host_id); |
| 391 manager->AddContentScripts(embedder_process_id, guest_view_instance_id, |
| 392 host_id, result); |
| 393 SendResponse(true); |
| 394 return true; |
| 395 } |
| 396 |
| 397 WebViewInternalRemoveContentScriptsFunction:: |
| 398 WebViewInternalRemoveContentScriptsFunction() { |
| 399 } |
| 400 |
| 401 WebViewInternalRemoveContentScriptsFunction:: |
| 402 ~WebViewInternalRemoveContentScriptsFunction() { |
| 403 } |
| 404 |
| 405 bool WebViewInternalRemoveContentScriptsFunction::RunAsync() { |
| 406 scoped_ptr<webview::RemoveContentScripts::Params> params( |
| 407 webview::RemoveContentScripts::Params::Create(*args_)); |
| 408 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 409 |
| 410 int guest_view_instance_id = 0; |
| 411 if (!args_->GetInteger(0, &guest_view_instance_id) || |
| 412 !guest_view_instance_id) { |
| 413 SendResponse(false); |
| 414 return false; |
| 415 } |
| 416 |
| 417 WebViewContentScriptManager* manager = |
| 418 WebViewContentScriptManager::Get(browser_context()); |
| 419 if (!manager) { |
| 420 SendResponse(false); |
| 421 return false; |
| 422 } |
| 423 |
| 424 if (!render_view_host() || !render_view_host()->GetProcess()) { |
| 425 SendResponse(false); |
| 426 return false; |
| 427 } |
| 428 |
| 429 int embedder_process_id = render_view_host()->GetProcess()->GetID(); |
| 430 manager->RemoveContentScripts(embedder_process_id, guest_view_instance_id, |
| 431 (params->script_name_list).get()); |
| 432 |
| 433 SendResponse(true); |
| 434 return true; |
| 435 } |
| 436 |
168 WebViewInternalSetNameFunction::WebViewInternalSetNameFunction() { | 437 WebViewInternalSetNameFunction::WebViewInternalSetNameFunction() { |
169 } | 438 } |
170 | 439 |
171 WebViewInternalSetNameFunction::~WebViewInternalSetNameFunction() { | 440 WebViewInternalSetNameFunction::~WebViewInternalSetNameFunction() { |
172 } | 441 } |
173 | 442 |
174 bool WebViewInternalSetNameFunction::RunAsyncSafe(WebViewGuest* guest) { | 443 bool WebViewInternalSetNameFunction::RunAsyncSafe(WebViewGuest* guest) { |
175 scoped_ptr<webview::SetName::Params> params( | 444 scoped_ptr<webview::SetName::Params> params( |
176 webview::SetName::Params::Create(*args_)); | 445 webview::SetName::Params::Create(*args_)); |
177 EXTENSION_FUNCTION_VALIDATE(params.get()); | 446 EXTENSION_FUNCTION_VALIDATE(params.get()); |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 // Will finish asynchronously. | 791 // Will finish asynchronously. |
523 return true; | 792 return true; |
524 } | 793 } |
525 | 794 |
526 void WebViewInternalClearDataFunction::ClearDataDone() { | 795 void WebViewInternalClearDataFunction::ClearDataDone() { |
527 Release(); // Balanced in RunAsync(). | 796 Release(); // Balanced in RunAsync(). |
528 SendResponse(true); | 797 SendResponse(true); |
529 } | 798 } |
530 | 799 |
531 } // namespace extensions | 800 } // namespace extensions |
OLD | NEW |