• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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