Home | History | Annotate | Download | only in browser
      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 "android_webview/browser/aw_form_database_service.h"
      6 #include "base/logging.h"
      7 #include "base/synchronization/waitable_event.h"
      8 #include "components/autofill/core/browser/webdata/autofill_table.h"
      9 #include "components/webdata/common/webdata_constants.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "ui/base/l10n/l10n_util_android.h"
     12 
     13 using base::WaitableEvent;
     14 using content::BrowserThread;
     15 
     16 namespace {
     17 
     18 // Callback to handle database error. It seems chrome uses this to
     19 // display an error dialog box only.
     20 void DatabaseErrorCallback(sql::InitStatus status) {
     21   LOG(WARNING) << "initializing autocomplete database failed";
     22 }
     23 
     24 }  // namespace
     25 
     26 namespace android_webview {
     27 
     28 AwFormDatabaseService::AwFormDatabaseService(const base::FilePath path) {
     29   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     30   web_database_ = new WebDatabaseService(path.Append(kWebDataFilename),
     31       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
     32       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
     33   web_database_->AddTable(
     34       scoped_ptr<WebDatabaseTable>(new autofill::AutofillTable(
     35           l10n_util::GetDefaultLocale())));
     36   web_database_->LoadDatabase();
     37 
     38   autofill_data_ = new autofill::AutofillWebDataService(
     39       web_database_,
     40       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
     41       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
     42       base::Bind(&DatabaseErrorCallback));
     43   autofill_data_->Init();
     44 }
     45 
     46 AwFormDatabaseService::~AwFormDatabaseService() {
     47   Shutdown();
     48 }
     49 
     50 void AwFormDatabaseService::Shutdown() {
     51   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     52   DCHECK(result_map_.empty());
     53   // TODO(sgurun) we don't run into this logic right now,
     54   // but if we do, then we need to implement cancellation
     55   // of pending queries.
     56   autofill_data_->ShutdownOnUIThread();
     57   web_database_->ShutdownDatabase();
     58 }
     59 
     60 scoped_refptr<autofill::AutofillWebDataService>
     61 AwFormDatabaseService::get_autofill_webdata_service() {
     62   return autofill_data_;
     63 }
     64 
     65 void AwFormDatabaseService::ClearFormData() {
     66   BrowserThread::PostTask(
     67       BrowserThread::DB,
     68       FROM_HERE,
     69       base::Bind(&AwFormDatabaseService::ClearFormDataImpl,
     70                  base::Unretained(this)));
     71 }
     72 
     73 void AwFormDatabaseService::ClearFormDataImpl() {
     74   base::Time begin;
     75   base::Time end = base::Time::Max();
     76   autofill_data_->RemoveFormElementsAddedBetween(begin, end);
     77   autofill_data_->RemoveAutofillDataModifiedBetween(begin, end);
     78 }
     79 
     80 bool AwFormDatabaseService::HasFormData() {
     81   WaitableEvent completion(false, false);
     82   bool result = false;
     83   BrowserThread::PostTask(
     84       BrowserThread::DB,
     85       FROM_HERE,
     86       base::Bind(&AwFormDatabaseService::HasFormDataImpl,
     87                  base::Unretained(this),
     88                  &completion,
     89                  &result));
     90   completion.Wait();
     91   return result;
     92 }
     93 
     94 void AwFormDatabaseService::HasFormDataImpl(
     95     WaitableEvent* completion,
     96     bool* result) {
     97   WebDataServiceBase::Handle pending_query_handle =
     98       autofill_data_->HasFormElements(this);
     99   PendingQuery query;
    100   query.result = result;
    101   query.completion = completion;
    102   result_map_[pending_query_handle] = query;
    103 }
    104 
    105 void AwFormDatabaseService::OnWebDataServiceRequestDone(
    106     WebDataServiceBase::Handle h,
    107     const WDTypedResult* result) {
    108 
    109   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
    110   bool has_form_data = false;
    111   if (result) {
    112     DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
    113     const WDResult<bool>* autofill_result =
    114         static_cast<const WDResult<bool>*>(result);
    115     has_form_data = autofill_result->GetValue();
    116   }
    117   QueryMap::const_iterator it = result_map_.find(h);
    118   if (it == result_map_.end()) {
    119     LOG(WARNING) << "Received unexpected callback from web data service";
    120     return;
    121   }
    122   *(it->second.result) = has_form_data;
    123   it->second.completion->Signal();
    124   result_map_.erase(h);
    125 }
    126 
    127 }  // namespace android_webview
    128