Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / api / execute_code_function.cc
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.
4
5 #ifndef EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_
6 #define EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_
7
8 #include "extensions/browser/api/execute_code_function.h"
9
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"
20
21 namespace {
22
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: \"*\". ";
29
30 }
31
32 namespace extensions {
33
34 using core_api::extension_types::InjectDetails;
35
36 ExecuteCodeFunction::ExecuteCodeFunction() {
37 }
38
39 ExecuteCodeFunction::~ExecuteCodeFunction() {
40 }
41
42 void ExecuteCodeFunction::DidLoadFile(bool success, const std::string& data) {
43   if (!success || !details_->file) {
44     DidLoadAndLocalizeFile(success, data);
45     return;
46   }
47
48   ScriptExecutor::ScriptType script_type =
49       ShouldInsertCSS() ? ScriptExecutor::CSS : ScriptExecutor::JAVASCRIPT;
50
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);
59   }
60
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));
71 }
72
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));
86
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);
91   }
92
93   file_url_ = net::FilePathToFileURL(resource_.GetFilePath());
94
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));
105 }
106
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);
118   }
119 }
120
121 bool ExecuteCodeFunction::Execute(const std::string& code_string) {
122   ScriptExecutor* executor = GetScriptExecutor();
123   if (!executor)
124     return false;
125
126   if (!extension())
127     return false;
128
129   ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT;
130   if (ShouldInsertCSS())
131     script_type = ScriptExecutor::CSS;
132
133   ScriptExecutor::FrameScope frame_scope =
134       details_->all_frames.get() && *details_->all_frames
135           ? ScriptExecutor::ALL_FRAMES
136           : ScriptExecutor::TOP_FRAME;
137
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;
142
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;
155   }
156   CHECK_NE(UserScript::UNDEFINED, run_at);
157
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;
175 }
176
177 bool ExecuteCodeFunction::HasPermission() {
178   return true;
179 }
180
181 bool ExecuteCodeFunction::RunAsync() {
182   EXTENSION_FUNCTION_VALIDATE(Init());
183
184   if (!details_->code.get() && !details_->file.get()) {
185     error_ = kNoCodeOrFileToExecuteError;
186     return false;
187   }
188   if (details_->code.get() && details_->file.get()) {
189     error_ = kMoreThanOneValuesError;
190     return false;
191   }
192
193   if (!CanExecuteScriptOnPage())
194     return false;
195
196   if (details_->code.get())
197     return Execute(*details_->code);
198
199   if (!details_->file.get())
200     return false;
201   resource_ = extension()->GetResource(*details_->file);
202
203   if (resource_.extension_root().empty() || resource_.relative_path().empty()) {
204     error_ = kNoCodeOrFileToExecuteError;
205     return false;
206   }
207
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();
222   }
223
224   return true;
225 }
226
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);
232
233   SendResponse(error.empty());
234 }
235
236 }  // namespace extensions
237
238 #endif  // EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_