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