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 16using content::WebContents; 17using extensions::api::tabs::InjectDetails; 18using extensions::api::webview::SetPermission::Params; 19namespace webview = extensions::api::webview; 20 21namespace extensions { 22 23namespace { 24int 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 42bool 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 53WebviewClearDataFunction::WebviewClearDataFunction() 54 : remove_mask_(0), 55 bad_message_(false) { 56}; 57 58WebviewClearDataFunction::~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. 64uint32 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? 89bool 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 134void WebviewClearDataFunction::ClearDataDone() { 135 Release(); // Balanced in RunImpl(). 136 SendResponse(true); 137} 138 139WebviewExecuteCodeFunction::WebviewExecuteCodeFunction() 140 : guest_instance_id_(0) { 141} 142 143WebviewExecuteCodeFunction::~WebviewExecuteCodeFunction() { 144} 145 146bool 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 167bool WebviewExecuteCodeFunction::ShouldInsertCSS() const { 168 return false; 169} 170 171bool WebviewExecuteCodeFunction::CanExecuteScriptOnPage() { 172 return true; 173} 174 175extensions::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 184bool WebviewExecuteCodeFunction::IsWebView() const { 185 return true; 186} 187 188WebviewExecuteScriptFunction::WebviewExecuteScriptFunction() { 189} 190 191void 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 202WebviewInsertCSSFunction::WebviewInsertCSSFunction() { 203} 204 205bool WebviewInsertCSSFunction::ShouldInsertCSS() const { 206 return true; 207} 208 209WebviewCaptureVisibleRegionFunction::WebviewCaptureVisibleRegionFunction() { 210} 211 212WebviewCaptureVisibleRegionFunction::~WebviewCaptureVisibleRegionFunction() { 213} 214 215bool WebviewCaptureVisibleRegionFunction::IsScreenshotEnabled() { 216 return true; 217} 218 219WebContents* 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 226void WebviewCaptureVisibleRegionFunction::OnCaptureFailure( 227 FailureReason reason) { 228 SendResponse(false); 229} 230 231WebviewGoFunction::WebviewGoFunction() { 232} 233 234WebviewGoFunction::~WebviewGoFunction() { 235} 236 237bool 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 245WebviewReloadFunction::WebviewReloadFunction() { 246} 247 248WebviewReloadFunction::~WebviewReloadFunction() { 249} 250 251bool WebviewReloadFunction::RunImplSafe(WebViewGuest* guest) { 252 guest->Reload(); 253 return true; 254} 255 256WebviewSetPermissionFunction::WebviewSetPermissionFunction() { 257} 258 259WebviewSetPermissionFunction::~WebviewSetPermissionFunction() { 260} 261 262bool 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 296WebviewOverrideUserAgentFunction::WebviewOverrideUserAgentFunction() { 297} 298 299WebviewOverrideUserAgentFunction::~WebviewOverrideUserAgentFunction() { 300} 301 302bool 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 311WebviewStopFunction::WebviewStopFunction() { 312} 313 314WebviewStopFunction::~WebviewStopFunction() { 315} 316 317bool WebviewStopFunction::RunImplSafe(WebViewGuest* guest) { 318 guest->Stop(); 319 return true; 320} 321 322WebviewTerminateFunction::WebviewTerminateFunction() { 323} 324 325WebviewTerminateFunction::~WebviewTerminateFunction() { 326} 327 328bool WebviewTerminateFunction::RunImplSafe(WebViewGuest* guest) { 329 guest->Terminate(); 330 return true; 331} 332 333} // namespace extensions 334