Add testing/scripts/OWNERS
[chromium-blink-merge.git] / extensions / browser / api / execute_code_function.cc
blob63d1bfef46cc0f34025e95bd25177ca58dc19694
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
3 // found in the LICENSE file.
5 #ifndef EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_
6 #define EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_
8 #include "extensions/browser/api/execute_code_function.h"
10 #include "extensions/browser/component_extension_resource_manager.h"
11 #include "extensions/browser/extensions_browser_client.h"
12 #include "extensions/browser/file_reader.h"
13 #include "extensions/common/error_utils.h"
14 #include "extensions/common/extension_messages.h"
15 #include "extensions/common/file_util.h"
16 #include "extensions/common/manifest_constants.h"
17 #include "extensions/common/message_bundle.h"
18 #include "net/base/filename_util.h"
19 #include "ui/base/resource/resource_bundle.h"
21 namespace {
23 // Error messages
24 const char kNoCodeOrFileToExecuteError[] = "No source code or file specified.";
25 const char kMoreThanOneValuesError[] =
26 "Code and file should not be specified "
27 "at the same time in the second argument.";
28 const char kLoadFileError[] = "Failed to load file: \"*\". ";
32 namespace extensions {
34 using core_api::extension_types::InjectDetails;
36 ExecuteCodeFunction::ExecuteCodeFunction() {
39 ExecuteCodeFunction::~ExecuteCodeFunction() {
42 void ExecuteCodeFunction::DidLoadFile(bool success, const std::string& data) {
43 if (!success || !details_->file) {
44 DidLoadAndLocalizeFile(success, data);
45 return;
48 ScriptExecutor::ScriptType script_type =
49 ShouldInsertCSS() ? ScriptExecutor::CSS : ScriptExecutor::JAVASCRIPT;
51 std::string extension_id;
52 base::FilePath extension_path;
53 std::string extension_default_locale;
54 if (extension()) {
55 extension_id = extension()->id();
56 extension_path = extension()->path();
57 extension()->manifest()->GetString(manifest_keys::kDefaultLocale,
58 &extension_default_locale);
61 content::BrowserThread::PostTask(
62 content::BrowserThread::FILE,
63 FROM_HERE,
64 base::Bind(&ExecuteCodeFunction::GetFileURLAndLocalizeCSS,
65 this,
66 script_type,
67 data,
68 extension_id,
69 extension_path,
70 extension_default_locale));
73 void ExecuteCodeFunction::GetFileURLAndLocalizeCSS(
74 ScriptExecutor::ScriptType script_type,
75 const std::string& data,
76 const std::string& extension_id,
77 const base::FilePath& extension_path,
78 const std::string& extension_default_locale) {
79 std::string localized_data = data;
80 // Check if the file is CSS and needs localization.
81 if ((script_type == ScriptExecutor::CSS) && !extension_id.empty() &&
82 (data.find(MessageBundle::kMessageBegin) != std::string::npos)) {
83 scoped_ptr<SubstitutionMap> localization_messages(
84 file_util::LoadMessageBundleSubstitutionMap(
85 extension_path, extension_id, extension_default_locale));
87 // We need to do message replacement on the data, so it has to be mutable.
88 std::string error;
89 MessageBundle::ReplaceMessagesWithExternalDictionary(
90 *localization_messages, &localized_data, &error);
93 file_url_ = net::FilePathToFileURL(resource_.GetFilePath());
95 // Call back DidLoadAndLocalizeFile on the UI thread. The success parameter
96 // is always true, because if loading had failed, we wouldn't have had
97 // anything to localize.
98 content::BrowserThread::PostTask(
99 content::BrowserThread::UI,
100 FROM_HERE,
101 base::Bind(&ExecuteCodeFunction::DidLoadAndLocalizeFile,
102 this,
103 true,
104 localized_data));
107 void ExecuteCodeFunction::DidLoadAndLocalizeFile(bool success,
108 const std::string& data) {
109 if (success) {
110 if (!Execute(data))
111 SendResponse(false);
112 } else {
113 // TODO(viettrungluu): bug: there's no particular reason the path should be
114 // UTF-8, in which case this may fail.
115 error_ = ErrorUtils::FormatErrorMessage(
116 kLoadFileError, resource_.relative_path().AsUTF8Unsafe());
117 SendResponse(false);
121 bool ExecuteCodeFunction::Execute(const std::string& code_string) {
122 ScriptExecutor* executor = GetScriptExecutor();
123 if (!executor)
124 return false;
126 if (!extension())
127 return false;
129 ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT;
130 if (ShouldInsertCSS())
131 script_type = ScriptExecutor::CSS;
133 ScriptExecutor::FrameScope frame_scope =
134 details_->all_frames.get() && *details_->all_frames
135 ? ScriptExecutor::ALL_FRAMES
136 : ScriptExecutor::TOP_FRAME;
138 ScriptExecutor::MatchAboutBlank match_about_blank =
139 details_->match_about_blank.get() && *details_->match_about_blank
140 ? ScriptExecutor::MATCH_ABOUT_BLANK
141 : ScriptExecutor::DONT_MATCH_ABOUT_BLANK;
143 UserScript::RunLocation run_at = UserScript::UNDEFINED;
144 switch (details_->run_at) {
145 case InjectDetails::RUN_AT_NONE:
146 case InjectDetails::RUN_AT_DOCUMENT_IDLE:
147 run_at = UserScript::DOCUMENT_IDLE;
148 break;
149 case InjectDetails::RUN_AT_DOCUMENT_START:
150 run_at = UserScript::DOCUMENT_START;
151 break;
152 case InjectDetails::RUN_AT_DOCUMENT_END:
153 run_at = UserScript::DOCUMENT_END;
154 break;
156 CHECK_NE(UserScript::UNDEFINED, run_at);
158 executor->ExecuteScript(
159 extension()->id(),
160 script_type,
161 code_string,
162 frame_scope,
163 match_about_blank,
164 run_at,
165 ScriptExecutor::ISOLATED_WORLD,
166 IsWebView() ? ScriptExecutor::WEB_VIEW_PROCESS
167 : ScriptExecutor::DEFAULT_PROCESS,
168 GetWebViewSrc(),
169 file_url_,
170 user_gesture_,
171 has_callback() ? ScriptExecutor::JSON_SERIALIZED_RESULT
172 : ScriptExecutor::NO_RESULT,
173 base::Bind(&ExecuteCodeFunction::OnExecuteCodeFinished, this));
174 return true;
177 bool ExecuteCodeFunction::HasPermission() {
178 return true;
181 bool ExecuteCodeFunction::RunAsync() {
182 EXTENSION_FUNCTION_VALIDATE(Init());
184 if (!details_->code.get() && !details_->file.get()) {
185 error_ = kNoCodeOrFileToExecuteError;
186 return false;
188 if (details_->code.get() && details_->file.get()) {
189 error_ = kMoreThanOneValuesError;
190 return false;
193 if (!CanExecuteScriptOnPage())
194 return false;
196 if (details_->code.get())
197 return Execute(*details_->code);
199 if (!details_->file.get())
200 return false;
201 resource_ = extension()->GetResource(*details_->file);
203 if (resource_.extension_root().empty() || resource_.relative_path().empty()) {
204 error_ = kNoCodeOrFileToExecuteError;
205 return false;
208 int resource_id;
209 ComponentExtensionResourceManager* component_extension_resource_manager =
210 ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager();
211 if (component_extension_resource_manager &&
212 component_extension_resource_manager->IsComponentExtensionResource(
213 resource_.extension_root(),
214 resource_.relative_path(),
215 &resource_id)) {
216 const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
217 DidLoadFile(true, rb.GetRawDataResource(resource_id).as_string());
218 } else {
219 scoped_refptr<FileReader> file_reader(new FileReader(
220 resource_, base::Bind(&ExecuteCodeFunction::DidLoadFile, this)));
221 file_reader->Start();
224 return true;
227 void ExecuteCodeFunction::OnExecuteCodeFinished(const std::string& error,
228 const GURL& on_url,
229 const base::ListValue& result) {
230 if (!error.empty())
231 SetError(error);
233 SendResponse(error.empty());
236 } // namespace extensions
238 #endif // EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_