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 13using base::WaitableEvent; 14using content::BrowserThread; 15 16namespace { 17 18// Callback to handle database error. It seems chrome uses this to 19// display an error dialog box only. 20void DatabaseErrorCallback(sql::InitStatus status) { 21 LOG(WARNING) << "initializing autocomplete database failed"; 22} 23 24} // namespace 25 26namespace android_webview { 27 28AwFormDatabaseService::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 46AwFormDatabaseService::~AwFormDatabaseService() { 47 Shutdown(); 48} 49 50void 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 60scoped_refptr<autofill::AutofillWebDataService> 61AwFormDatabaseService::get_autofill_webdata_service() { 62 return autofill_data_; 63} 64 65void AwFormDatabaseService::ClearFormData() { 66 BrowserThread::PostTask( 67 BrowserThread::DB, 68 FROM_HERE, 69 base::Bind(&AwFormDatabaseService::ClearFormDataImpl, 70 base::Unretained(this))); 71} 72 73void 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 80bool 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 94void 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 105void 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