Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / extensions / browser / api / execute_code_function.cc
blob21845aa47ec48b07e549e7b449c10d0641799358
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 kBadFileEncodingError[] =
29 "Could not load file '*' for content script. It isn't UTF-8 encoded.";
30 const char kLoadFileError[] = "Failed to load file: \"*\". ";
34 namespace extensions {
36 using core_api::extension_types::InjectDetails;
38 ExecuteCodeFunction::ExecuteCodeFunction() {
41 ExecuteCodeFunction::~ExecuteCodeFunction() {
44 void ExecuteCodeFunction::DidLoadFile(bool success, const std::string& data) {
45 if (!success || !details_->file) {
46 DidLoadAndLocalizeFile(success, data);
47 return;
50 ScriptExecutor::ScriptType script_type =
51 ShouldInsertCSS() ? ScriptExecutor::CSS : ScriptExecutor::JAVASCRIPT;
53 std::string extension_id;
54 base::FilePath extension_path;
55 std::string extension_default_locale;
56 if (extension()) {
57 extension_id = extension()->id();
58 extension_path = extension()->path();
59 extension()->manifest()->GetString(manifest_keys::kDefaultLocale,
60 &extension_default_locale);
63 content::BrowserThread::PostTask(
64 content::BrowserThread::FILE,
65 FROM_HERE,
66 base::Bind(&ExecuteCodeFunction::GetFileURLAndLocalizeCSS,
67 this,
68 script_type,
69 data,
70 extension_id,
71 extension_path,
72 extension_default_locale));
75 void ExecuteCodeFunction::GetFileURLAndLocalizeCSS(
76 ScriptExecutor::ScriptType script_type,
77 const std::string& data,
78 const std::string& extension_id,
79 const base::FilePath& extension_path,
80 const std::string& extension_default_locale) {
81 std::string localized_data = data;
82 // Check if the file is CSS and needs localization.
83 if ((script_type == ScriptExecutor::CSS) && !extension_id.empty() &&
84 (data.find(MessageBundle::kMessageBegin) != std::string::npos)) {
85 scoped_ptr<SubstitutionMap> localization_messages(
86 file_util::LoadMessageBundleSubstitutionMap(
87 extension_path, extension_id, extension_default_locale));
89 // We need to do message replacement on the data, so it has to be mutable.
90 std::string error;
91 MessageBundle::ReplaceMessagesWithExternalDictionary(
92 *localization_messages, &localized_data, &error);
95 file_url_ = net::FilePathToFileURL(resource_.GetFilePath());
97 // Call back DidLoadAndLocalizeFile on the UI thread. The success parameter
98 // is always true, because if loading had failed, we wouldn't have had
99 // anything to localize.
100 content::BrowserThread::PostTask(
101 content::BrowserThread::UI,
102 FROM_HERE,
103 base::Bind(&ExecuteCodeFunction::DidLoadAndLocalizeFile,
104 this,
105 true,
106 localized_data));
109 void ExecuteCodeFunction::DidLoadAndLocalizeFile(bool success,
110 const std::string& data) {
111 if (success) {
112 if (!base::IsStringUTF8(data)) {
113 error_ = ErrorUtils::FormatErrorMessage(
114 kBadFileEncodingError, resource_.relative_path().AsUTF8Unsafe());
115 SendResponse(false);
116 } else if (!Execute(data))
117 SendResponse(false);
118 } else {
119 // TODO(viettrungluu): bug: there's no particular reason the path should be
120 // UTF-8, in which case this may fail.
121 error_ = ErrorUtils::FormatErrorMessage(
122 kLoadFileError, resource_.relative_path().AsUTF8Unsafe());
123 SendResponse(false);
127 bool ExecuteCodeFunction::Execute(const std::string& code_string) {
128 ScriptExecutor* executor = GetScriptExecutor();
129 if (!executor)
130 return false;
132 if (!extension())
133 return false;
135 ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT;
136 if (ShouldInsertCSS())
137 script_type = ScriptExecutor::CSS;
139 ScriptExecutor::FrameScope frame_scope =
140 details_->all_frames.get() && *details_->all_frames
141 ? ScriptExecutor::ALL_FRAMES
142 : ScriptExecutor::TOP_FRAME;
144 ScriptExecutor::MatchAboutBlank match_about_blank =
145 details_->match_about_blank.get() && *details_->match_about_blank
146 ? ScriptExecutor::MATCH_ABOUT_BLANK
147 : ScriptExecutor::DONT_MATCH_ABOUT_BLANK;
149 UserScript::RunLocation run_at = UserScript::UNDEFINED;
150 switch (details_->run_at) {
151 case InjectDetails::RUN_AT_NONE:
152 case InjectDetails::RUN_AT_DOCUMENT_IDLE:
153 run_at = UserScript::DOCUMENT_IDLE;
154 break;
155 case InjectDetails::RUN_AT_DOCUMENT_START:
156 run_at = UserScript::DOCUMENT_START;
157 break;
158 case InjectDetails::RUN_AT_DOCUMENT_END:
159 run_at = UserScript::DOCUMENT_END;
160 break;
162 CHECK_NE(UserScript::UNDEFINED, run_at);
164 executor->ExecuteScript(
165 extension()->id(),
166 script_type,
167 code_string,
168 frame_scope,
169 match_about_blank,
170 run_at,
171 ScriptExecutor::ISOLATED_WORLD,
172 IsWebView() ? ScriptExecutor::WEB_VIEW_PROCESS
173 : ScriptExecutor::DEFAULT_PROCESS,
174 GetWebViewSrc(),
175 file_url_,
176 user_gesture_,
177 has_callback() ? ScriptExecutor::JSON_SERIALIZED_RESULT
178 : ScriptExecutor::NO_RESULT,
179 base::Bind(&ExecuteCodeFunction::OnExecuteCodeFinished, this));
180 return true;
183 bool ExecuteCodeFunction::HasPermission() {
184 return true;
187 bool ExecuteCodeFunction::RunAsync() {
188 EXTENSION_FUNCTION_VALIDATE(Init());
190 if (!details_->code.get() && !details_->file.get()) {
191 error_ = kNoCodeOrFileToExecuteError;
192 return false;
194 if (details_->code.get() && details_->file.get()) {
195 error_ = kMoreThanOneValuesError;
196 return false;
199 if (!CanExecuteScriptOnPage())
200 return false;
202 if (details_->code.get())
203 return Execute(*details_->code);
205 if (!details_->file.get())
206 return false;
207 resource_ = extension()->GetResource(*details_->file);
209 if (resource_.extension_root().empty() || resource_.relative_path().empty()) {
210 error_ = kNoCodeOrFileToExecuteError;
211 return false;
214 int resource_id;
215 const ComponentExtensionResourceManager*
216 component_extension_resource_manager =
217 ExtensionsBrowserClient::Get()
218 ->GetComponentExtensionResourceManager();
219 if (component_extension_resource_manager &&
220 component_extension_resource_manager->IsComponentExtensionResource(
221 resource_.extension_root(),
222 resource_.relative_path(),
223 &resource_id)) {
224 const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
225 DidLoadFile(true, rb.GetRawDataResource(resource_id).as_string());
226 } else {
227 scoped_refptr<FileReader> file_reader(new FileReader(
228 resource_, base::Bind(&ExecuteCodeFunction::DidLoadFile, this)));
229 file_reader->Start();
232 return true;
235 void ExecuteCodeFunction::OnExecuteCodeFinished(const std::string& error,
236 const GURL& on_url,
237 const base::ListValue& result) {
238 if (!error.empty())
239 SetError(error);
241 SendResponse(error.empty());
244 } // namespace extensions
246 #endif // EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_