Chromium Code Reviews| Index: extensions/browser/api/guest_view/web_view/web_view_internal_api.cc |
| diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc |
| index 74c89c6346f931030692756356d28be189b178e3..727c2158f7e142aa8abaeff4c55178b4b1c1433e 100644 |
| --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc |
| +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc |
| @@ -4,6 +4,7 @@ |
| #include "extensions/browser/api/guest_view/web_view/web_view_internal_api.h" |
| +#include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "content/public/browser/browser_context.h" |
| @@ -13,17 +14,25 @@ |
| #include "content/public/common/stop_find_action.h" |
| #include "content/public/common/url_fetcher.h" |
| #include "extensions/browser/guest_view/web_view/web_view_constants.h" |
| +#include "extensions/browser/guest_view/web_view/web_view_content_script_manager.h" |
| #include "extensions/common/api/web_view_internal.h" |
| #include "extensions/common/error_utils.h" |
| +#include "extensions/common/manifest_constants.h" |
| +#include "extensions/common/user_script.h" |
| #include "net/base/load_flags.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "third_party/WebKit/public/web/WebFindOptions.h" |
| using content::WebContents; |
| +using extensions::ExtensionResource; |
| +using extensions::core_api::web_view_internal::ContentScriptDetails; |
| using extensions::core_api::web_view_internal::SetPermission::Params; |
| using extensions::core_api::extension_types::InjectDetails; |
| +using extensions::UserScript; |
| using ui_zoom::ZoomController; |
| +// error messages for content scripts: |
| +namespace errors = extensions::manifest_errors; |
| namespace web_view_internal = extensions::core_api::web_view_internal; |
| namespace { |
| @@ -37,6 +46,7 @@ const char kLocalStorageKey[] = "localStorage"; |
| const char kWebSQLKey[] = "webSQL"; |
| const char kSinceKey[] = "since"; |
| const char kLoadFileError[] = "Failed to load file: \"*\". "; |
| +const char kViewInstanceIdError[] = "view_instance_id is missing."; |
| uint32 MaskForKey(const char* key) { |
| if (strcmp(key, kAppCacheKey) == 0) |
| @@ -56,6 +66,148 @@ uint32 MaskForKey(const char* key) { |
| return 0; |
| } |
| +HostID GenerateHostIDFromEmbedder(const extensions::Extension* extension, |
| + const content::WebContents* web_contents) { |
| + if (extension) |
| + return HostID(HostID::EXTENSIONS, extension->id()); |
| + |
| + if (web_contents && web_contents->GetWebUI()) { |
| + const GURL& url = web_contents->GetSiteInstance()->GetSiteURL(); |
| + return HostID(HostID::WEBUI, url.spec()); |
| + } |
| + NOTREACHED(); |
| + return HostID(); |
| +} |
| + |
| +// Parses the values stored in ContentScriptDetails, and constructs a |
| +// UserScript. |
| +bool ParseContentScript(const ContentScriptDetails& script_value, |
| + const extensions::Extension* extension, |
| + const GURL& owner_base_url, |
| + UserScript* script, |
| + std::string* error) { |
| + // matches (required): |
| + const std::vector<std::string>& matches = script_value.matches; |
| + if (matches.size() == 0) |
| + return false; |
| + |
| + for (const std::string& match : matches) { |
| + URLPattern pattern(UserScript::ValidUserScriptSchemes( |
| + true /* canExecuteScriptEverywhere */)); |
| + if (pattern.Parse(match) != URLPattern::PARSE_SUCCESS) { |
| + *error = errors::kInvalidMatches; |
| + return false; |
| + } |
| + script->add_url_pattern(pattern); |
| + } |
| + |
| + // exclude_matches: |
| + if (script_value.exclude_matches) { |
| + const std::vector<std::string>& exclude_matches = |
| + *(script_value.exclude_matches.get()); |
| + for (const std::string& exclude_match : exclude_matches) { |
| + URLPattern pattern(UserScript::ValidUserScriptSchemes( |
| + true /* canExecuteScriptEverywhere */)); |
| + |
| + if (pattern.Parse(exclude_match) != URLPattern::PARSE_SUCCESS) { |
| + *error = errors::kInvalidExcludeMatches; |
| + return false; |
| + } |
| + script->add_exclude_url_pattern(pattern); |
| + } |
| + } |
| + // run_at: |
| + if (script_value.run_at) { |
| + UserScript::RunLocation run_at = UserScript::UNDEFINED; |
| + switch (script_value.run_at) { |
| + case extensions::core_api::extension_types::RUN_AT_NONE: |
| + case extensions::core_api::extension_types::RUN_AT_DOCUMENT_IDLE: |
| + run_at = UserScript::DOCUMENT_IDLE; |
| + break; |
| + case extensions::core_api::extension_types::RUN_AT_DOCUMENT_START: |
| + run_at = UserScript::DOCUMENT_START; |
| + break; |
| + case extensions::core_api::extension_types::RUN_AT_DOCUMENT_END: |
| + run_at = UserScript::DOCUMENT_END; |
| + break; |
| + } |
| + script->set_run_location(run_at); |
| + } |
| + |
| + // match_about_blank: |
| + if (script_value.match_about_blank) |
| + script->set_match_about_blank(*script_value.match_about_blank); |
| + |
| + // css: |
| + if (script_value.css) { |
| + for (const std::string& relative : *(script_value.css.get())) { |
| + GURL url = owner_base_url.Resolve(relative); |
| + if (extension) { |
| + ExtensionResource resource = extension->GetResource(relative); |
| + script->css_scripts().push_back(UserScript::File( |
| + resource.extension_root(), resource.relative_path(), url)); |
| + } else { |
| + script->css_scripts().push_back(extensions::UserScript::File( |
| + base::FilePath(), base::FilePath(), url)); |
| + } |
| + } |
| + } |
| + |
| + // js: |
| + if (script_value.js) { |
| + for (const std::string& relative : *(script_value.js.get())) { |
| + GURL url = owner_base_url.Resolve(relative); |
| + if (extension) { |
| + ExtensionResource resource = extension->GetResource(relative); |
| + script->js_scripts().push_back(UserScript::File( |
| + resource.extension_root(), resource.relative_path(), url)); |
| + } else { |
| + script->js_scripts().push_back(extensions::UserScript::File( |
| + base::FilePath(), base::FilePath(), url)); |
| + } |
| + } |
| + } |
| + |
| + // all_frames: |
| + if (script_value.all_frames) |
| + script->set_match_all_frames(*(script_value.all_frames)); |
| + |
| + // include_globs: |
| + if (script_value.include_globs) { |
| + for (const std::string& glob : *(script_value.include_globs.get())) |
| + script->add_glob(glob); |
| + } |
| + |
| + // exclude_globs: |
| + if (script_value.exclude_globs) { |
| + for (const std::string& glob : *(script_value.exclude_globs.get())) |
| + script->add_exclude_glob(glob); |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool ParseContentScripts( |
| + std::vector<linked_ptr<ContentScriptDetails>> content_script_list, |
| + const extensions::Extension* extension, |
| + const GURL& owner_base_url, |
| + std::map<std::string, UserScript>* result, |
| + std::string* error) { |
| + if (content_script_list.empty()) |
| + return false; |
| + for (const linked_ptr<ContentScriptDetails> script_value : |
| + content_script_list) { |
| + const std::string& name = script_value->name; |
| + UserScript script; |
| + if (!ParseContentScript(*script_value, extension, owner_base_url, &script, |
| + error)) |
| + return false; |
| + script.set_name(name); |
| + (*result)[name] = script; |
| + } |
| + return true; |
| +} |
| + |
| } // namespace |
| namespace extensions { |
| @@ -256,6 +408,87 @@ bool WebViewInternalInsertCSSFunction::ShouldInsertCSS() const { |
| return true; |
| } |
| +WebViewInternalAddContentScriptsFunction:: |
| + WebViewInternalAddContentScriptsFunction() { |
| +} |
| + |
| +WebViewInternalAddContentScriptsFunction:: |
| + ~WebViewInternalAddContentScriptsFunction() { |
| +} |
| + |
| +ExecuteCodeFunction::ResponseAction |
| +WebViewInternalAddContentScriptsFunction::Run() { |
| + scoped_ptr<web_view_internal::AddContentScripts::Params> params( |
| + web_view_internal::AddContentScripts::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + |
| + int view_instance_id = params->instance_id; |
|
Devlin
2015/04/14 23:04:57
why not just use params->instance_id?
Xi Han
2015/04/15 19:43:55
Since later we will use view_instance_id again (li
Devlin
2015/04/15 20:58:05
The compiler will definitely optimize this out (th
Xi Han
2015/04/16 15:12:22
That is fine, updated.
|
| + if (!view_instance_id) |
| + return RespondNow(Error(kViewInstanceIdError)); |
| + |
| + GURL owner_base_url( |
| + render_view_host()->GetSiteInstance()->GetSiteURL().GetWithEmptyPath()); |
| + std::map<std::string, UserScript> scripts; |
|
Devlin
2015/04/14 23:04:57
This map is still rather useless. Why not just ge
Xi Han
2015/04/15 19:43:55
This map is used to deal with the name duplication
Devlin
2015/04/15 20:58:05
I think if the user is trying to add two scripts w
Xi Han
2015/04/16 15:12:22
That is ok, I use a set to check the duplication o
|
| + std::set<UserScript> result; |
| + if (!ParseContentScripts(params->content_script_list, extension(), |
| + owner_base_url, &scripts, &error_)) |
| + return RespondNow(Error(error_)); |
| + |
| + WebViewContentScriptManager* manager = |
| + WebViewContentScriptManager::Get(browser_context()); |
| + |
| + content::WebContents* sender_web_contents = GetSenderWebContents(); |
| + HostID host_id = GenerateHostIDFromEmbedder(extension(), sender_web_contents); |
| + |
| + for (const auto& iter : scripts) { |
| + UserScript script = iter.second; |
| + script.set_id(UserScript::GenerateUserScriptID()); |
|
Devlin
2015/04/14 23:04:57
Why not do these in ParseContentScript(s)?
Xi Han
2015/04/15 19:43:55
It could, but I hope the ParseContentScript(s) onl
Devlin
2015/04/15 20:58:05
I think I'd like to have the script generation all
Xi Han
2015/04/16 15:12:22
Yes, as you suggested, I also move the initilizati
|
| + script.set_incognito_enabled(browser_context()->IsOffTheRecord()); |
| + script.set_host_id( |
| + GenerateHostIDFromEmbedder(extension(), sender_web_contents)); |
| + script.set_consumer_instance_type(UserScript::WEBVIEW); |
| + result.insert(script); |
| + } |
| + |
| + manager->AddContentScripts(sender_web_contents, view_instance_id, host_id, |
| + result); |
| + |
| + return RespondNow(NoArguments()); |
| +} |
| + |
| +WebViewInternalRemoveContentScriptsFunction:: |
| + WebViewInternalRemoveContentScriptsFunction() { |
| +} |
| + |
| +WebViewInternalRemoveContentScriptsFunction:: |
| + ~WebViewInternalRemoveContentScriptsFunction() { |
| +} |
| + |
| +ExecuteCodeFunction::ResponseAction |
| +WebViewInternalRemoveContentScriptsFunction::Run() { |
| + scoped_ptr<web_view_internal::RemoveContentScripts::Params> params( |
| + web_view_internal::RemoveContentScripts::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + |
| + int view_instance_id = params->instance_id; |
| + if (!view_instance_id) |
|
Devlin
2015/04/14 23:04:57
just use params->instance_id
Xi Han
2015/04/15 19:43:55
Same as above. It is used in line 487.
Xi Han
2015/04/16 15:12:22
Done.
|
| + return RespondNow(Error(kViewInstanceIdError)); |
| + |
| + WebViewContentScriptManager* manager = |
| + WebViewContentScriptManager::Get(browser_context()); |
| + DCHECK(manager); |
| + |
| + content::WebContents* sender_web_contents = GetSenderWebContents(); |
| + HostID host_id = GenerateHostIDFromEmbedder(extension(), sender_web_contents); |
| + |
| + std::vector<std::string> script_name_list; |
| + if (params->script_name_list) |
| + script_name_list.swap(*params->script_name_list); |
| + manager->RemoveContentScripts(GetSenderWebContents(), view_instance_id, |
| + host_id, script_name_list); |
| + return RespondNow(NoArguments()); |
| +} |
| + |
| WebViewInternalSetNameFunction::WebViewInternalSetNameFunction() { |
| } |