Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Side by Side Diff: chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc

Issue 11747025: Run the JSON Schema Compiler's bundle compilation on JSON files. Previously it (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix ms release build Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h"
6
7 #include "base/bind.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/extensions/api/tabs/tabs.h"
11 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/extensions/file_reader.h"
15 #include "chrome/browser/extensions/script_executor.h"
16 #include "chrome/browser/extensions/tab_helper.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/common/extensions/api/tabs.h"
20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/extensions/extension_file_util.h"
23 #include "chrome/common/extensions/extension_l10n_util.h"
24 #include "chrome/common/extensions/extension_manifest_constants.h"
25 #include "chrome/common/extensions/extension_messages.h"
26 #include "chrome/common/extensions/message_bundle.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "extensions/common/error_utils.h"
30
31 using content::BrowserThread;
32 using extensions::api::tabs::InjectDetails;
33 using extensions::ErrorUtils;
34 using extensions::ScriptExecutor;
35 using extensions::UserScript;
36
37 namespace keys = extensions::tabs_constants;
38
39 ExecuteCodeInTabFunction::ExecuteCodeInTabFunction()
40 : execute_tab_id_(-1) {
41 }
42
43 ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
44
45 bool ExecuteCodeInTabFunction::HasPermission() {
46 if (Init() &&
47 extension_->HasAPIPermissionForTab(execute_tab_id_,
48 extensions::APIPermission::kTab)) {
49 return true;
50 }
51 return ExtensionFunction::HasPermission();
52 }
53
54 bool ExecuteCodeInTabFunction::RunImpl() {
55 EXTENSION_FUNCTION_VALIDATE(Init());
56
57 if (!details_->code.get() && !details_->file.get()) {
58 error_ = keys::kNoCodeOrFileToExecuteError;
59 return false;
60 }
61 if (details_->code.get() && details_->file.get()) {
62 error_ = keys::kMoreThanOneValuesError;
63 return false;
64 }
65
66 content::WebContents* contents = NULL;
67
68 // If |tab_id| is specified, look for the tab. Otherwise default to selected
69 // tab in the current window.
70 CHECK_GE(execute_tab_id_, 0);
71 if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(),
72 include_incognito(),
73 NULL, NULL, &contents, NULL)) {
74 return false;
75 }
76
77 // NOTE: This can give the wrong answer due to race conditions, but it is OK,
78 // we check again in the renderer.
79 CHECK(contents);
80 if (!GetExtension()->CanExecuteScriptOnPage(contents->GetURL(),
81 contents->GetURL(),
82 execute_tab_id_,
83 NULL,
84 &error_)) {
85 return false;
86 }
87
88 if (details_->code.get())
89 return Execute(*details_->code);
90
91 CHECK(details_->file.get());
92 resource_ = GetExtension()->GetResource(*details_->file);
93
94 if (resource_.extension_root().empty() || resource_.relative_path().empty()) {
95 error_ = keys::kNoCodeOrFileToExecuteError;
96 return false;
97 }
98
99 scoped_refptr<FileReader> file_reader(new FileReader(
100 resource_, base::Bind(&ExecuteCodeInTabFunction::DidLoadFile, this)));
101 file_reader->Start();
102
103 return true;
104 }
105
106 void ExecuteCodeInTabFunction::OnExecuteCodeFinished(const std::string& error,
107 int32 on_page_id,
108 const GURL& on_url,
109 const ListValue& result) {
110 if (!error.empty())
111 SetError(error);
112
113 SendResponse(error.empty());
114 }
115
116 void TabsExecuteScriptFunction::OnExecuteCodeFinished(const std::string& error,
117 int32 on_page_id,
118 const GURL& on_url,
119 const ListValue& result) {
120 if (error.empty())
121 SetResult(result.DeepCopy());
122 ExecuteCodeInTabFunction::OnExecuteCodeFinished(error, on_page_id, on_url,
123 result);
124 }
125
126 bool ExecuteCodeInTabFunction::Init() {
127 if (details_.get())
128 return true;
129
130 // |tab_id| is optional so it's ok if it's not there.
131 int tab_id = -1;
132 args_->GetInteger(0, &tab_id);
133
134 // |details| are not optional.
135 DictionaryValue* details_value = NULL;
136 if (!args_->GetDictionary(1, &details_value))
137 return false;
138 scoped_ptr<InjectDetails> details(new InjectDetails());
139 if (!InjectDetails::Populate(*details_value, details.get()))
140 return false;
141
142 // If the tab ID is -1 then it needs to be converted to the currently active
143 // tab's ID.
144 if (tab_id == -1) {
145 Browser* browser = GetCurrentBrowser();
146 if (!browser)
147 return false;
148 content::WebContents* web_contents = NULL;
149 if (!ExtensionTabUtil::GetDefaultTab(browser, &web_contents, &tab_id))
150 return false;
151 }
152
153 execute_tab_id_ = tab_id;
154 details_ = details.Pass();
155 return true;
156 }
157
158 void ExecuteCodeInTabFunction::DidLoadFile(bool success,
159 const std::string& data) {
160 std::string function_name = name();
161 const extensions::Extension* extension = GetExtension();
162
163 // Check if the file is CSS and needs localization.
164 if (success &&
165 function_name == TabsInsertCSSFunction::function_name() &&
166 extension != NULL &&
167 data.find(
168 extensions::MessageBundle::kMessageBegin) != std::string::npos) {
169 BrowserThread::PostTask(
170 BrowserThread::FILE, FROM_HERE,
171 base::Bind(&ExecuteCodeInTabFunction::LocalizeCSS, this,
172 data,
173 extension->id(),
174 extension->path(),
175 extension->default_locale()));
176 } else {
177 DidLoadAndLocalizeFile(success, data);
178 }
179 }
180
181 void ExecuteCodeInTabFunction::LocalizeCSS(
182 const std::string& data,
183 const std::string& extension_id,
184 const FilePath& extension_path,
185 const std::string& extension_default_locale) {
186 scoped_ptr<SubstitutionMap> localization_messages(
187 extension_file_util::LoadMessageBundleSubstitutionMap(
188 extension_path, extension_id, extension_default_locale));
189
190 // We need to do message replacement on the data, so it has to be mutable.
191 std::string css_data = data;
192 std::string error;
193 extensions::MessageBundle::ReplaceMessagesWithExternalDictionary(
194 *localization_messages, &css_data, &error);
195
196 // Call back DidLoadAndLocalizeFile on the UI thread. The success parameter
197 // is always true, because if loading had failed, we wouldn't have had
198 // anything to localize.
199 BrowserThread::PostTask(
200 BrowserThread::UI, FROM_HERE,
201 base::Bind(&ExecuteCodeInTabFunction::DidLoadAndLocalizeFile, this,
202 true, css_data));
203 }
204
205 void ExecuteCodeInTabFunction::DidLoadAndLocalizeFile(bool success,
206 const std::string& data) {
207 if (success) {
208 if (!Execute(data))
209 SendResponse(false);
210 } else {
211 #if defined(OS_POSIX)
212 // TODO(viettrungluu): bug: there's no particular reason the path should be
213 // UTF-8, in which case this may fail.
214 error_ = ErrorUtils::FormatErrorMessage(keys::kLoadFileError,
215 resource_.relative_path().value());
216 #elif defined(OS_WIN)
217 error_ = ErrorUtils::FormatErrorMessage(keys::kLoadFileError,
218 WideToUTF8(resource_.relative_path().value()));
219 #endif // OS_WIN
220 SendResponse(false);
221 }
222 }
223
224 bool ExecuteCodeInTabFunction::Execute(const std::string& code_string) {
225 content::WebContents* contents = NULL;
226 Browser* browser = NULL;
227
228 bool success = ExtensionTabUtil::GetTabById(
229 execute_tab_id_, profile(), include_incognito(), &browser, NULL,
230 &contents, NULL) && contents && browser;
231
232 if (!success)
233 return false;
234
235 const extensions::Extension* extension = GetExtension();
236 if (!extension)
237 return false;
238
239 ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT;
240 std::string function_name = name();
241 if (function_name == TabsInsertCSSFunction::function_name()) {
242 script_type = ScriptExecutor::CSS;
243 } else if (function_name != TabsExecuteScriptFunction::function_name()) {
244 NOTREACHED();
245 }
246
247 ScriptExecutor::FrameScope frame_scope =
248 details_->all_frames.get() && *details_->all_frames ?
249 ScriptExecutor::ALL_FRAMES :
250 ScriptExecutor::TOP_FRAME;
251
252 UserScript::RunLocation run_at = UserScript::UNDEFINED;
253 switch (details_->run_at) {
254 case InjectDetails::RUN_AT_NONE:
255 case InjectDetails::RUN_AT_DOCUMENT_IDLE:
256 run_at = UserScript::DOCUMENT_IDLE;
257 break;
258 case InjectDetails::RUN_AT_DOCUMENT_START:
259 run_at = UserScript::DOCUMENT_START;
260 break;
261 case InjectDetails::RUN_AT_DOCUMENT_END:
262 run_at = UserScript::DOCUMENT_END;
263 break;
264 }
265 CHECK_NE(UserScript::UNDEFINED, run_at);
266
267 extensions::TabHelper::FromWebContents(contents)->
268 script_executor()->ExecuteScript(
269 extension->id(),
270 script_type,
271 code_string,
272 frame_scope,
273 run_at,
274 ScriptExecutor::ISOLATED_WORLD,
275 base::Bind(&ExecuteCodeInTabFunction::OnExecuteCodeFinished, this));
276 return true;
277 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h ('k') | chrome/browser/extensions/api/tabs/tabs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698