1 // Copyright (c) 2011 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 #ifndef CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__ 6 #define CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__ 7 #pragma once 8 9 #include <map> 10 #include <string> 11 #include <vector> 12 13 #include "app/sql/init_status.h" 14 #include "base/file_path.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/synchronization/lock.h" 17 #ifdef ANDROID 18 // TODO(kristianm): Quick upstream 19 #include "base/task.h" 20 #include "base/time.h" 21 #endif 22 #include "chrome/browser/search_engines/template_url_id.h" 23 #ifndef ANDROID 24 #include "content/browser/browser_thread.h" 25 #endif 26 #ifdef ANDROID 27 #include "third_party/skia/include/core/SkBitmap.h" 28 #endif 29 30 class AutofillChange; 31 class AutofillProfile; 32 class CreditCard; 33 class GURL; 34 #if defined(OS_WIN) 35 struct IE7PasswordInfo; 36 #endif 37 class MessageLoop; 38 class SkBitmap; 39 class Task; 40 class TemplateURL; 41 class WebDatabase; 42 43 namespace base { 44 class Thread; 45 } 46 47 namespace webkit_glue { 48 struct FormField; 49 struct PasswordForm; 50 } 51 52 //////////////////////////////////////////////////////////////////////////////// 53 // 54 // WebDataService is a generic data repository for meta data associated with 55 // web pages. All data is retrieved and archived in an asynchronous way. 56 // 57 // All requests return a handle. The handle can be used to cancel the request. 58 // 59 //////////////////////////////////////////////////////////////////////////////// 60 61 62 //////////////////////////////////////////////////////////////////////////////// 63 // 64 // WebDataService results 65 // 66 //////////////////////////////////////////////////////////////////////////////// 67 68 // 69 // Result types 70 // 71 typedef enum { 72 BOOL_RESULT = 1, // WDResult<bool> 73 KEYWORDS_RESULT, // WDResult<WDKeywordsResult> 74 INT64_RESULT, // WDResult<int64> 75 PASSWORD_RESULT, // WDResult<std::vector<PasswordForm*>> 76 #if defined(OS_WIN) 77 PASSWORD_IE7_RESULT, // WDResult<IE7PasswordInfo> 78 #endif 79 WEB_APP_IMAGES, // WDResult<WDAppImagesResult> 80 TOKEN_RESULT, // WDResult<std::vector<std::string>> 81 AUTOFILL_VALUE_RESULT, // WDResult<std::vector<string16>> 82 AUTOFILL_CHANGES, // WDResult<std::vector<AutofillChange>> 83 AUTOFILL_PROFILE_RESULT, // WDResult<AutofillProfile> 84 AUTOFILL_PROFILES_RESULT, // WDResult<std::vector<AutofillProfile*>> 85 AUTOFILL_CREDITCARD_RESULT, // WDResult<CreditCard> 86 AUTOFILL_CREDITCARDS_RESULT // WDResult<std::vector<CreditCard*>> 87 } WDResultType; 88 89 typedef std::vector<AutofillChange> AutofillChangeList; 90 91 // Result from GetWebAppImages. 92 struct WDAppImagesResult { 93 WDAppImagesResult(); 94 ~WDAppImagesResult(); 95 96 // True if SetWebAppHasAllImages(true) was invoked. 97 bool has_all_images; 98 99 // The images, may be empty. 100 std::vector<SkBitmap> images; 101 }; 102 103 struct WDKeywordsResult { 104 WDKeywordsResult(); 105 ~WDKeywordsResult(); 106 107 std::vector<TemplateURL*> keywords; 108 // Identifies the ID of the TemplateURL that is the default search. A value of 109 // 0 indicates there is no default search provider. 110 int64 default_search_provider_id; 111 // Version of the built-in keywords. A value of 0 indicates a first run. 112 int builtin_keyword_version; 113 }; 114 115 // 116 // The top level class for a result. 117 // 118 class WDTypedResult { 119 public: ~WDTypedResult()120 virtual ~WDTypedResult() {} 121 122 // Return the result type. GetType()123 WDResultType GetType() const { 124 return type_; 125 } 126 127 protected: WDTypedResult(WDResultType type)128 explicit WDTypedResult(WDResultType type) : type_(type) { 129 } 130 131 private: 132 WDResultType type_; 133 DISALLOW_COPY_AND_ASSIGN(WDTypedResult); 134 }; 135 136 // A result containing one specific pointer or literal value. 137 template <class T> class WDResult : public WDTypedResult { 138 public: 139 WDResult(WDResultType type,const T & v)140 WDResult(WDResultType type, const T& v) : WDTypedResult(type), value_(v) { 141 } 142 ~WDResult()143 virtual ~WDResult() { 144 } 145 146 // Return a single value result. GetValue()147 T GetValue() const { 148 return value_; 149 } 150 151 private: 152 T value_; 153 154 DISALLOW_COPY_AND_ASSIGN(WDResult); 155 }; 156 157 template <class T> class WDObjectResult : public WDTypedResult { 158 public: WDObjectResult(WDResultType type)159 explicit WDObjectResult(WDResultType type) : WDTypedResult(type) { 160 } 161 GetValue()162 T* GetValue() const { 163 return &value_; 164 } 165 166 private: 167 // mutable to keep GetValue() const. 168 mutable T value_; 169 DISALLOW_COPY_AND_ASSIGN(WDObjectResult); 170 }; 171 172 class WebDataServiceConsumer; 173 174 class WebDataService 175 : public base::RefCountedThreadSafe<WebDataService 176 #ifndef ANDROID 177 , BrowserThread::DeleteOnUIThread 178 #endif 179 > { 180 public: 181 // All requests return an opaque handle of the following type. 182 typedef int Handle; 183 184 ////////////////////////////////////////////////////////////////////////////// 185 // 186 // Internal requests 187 // 188 // Every request is processed using a request object. The object contains 189 // both the request parameters and the results. 190 ////////////////////////////////////////////////////////////////////////////// 191 class WebDataRequest { 192 public: 193 WebDataRequest(WebDataService* service, 194 Handle handle, 195 WebDataServiceConsumer* consumer); 196 197 virtual ~WebDataRequest(); 198 199 Handle GetHandle() const; 200 WebDataServiceConsumer* GetConsumer() const; 201 bool IsCancelled() const; 202 203 // This can be invoked from any thread. From this point we assume that 204 // our consumer_ reference is invalid. 205 void Cancel(); 206 207 // Invoked by the service when this request has been completed. 208 // This will notify the service in whatever thread was used to create this 209 // request. 210 void RequestComplete(); 211 212 // The result is owned by the request. 213 void SetResult(WDTypedResult* r); 214 const WDTypedResult* GetResult() const; 215 216 private: 217 scoped_refptr<WebDataService> service_; 218 MessageLoop* message_loop_; 219 Handle handle_; 220 bool canceled_; 221 WebDataServiceConsumer* consumer_; 222 WDTypedResult* result_; 223 224 DISALLOW_COPY_AND_ASSIGN(WebDataRequest); 225 }; 226 227 // 228 // Internally we use instances of the following template to represent 229 // requests. 230 // 231 template <class T> 232 class GenericRequest : public WebDataRequest { 233 public: GenericRequest(WebDataService * service,Handle handle,WebDataServiceConsumer * consumer,const T & arg)234 GenericRequest(WebDataService* service, 235 Handle handle, 236 WebDataServiceConsumer* consumer, 237 const T& arg) 238 : WebDataRequest(service, handle, consumer), 239 arg_(arg) { 240 } 241 ~GenericRequest()242 virtual ~GenericRequest() { 243 } 244 GetArgument()245 T GetArgument() { 246 return arg_; 247 } 248 249 private: 250 T arg_; 251 }; 252 253 template <class T, class U> 254 class GenericRequest2 : public WebDataRequest { 255 public: GenericRequest2(WebDataService * service,Handle handle,WebDataServiceConsumer * consumer,const T & arg1,const U & arg2)256 GenericRequest2(WebDataService* service, 257 Handle handle, 258 WebDataServiceConsumer* consumer, 259 const T& arg1, 260 const U& arg2) 261 : WebDataRequest(service, handle, consumer), 262 arg1_(arg1), 263 arg2_(arg2) { 264 } 265 ~GenericRequest2()266 virtual ~GenericRequest2() { } 267 GetArgument1()268 T GetArgument1() { 269 return arg1_; 270 } 271 GetArgument2()272 U GetArgument2() { 273 return arg2_; 274 } 275 276 private: 277 T arg1_; 278 U arg2_; 279 }; 280 281 WebDataService(); 282 283 // Initializes the web data service. Returns false on failure 284 // Takes the path of the profile directory as its argument. 285 bool Init(const FilePath& profile_path); 286 287 // Shutdown the web data service. The service can no longer be used after this 288 // call. 289 void Shutdown(); 290 291 // Returns false if Shutdown() has been called. 292 bool IsRunning() const; 293 294 // Unloads the database without actually shutting down the service. This can 295 // be used to temporarily reduce the browser process' memory footprint. 296 void UnloadDatabase(); 297 298 // Cancel any pending request. You need to call this method if your 299 // WebDataServiceConsumer is about to be deleted. 300 void CancelRequest(Handle h); 301 302 virtual bool IsDatabaseLoaded(); 303 virtual WebDatabase* GetDatabase(); 304 305 ////////////////////////////////////////////////////////////////////////////// 306 // 307 // Keywords 308 // 309 ////////////////////////////////////////////////////////////////////////////// 310 311 // As the database processes requests at a later date, all deletion is 312 // done on the background thread. 313 // 314 // Many of the keyword related methods do not return a handle. This is because 315 // the caller (TemplateURLModel) does not need to know when the request is 316 // done. 317 void AddKeyword(const TemplateURL& url); 318 319 void RemoveKeyword(const TemplateURL& url); 320 321 void UpdateKeyword(const TemplateURL& url); 322 323 // Fetches the keywords. 324 // On success, consumer is notified with WDResult<std::vector<TemplateURL*>. 325 Handle GetKeywords(WebDataServiceConsumer* consumer); 326 327 // Sets the keywords used for the default search provider. 328 void SetDefaultSearchProvider(const TemplateURL* url); 329 330 // Sets the version of the builtin keywords. 331 void SetBuiltinKeywordVersion(int version); 332 333 ////////////////////////////////////////////////////////////////////////////// 334 // 335 // Web Apps 336 // 337 ////////////////////////////////////////////////////////////////////////////// 338 339 // Sets the image for the specified web app. A web app can have any number of 340 // images, but only one at a particular size. If there was an image for the 341 // web app at the size of the given image it is replaced. 342 void SetWebAppImage(const GURL& app_url, const SkBitmap& image); 343 344 // Sets whether all the images have been downloaded for the specified web app. 345 void SetWebAppHasAllImages(const GURL& app_url, bool has_all_images); 346 347 // Removes all images for the specified web app. 348 void RemoveWebApp(const GURL& app_url); 349 350 // Fetches the images and whether all images have been downloaded for the 351 // specified web app. 352 Handle GetWebAppImages(const GURL& app_url, WebDataServiceConsumer* consumer); 353 354 ////////////////////////////////////////////////////////////////////////////// 355 // 356 // Token Service 357 // 358 ////////////////////////////////////////////////////////////////////////////// 359 360 // Set a token to use for a specified service. 361 void SetTokenForService(const std::string& service, 362 const std::string& token); 363 364 // Remove all tokens stored in the web database. 365 void RemoveAllTokens(); 366 367 // Null on failure. Success is WDResult<std::vector<std::string> > 368 Handle GetAllTokens(WebDataServiceConsumer* consumer); 369 370 ////////////////////////////////////////////////////////////////////////////// 371 // 372 // Password manager 373 // NOTE: These methods are all deprecated; new clients should use 374 // PasswordStore. These are only still here because Windows is (temporarily) 375 // still using them for its PasswordStore implementation. 376 // 377 ////////////////////////////////////////////////////////////////////////////// 378 379 // Adds |form| to the list of remembered password forms. 380 void AddLogin(const webkit_glue::PasswordForm& form); 381 382 // Updates the remembered password form. 383 void UpdateLogin(const webkit_glue::PasswordForm& form); 384 385 // Removes |form| from the list of remembered password forms. 386 void RemoveLogin(const webkit_glue::PasswordForm& form); 387 388 // Removes all logins created in the specified daterange 389 void RemoveLoginsCreatedBetween(const base::Time& delete_begin, 390 const base::Time& delete_end); 391 392 // Removes all logins created on or after the date passed in. 393 void RemoveLoginsCreatedAfter(const base::Time& delete_begin); 394 395 // Gets a list of password forms that match |form|. 396 // |consumer| will be notified when the request is done. The result is of 397 // type WDResult<std::vector<PasswordForm*>>. 398 // The result will be null on failure. The |consumer| owns all PasswordForm's. 399 Handle GetLogins(const webkit_glue::PasswordForm& form, 400 WebDataServiceConsumer* consumer); 401 402 // Gets the complete list of password forms that have not been blacklisted and 403 // are thus auto-fillable. 404 // |consumer| will be notified when the request is done. The result is of 405 // type WDResult<std::vector<PasswordForm*>>. 406 // The result will be null on failure. The |consumer| owns all PasswordForms. 407 Handle GetAutofillableLogins(WebDataServiceConsumer* consumer); 408 409 // Gets the complete list of password forms that have been blacklisted. 410 // |consumer| will be notified when the request is done. The result is of 411 // type WDResult<std::vector<PasswordForm*>>. 412 // The result will be null on failure. The |consumer| owns all PasswordForm's. 413 Handle GetBlacklistLogins(WebDataServiceConsumer* consumer); 414 415 #if defined(OS_WIN) 416 // Adds |info| to the list of imported passwords from ie7/ie8. 417 void AddIE7Login(const IE7PasswordInfo& info); 418 419 // Removes |info| from the list of imported passwords from ie7/ie8. 420 void RemoveIE7Login(const IE7PasswordInfo& info); 421 422 // Get the login matching the information in |info|. |consumer| will be 423 // notified when the request is done. The result is of type 424 // WDResult<IE7PasswordInfo>. 425 // If there is no match, the fields of the IE7PasswordInfo will be empty. 426 Handle GetIE7Login(const IE7PasswordInfo& info, 427 WebDataServiceConsumer* consumer); 428 #endif // defined(OS_WIN) 429 430 ////////////////////////////////////////////////////////////////////////////// 431 // 432 // Autofill. 433 // 434 ////////////////////////////////////////////////////////////////////////////// 435 436 // Schedules a task to add form fields to the web database. 437 virtual void AddFormFields(const std::vector<webkit_glue::FormField>& fields); 438 439 // Initiates the request for a vector of values which have been entered in 440 // form input fields named |name|. The method OnWebDataServiceRequestDone of 441 // |consumer| gets called back when the request is finished, with the vector 442 // included in the argument |result|. 443 Handle GetFormValuesForElementName(const string16& name, 444 const string16& prefix, 445 int limit, 446 WebDataServiceConsumer* consumer); 447 448 // Removes form elements recorded for Autocomplete from the database. 449 void RemoveFormElementsAddedBetween(const base::Time& delete_begin, 450 const base::Time& delete_end); 451 void RemoveFormValueForElementName(const string16& name, 452 const string16& value); 453 454 // Schedules a task to add an Autofill profile to the web database. 455 void AddAutofillProfile(const AutofillProfile& profile); 456 457 // Schedules a task to update an Autofill profile in the web database. 458 void UpdateAutofillProfile(const AutofillProfile& profile); 459 460 // Schedules a task to remove an Autofill profile from the web database. 461 // |guid| is the identifer of the profile to remove. 462 void RemoveAutofillProfile(const std::string& guid); 463 464 // Initiates the request for all Autofill profiles. The method 465 // OnWebDataServiceRequestDone of |consumer| gets called when the request is 466 // finished, with the profiles included in the argument |result|. The 467 // consumer owns the profiles. 468 Handle GetAutofillProfiles(WebDataServiceConsumer* consumer); 469 470 // Remove "trashed" profile guids from the web database and optionally send 471 // notifications to tell Sync that the items have been removed. 472 void EmptyMigrationTrash(bool notify_sync); 473 474 // Schedules a task to add credit card to the web database. 475 void AddCreditCard(const CreditCard& credit_card); 476 477 // Schedules a task to update credit card in the web database. 478 void UpdateCreditCard(const CreditCard& credit_card); 479 480 // Schedules a task to remove a credit card from the web database. 481 // |guid| is identifer of the credit card to remove. 482 void RemoveCreditCard(const std::string& guid); 483 484 // Initiates the request for all credit cards. The method 485 // OnWebDataServiceRequestDone of |consumer| gets called when the request is 486 // finished, with the credit cards included in the argument |result|. The 487 // consumer owns the credit cards. 488 Handle GetCreditCards(WebDataServiceConsumer* consumer); 489 490 // Removes Autofill records from the database. 491 void RemoveAutofillProfilesAndCreditCardsModifiedBetween( 492 const base::Time& delete_begin, 493 const base::Time& delete_end); 494 495 // Testing 496 #ifdef UNIT_TEST set_failed_init(bool value)497 void set_failed_init(bool value) { failed_init_ = value; } 498 #endif 499 500 protected: 501 friend class TemplateURLModelTest; 502 friend class TemplateURLModelTestingProfile; 503 friend class WebDataServiceTest; 504 friend class WebDataRequest; 505 506 virtual ~WebDataService(); 507 508 // This is invoked by the unit test; path is the path of the Web Data file. 509 bool InitWithPath(const FilePath& path); 510 511 // Invoked by request implementations when a request has been processed. 512 void RequestCompleted(Handle h); 513 514 // Register the request as a pending request. 515 void RegisterRequest(WebDataRequest* request); 516 517 ////////////////////////////////////////////////////////////////////////////// 518 // 519 // The following methods are only invoked in the web data service thread. 520 // 521 ////////////////////////////////////////////////////////////////////////////// 522 private: 523 #ifndef ANDROID 524 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 525 #endif 526 friend class DeleteTask<WebDataService>; 527 friend class ShutdownTask; 528 529 typedef GenericRequest2<std::vector<const TemplateURL*>, 530 std::vector<TemplateURL*> > SetKeywordsRequest; 531 532 // Invoked on the main thread if initializing the db fails. 533 void DBInitFailed(sql::InitStatus init_status); 534 535 // Initialize the database, if it hasn't already been initialized. 536 void InitializeDatabaseIfNecessary(); 537 538 // The notification method. 539 void NotifyDatabaseLoadedOnUIThread(); 540 541 // Commit any pending transaction and deletes the database. 542 void ShutdownDatabase(); 543 544 // Commit the current transaction and creates a new one. 545 void Commit(); 546 547 // Schedule a task on our worker thread. 548 void ScheduleTask(Task* t); 549 550 // Schedule a commit if one is not already pending. 551 void ScheduleCommit(); 552 553 // Return the next request handle. 554 int GetNextRequestHandle(); 555 556 ////////////////////////////////////////////////////////////////////////////// 557 // 558 // Keywords. 559 // 560 ////////////////////////////////////////////////////////////////////////////// 561 void AddKeywordImpl(GenericRequest<TemplateURL>* request); 562 void RemoveKeywordImpl(GenericRequest<TemplateURLID>* request); 563 void UpdateKeywordImpl(GenericRequest<TemplateURL>* request); 564 void GetKeywordsImpl(WebDataRequest* request); 565 void SetDefaultSearchProviderImpl(GenericRequest<TemplateURLID>* r); 566 void SetBuiltinKeywordVersionImpl(GenericRequest<int>* r); 567 568 ////////////////////////////////////////////////////////////////////////////// 569 // 570 // Web Apps. 571 // 572 ////////////////////////////////////////////////////////////////////////////// 573 void SetWebAppImageImpl(GenericRequest2<GURL, SkBitmap>* request); 574 void SetWebAppHasAllImagesImpl(GenericRequest2<GURL, bool>* request); 575 void RemoveWebAppImpl(GenericRequest<GURL>* request); 576 void GetWebAppImagesImpl(GenericRequest<GURL>* request); 577 578 ////////////////////////////////////////////////////////////////////////////// 579 // 580 // Token Service. 581 // 582 ////////////////////////////////////////////////////////////////////////////// 583 584 void RemoveAllTokensImpl(GenericRequest<std::string>* request); 585 void SetTokenForServiceImpl( 586 GenericRequest2<std::string, std::string>* request); 587 void GetAllTokensImpl(GenericRequest<std::string>* request); 588 589 ////////////////////////////////////////////////////////////////////////////// 590 // 591 // Password manager. 592 // 593 ////////////////////////////////////////////////////////////////////////////// 594 void AddLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request); 595 void UpdateLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request); 596 void RemoveLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request); 597 void RemoveLoginsCreatedBetweenImpl( 598 GenericRequest2<base::Time, base::Time>* request); 599 void GetLoginsImpl(GenericRequest<webkit_glue::PasswordForm>* request); 600 void GetAutofillableLoginsImpl(WebDataRequest* request); 601 void GetBlacklistLoginsImpl(WebDataRequest* request); 602 #if defined(OS_WIN) 603 void AddIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request); 604 void RemoveIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request); 605 void GetIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request); 606 #endif // defined(OS_WIN) 607 608 ////////////////////////////////////////////////////////////////////////////// 609 // 610 // Autofill. 611 // 612 ////////////////////////////////////////////////////////////////////////////// 613 void AddFormElementsImpl( 614 GenericRequest<std::vector<webkit_glue::FormField> >* request); 615 void GetFormValuesForElementNameImpl(WebDataRequest* request, 616 const string16& name, const string16& prefix, int limit); 617 void RemoveFormElementsAddedBetweenImpl( 618 GenericRequest2<base::Time, base::Time>* request); 619 void RemoveFormValueForElementNameImpl( 620 GenericRequest2<string16, string16>* request); 621 void AddAutofillProfileImpl(GenericRequest<AutofillProfile>* request); 622 void UpdateAutofillProfileImpl(GenericRequest<AutofillProfile>* request); 623 void RemoveAutofillProfileImpl(GenericRequest<std::string>* request); 624 void GetAutofillProfilesImpl(WebDataRequest* request); 625 void EmptyMigrationTrashImpl(GenericRequest<bool>* request); 626 void AddCreditCardImpl(GenericRequest<CreditCard>* request); 627 void UpdateCreditCardImpl(GenericRequest<CreditCard>* request); 628 void RemoveCreditCardImpl(GenericRequest<std::string>* request); 629 void GetCreditCardsImpl(WebDataRequest* request); 630 void RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl( 631 GenericRequest2<base::Time, base::Time>* request); 632 633 // True once initialization has started. 634 bool is_running_; 635 636 // The path with which to initialize the database. 637 FilePath path_; 638 639 // Our database. 640 WebDatabase* db_; 641 642 // Whether the database failed to initialize. We use this to avoid 643 // continually trying to reinit. 644 bool failed_init_; 645 646 // Whether we should commit the database. 647 bool should_commit_; 648 649 // A lock to protect pending requests and next request handle. 650 base::Lock pending_lock_; 651 652 // Next handle to be used for requests. Incremented for each use. 653 Handle next_request_handle_; 654 655 typedef std::map<Handle, WebDataRequest*> RequestMap; 656 RequestMap pending_requests_; 657 658 // MessageLoop the WebDataService is created on. 659 MessageLoop* main_loop_; 660 661 DISALLOW_COPY_AND_ASSIGN(WebDataService); 662 }; 663 664 //////////////////////////////////////////////////////////////////////////////// 665 // 666 // WebDataServiceConsumer. 667 // 668 // All requests to the web data service are asynchronous. When the request has 669 // been performed, the data consumer is notified using the following interface. 670 // 671 //////////////////////////////////////////////////////////////////////////////// 672 673 class WebDataServiceConsumer { 674 public: 675 676 // Called when a request is done. h uniquely identifies the request. 677 // result can be NULL, if no result is expected or if the database could 678 // not be opened. The result object is destroyed after this call. 679 virtual void OnWebDataServiceRequestDone(WebDataService::Handle h, 680 const WDTypedResult* result) = 0; 681 682 protected: 683 virtual ~WebDataServiceConsumer() {} 684 }; 685 686 #endif // CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__ 687