Home | History | Annotate | Download | only in webview
      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