1 // Copyright (c) 2013 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/webview/webview_api.h"
6
7 #include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
8 #include "chrome/browser/extensions/tab_helper.h"
9 #include "chrome/common/extensions/api/webview.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/storage_partition.h"
13 #include "content/public/browser/web_contents.h"
14 #include "extensions/common/error_utils.h"
15
16 using content::WebContents;
17 using extensions::api::tabs::InjectDetails;
18 using extensions::api::webview::SetPermission::Params;
19 namespace webview = extensions::api::webview;
20
21 namespace extensions {
22
23 namespace {
MaskForKey(const char * key)24 int MaskForKey(const char* key) {
25 if (strcmp(key, extension_browsing_data_api_constants::kAppCacheKey) == 0)
26 return content::StoragePartition::REMOVE_DATA_MASK_APPCACHE;
27 if (strcmp(key, extension_browsing_data_api_constants::kCookiesKey) == 0)
28 return content::StoragePartition::REMOVE_DATA_MASK_COOKIES;
29 if (strcmp(key, extension_browsing_data_api_constants::kFileSystemsKey) == 0)
30 return content::StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
31 if (strcmp(key, extension_browsing_data_api_constants::kIndexedDBKey) == 0)
32 return content::StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
33 if (strcmp(key, extension_browsing_data_api_constants::kLocalStorageKey) == 0)
34 return content::StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
35 if (strcmp(key, extension_browsing_data_api_constants::kWebSQLKey) == 0)
36 return content::StoragePartition::REMOVE_DATA_MASK_WEBSQL;
37 return 0;
38 }
39
40 } // namespace
41
RunImpl()42 bool WebviewExtensionFunction::RunImpl() {
43 int instance_id = 0;
44 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id));
45 WebViewGuest* guest = WebViewGuest::From(
46 render_view_host()->GetProcess()->GetID(), instance_id);
47 if (!guest)
48 return false;
49
50 return RunImplSafe(guest);
51 }
52
WebviewClearDataFunction()53 WebviewClearDataFunction::WebviewClearDataFunction()
54 : remove_mask_(0),
55 bad_message_(false) {
56 };
57
~WebviewClearDataFunction()58 WebviewClearDataFunction::~WebviewClearDataFunction() {
59 };
60
61 // Parses the |dataToRemove| argument to generate the remove mask. Sets
62 // |bad_message_| (like EXTENSION_FUNCTION_VALIDATE would if this were a bool
63 // method) if 'dataToRemove' is not present.
GetRemovalMask()64 uint32 WebviewClearDataFunction::GetRemovalMask() {
65 base::DictionaryValue* data_to_remove;
66 if (!args_->GetDictionary(2, &data_to_remove)) {
67 bad_message_ = true;
68 return 0;
69 }
70
71 uint32 remove_mask = 0;
72 for (base::DictionaryValue::Iterator i(*data_to_remove);
73 !i.IsAtEnd();
74 i.Advance()) {
75 bool selected = false;
76 if (!i.value().GetAsBoolean(&selected)) {
77 bad_message_ = true;
78 return 0;
79 }
80 if (selected)
81 remove_mask |= MaskForKey(i.key().c_str());
82 }
83
84 return remove_mask;
85 }
86
87 // TODO(lazyboy): Parameters in this extension function are similar (or a
88 // sub-set) to BrowsingDataRemoverFunction. How can we share this code?
RunImplSafe(WebViewGuest * guest)89 bool WebviewClearDataFunction::RunImplSafe(WebViewGuest* guest) {
90 // Grab the initial |options| parameter, and parse out the arguments.
91 base::DictionaryValue* options;
92 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options));
93 DCHECK(options);
94
95 // If |ms_since_epoch| isn't set, default it to 0.
96 double ms_since_epoch;
97 if (!options->GetDouble(extension_browsing_data_api_constants::kSinceKey,
98 &ms_since_epoch)) {
99 ms_since_epoch = 0;
100 }
101
102 // base::Time takes a double that represents seconds since epoch. JavaScript
103 // gives developers milliseconds, so do a quick conversion before populating
104 // the object. Also, Time::FromDoubleT converts double time 0 to empty Time
105 // object. So we need to do special handling here.
106 remove_since_ = (ms_since_epoch == 0) ?
107 base::Time::UnixEpoch() :
108 base::Time::FromDoubleT(ms_since_epoch / 1000.0);
109
110 remove_mask_ = GetRemovalMask();
111 if (bad_message_)
112 return false;
113
114 AddRef(); // Balanced below or in WebviewClearDataFunction::Done().
115
116 bool scheduled = false;
117 if (remove_mask_) {
118 scheduled = guest->ClearData(
119 remove_since_,
120 remove_mask_,
121 base::Bind(&WebviewClearDataFunction::ClearDataDone,
122 this));
123 }
124 if (!remove_mask_ || !scheduled) {
125 SendResponse(false);
126 Release(); // Balanced above.
127 return false;
128 }
129
130 // Will finish asynchronously.
131 return true;
132 }
133
ClearDataDone()134 void WebviewClearDataFunction::ClearDataDone() {
135 Release(); // Balanced in RunImpl().
136 SendResponse(true);
137 }
138
WebviewExecuteCodeFunction()139 WebviewExecuteCodeFunction::WebviewExecuteCodeFunction()
140 : guest_instance_id_(0) {
141 }
142
~WebviewExecuteCodeFunction()143 WebviewExecuteCodeFunction::~WebviewExecuteCodeFunction() {
144 }
145
Init()146 bool WebviewExecuteCodeFunction::Init() {
147 if (details_.get())
148 return true;
149
150 if (!args_->GetInteger(0, &guest_instance_id_))
151 return false;
152
153 if (!guest_instance_id_)
154 return false;
155
156 base::DictionaryValue* details_value = NULL;
157 if (!args_->GetDictionary(1, &details_value))
158 return false;
159 scoped_ptr<InjectDetails> details(new InjectDetails());
160 if (!InjectDetails::Populate(*details_value, details.get()))
161 return false;
162
163 details_ = details.Pass();
164 return true;
165 }
166
ShouldInsertCSS() const167 bool WebviewExecuteCodeFunction::ShouldInsertCSS() const {
168 return false;
169 }
170
CanExecuteScriptOnPage()171 bool WebviewExecuteCodeFunction::CanExecuteScriptOnPage() {
172 return true;
173 }
174
GetScriptExecutor()175 extensions::ScriptExecutor* WebviewExecuteCodeFunction::GetScriptExecutor() {
176 WebViewGuest* guest = WebViewGuest::From(
177 render_view_host()->GetProcess()->GetID(), guest_instance_id_);
178 if (!guest)
179 return NULL;
180
181 return guest->script_executor();
182 }
183
IsWebView() const184 bool WebviewExecuteCodeFunction::IsWebView() const {
185 return true;
186 }
187
WebviewExecuteScriptFunction()188 WebviewExecuteScriptFunction::WebviewExecuteScriptFunction() {
189 }
190
OnExecuteCodeFinished(const std::string & error,int32 on_page_id,const GURL & on_url,const base::ListValue & result)191 void WebviewExecuteScriptFunction::OnExecuteCodeFinished(
192 const std::string& error,
193 int32 on_page_id,
194 const GURL& on_url,
195 const base::ListValue& result) {
196 if (error.empty())
197 SetResult(result.DeepCopy());
198 WebviewExecuteCodeFunction::OnExecuteCodeFinished(error, on_page_id, on_url,
199 result);
200 }
201
WebviewInsertCSSFunction()202 WebviewInsertCSSFunction::WebviewInsertCSSFunction() {
203 }
204
ShouldInsertCSS() const205 bool WebviewInsertCSSFunction::ShouldInsertCSS() const {
206 return true;
207 }
208
WebviewCaptureVisibleRegionFunction()209 WebviewCaptureVisibleRegionFunction::WebviewCaptureVisibleRegionFunction() {
210 }
211
~WebviewCaptureVisibleRegionFunction()212 WebviewCaptureVisibleRegionFunction::~WebviewCaptureVisibleRegionFunction() {
213 }
214
IsScreenshotEnabled()215 bool WebviewCaptureVisibleRegionFunction::IsScreenshotEnabled() {
216 return true;
217 }
218
GetWebContentsForID(int instance_id)219 WebContents* WebviewCaptureVisibleRegionFunction::GetWebContentsForID(
220 int instance_id) {
221 WebViewGuest* guest = WebViewGuest::From(
222 render_view_host()->GetProcess()->GetID(), instance_id);
223 return guest ? guest->guest_web_contents() : NULL;
224 }
225
OnCaptureFailure(FailureReason reason)226 void WebviewCaptureVisibleRegionFunction::OnCaptureFailure(
227 FailureReason reason) {
228 SendResponse(false);
229 }
230
WebviewGoFunction()231 WebviewGoFunction::WebviewGoFunction() {
232 }
233
~WebviewGoFunction()234 WebviewGoFunction::~WebviewGoFunction() {
235 }
236
RunImplSafe(WebViewGuest * guest)237 bool WebviewGoFunction::RunImplSafe(WebViewGuest* guest) {
238 scoped_ptr<webview::Go::Params> params(webview::Go::Params::Create(*args_));
239 EXTENSION_FUNCTION_VALIDATE(params.get());
240
241 guest->Go(params->relative_index);
242 return true;
243 }
244
WebviewReloadFunction()245 WebviewReloadFunction::WebviewReloadFunction() {
246 }
247
~WebviewReloadFunction()248 WebviewReloadFunction::~WebviewReloadFunction() {
249 }
250
RunImplSafe(WebViewGuest * guest)251 bool WebviewReloadFunction::RunImplSafe(WebViewGuest* guest) {
252 guest->Reload();
253 return true;
254 }
255
WebviewSetPermissionFunction()256 WebviewSetPermissionFunction::WebviewSetPermissionFunction() {
257 }
258
~WebviewSetPermissionFunction()259 WebviewSetPermissionFunction::~WebviewSetPermissionFunction() {
260 }
261
RunImplSafe(WebViewGuest * guest)262 bool WebviewSetPermissionFunction::RunImplSafe(WebViewGuest* guest) {
263 scoped_ptr<webview::SetPermission::Params> params(
264 webview::SetPermission::Params::Create(*args_));
265 EXTENSION_FUNCTION_VALIDATE(params.get());
266
267 WebViewGuest::PermissionResponseAction action = WebViewGuest::DEFAULT;
268 switch (params->action) {
269 case Params::ACTION_ALLOW:
270 action = WebViewGuest::ALLOW;
271 break;
272 case Params::ACTION_DENY:
273 action = WebViewGuest::DENY;
274 break;
275 case Params::ACTION_DEFAULT:
276 break;
277 default:
278 NOTREACHED();
279 }
280
281 std::string user_input;
282 if (params->user_input)
283 user_input = *params->user_input;
284
285 WebViewGuest::SetPermissionResult result =
286 guest->SetPermission(params->request_id, action, user_input);
287
288 EXTENSION_FUNCTION_VALIDATE(result != WebViewGuest::SET_PERMISSION_INVALID);
289
290 SetResult(base::Value::CreateBooleanValue(
291 result == WebViewGuest::SET_PERMISSION_ALLOWED));
292 SendResponse(true);
293 return true;
294 }
295
WebviewOverrideUserAgentFunction()296 WebviewOverrideUserAgentFunction::WebviewOverrideUserAgentFunction() {
297 }
298
~WebviewOverrideUserAgentFunction()299 WebviewOverrideUserAgentFunction::~WebviewOverrideUserAgentFunction() {
300 }
301
RunImplSafe(WebViewGuest * guest)302 bool WebviewOverrideUserAgentFunction::RunImplSafe(WebViewGuest* guest) {
303 scoped_ptr<extensions::api::webview::OverrideUserAgent::Params> params(
304 extensions::api::webview::OverrideUserAgent::Params::Create(*args_));
305 EXTENSION_FUNCTION_VALIDATE(params.get());
306
307 guest->SetUserAgentOverride(params->user_agent_override);
308 return true;
309 }
310
WebviewStopFunction()311 WebviewStopFunction::WebviewStopFunction() {
312 }
313
~WebviewStopFunction()314 WebviewStopFunction::~WebviewStopFunction() {
315 }
316
RunImplSafe(WebViewGuest * guest)317 bool WebviewStopFunction::RunImplSafe(WebViewGuest* guest) {
318 guest->Stop();
319 return true;
320 }
321
WebviewTerminateFunction()322 WebviewTerminateFunction::WebviewTerminateFunction() {
323 }
324
~WebviewTerminateFunction()325 WebviewTerminateFunction::~WebviewTerminateFunction() {
326 }
327
RunImplSafe(WebViewGuest * guest)328 bool WebviewTerminateFunction::RunImplSafe(WebViewGuest* guest) {
329 guest->Terminate();
330 return true;
331 }
332
333 } // namespace extensions
334