C++程序  |  687行  |  22.87 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__
#define CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__
#pragma once

#include <map>
#include <string>
#include <vector>

#include "app/sql/init_status.h"
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#ifdef ANDROID
// TODO(kristianm): Quick upstream
#include "base/task.h"
#include "base/time.h"
#endif
#include "chrome/browser/search_engines/template_url_id.h"
#ifndef ANDROID
#include "content/browser/browser_thread.h"
#endif
#ifdef ANDROID
#include "third_party/skia/include/core/SkBitmap.h"
#endif

class AutofillChange;
class AutofillProfile;
class CreditCard;
class GURL;
#if defined(OS_WIN)
struct IE7PasswordInfo;
#endif
class MessageLoop;
class SkBitmap;
class Task;
class TemplateURL;
class WebDatabase;

namespace base {
class Thread;
}

namespace webkit_glue {
struct FormField;
struct PasswordForm;
}

////////////////////////////////////////////////////////////////////////////////
//
// WebDataService is a generic data repository for meta data associated with
// web pages. All data is retrieved and archived in an asynchronous way.
//
// All requests return a handle. The handle can be used to cancel the request.
//
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
//
// WebDataService results
//
////////////////////////////////////////////////////////////////////////////////

//
// Result types
//
typedef enum {
  BOOL_RESULT = 1,             // WDResult<bool>
  KEYWORDS_RESULT,             // WDResult<WDKeywordsResult>
  INT64_RESULT,                // WDResult<int64>
  PASSWORD_RESULT,             // WDResult<std::vector<PasswordForm*>>
#if defined(OS_WIN)
  PASSWORD_IE7_RESULT,         // WDResult<IE7PasswordInfo>
#endif
  WEB_APP_IMAGES,              // WDResult<WDAppImagesResult>
  TOKEN_RESULT,                // WDResult<std::vector<std::string>>
  AUTOFILL_VALUE_RESULT,       // WDResult<std::vector<string16>>
  AUTOFILL_CHANGES,            // WDResult<std::vector<AutofillChange>>
  AUTOFILL_PROFILE_RESULT,     // WDResult<AutofillProfile>
  AUTOFILL_PROFILES_RESULT,    // WDResult<std::vector<AutofillProfile*>>
  AUTOFILL_CREDITCARD_RESULT,  // WDResult<CreditCard>
  AUTOFILL_CREDITCARDS_RESULT  // WDResult<std::vector<CreditCard*>>
} WDResultType;

typedef std::vector<AutofillChange> AutofillChangeList;

// Result from GetWebAppImages.
struct WDAppImagesResult {
  WDAppImagesResult();
  ~WDAppImagesResult();

  // True if SetWebAppHasAllImages(true) was invoked.
  bool has_all_images;

  // The images, may be empty.
  std::vector<SkBitmap> images;
};

struct WDKeywordsResult {
  WDKeywordsResult();
  ~WDKeywordsResult();

  std::vector<TemplateURL*> keywords;
  // Identifies the ID of the TemplateURL that is the default search. A value of
  // 0 indicates there is no default search provider.
  int64 default_search_provider_id;
  // Version of the built-in keywords. A value of 0 indicates a first run.
  int builtin_keyword_version;
};

//
// The top level class for a result.
//
class WDTypedResult {
 public:
  virtual ~WDTypedResult() {}

  // Return the result type.
  WDResultType GetType() const {
    return type_;
  }

 protected:
  explicit WDTypedResult(WDResultType type) : type_(type) {
  }

 private:
  WDResultType type_;
  DISALLOW_COPY_AND_ASSIGN(WDTypedResult);
};

// A result containing one specific pointer or literal value.
template <class T> class WDResult : public WDTypedResult {
 public:

  WDResult(WDResultType type, const T& v) : WDTypedResult(type), value_(v) {
  }

  virtual ~WDResult() {
  }

  // Return a single value result.
  T GetValue() const {
    return value_;
  }

 private:
  T value_;

  DISALLOW_COPY_AND_ASSIGN(WDResult);
};

template <class T> class WDObjectResult : public WDTypedResult {
 public:
  explicit WDObjectResult(WDResultType type) : WDTypedResult(type) {
  }

  T* GetValue() const {
    return &value_;
  }

 private:
  // mutable to keep GetValue() const.
  mutable T value_;
  DISALLOW_COPY_AND_ASSIGN(WDObjectResult);
};

class WebDataServiceConsumer;

class WebDataService
    : public base::RefCountedThreadSafe<WebDataService
#ifndef ANDROID
                                        , BrowserThread::DeleteOnUIThread
#endif
                                       > {
 public:
  // All requests return an opaque handle of the following type.
  typedef int Handle;

  //////////////////////////////////////////////////////////////////////////////
  //
  // Internal requests
  //
  // Every request is processed using a request object. The object contains
  // both the request parameters and the results.
  //////////////////////////////////////////////////////////////////////////////
  class WebDataRequest {
   public:
    WebDataRequest(WebDataService* service,
                   Handle handle,
                   WebDataServiceConsumer* consumer);

    virtual ~WebDataRequest();

    Handle GetHandle() const;
    WebDataServiceConsumer* GetConsumer() const;
    bool IsCancelled() const;

    // This can be invoked from any thread. From this point we assume that
    // our consumer_ reference is invalid.
    void Cancel();

    // Invoked by the service when this request has been completed.
    // This will notify the service in whatever thread was used to create this
    // request.
    void RequestComplete();

    // The result is owned by the request.
    void SetResult(WDTypedResult* r);
    const WDTypedResult* GetResult() const;

   private:
    scoped_refptr<WebDataService> service_;
    MessageLoop* message_loop_;
    Handle handle_;
    bool canceled_;
    WebDataServiceConsumer* consumer_;
    WDTypedResult* result_;

    DISALLOW_COPY_AND_ASSIGN(WebDataRequest);
  };

  //
  // Internally we use instances of the following template to represent
  // requests.
  //
  template <class T>
  class GenericRequest : public WebDataRequest {
   public:
    GenericRequest(WebDataService* service,
                   Handle handle,
                   WebDataServiceConsumer* consumer,
                   const T& arg)
        : WebDataRequest(service, handle, consumer),
          arg_(arg) {
    }

    virtual ~GenericRequest() {
    }

    T GetArgument() {
      return arg_;
    }

   private:
    T arg_;
  };

  template <class T, class U>
  class GenericRequest2 : public WebDataRequest {
   public:
    GenericRequest2(WebDataService* service,
                    Handle handle,
                    WebDataServiceConsumer* consumer,
                    const T& arg1,
                    const U& arg2)
        : WebDataRequest(service, handle, consumer),
          arg1_(arg1),
          arg2_(arg2) {
    }

    virtual ~GenericRequest2() { }

    T GetArgument1() {
      return arg1_;
    }

    U GetArgument2() {
      return arg2_;
    }

   private:
    T arg1_;
    U arg2_;
  };

  WebDataService();

  // Initializes the web data service. Returns false on failure
  // Takes the path of the profile directory as its argument.
  bool Init(const FilePath& profile_path);

  // Shutdown the web data service. The service can no longer be used after this
  // call.
  void Shutdown();

  // Returns false if Shutdown() has been called.
  bool IsRunning() const;

  // Unloads the database without actually shutting down the service.  This can
  // be used to temporarily reduce the browser process' memory footprint.
  void UnloadDatabase();

  // Cancel any pending request. You need to call this method if your
  // WebDataServiceConsumer is about to be deleted.
  void CancelRequest(Handle h);

  virtual bool IsDatabaseLoaded();
  virtual WebDatabase* GetDatabase();

  //////////////////////////////////////////////////////////////////////////////
  //
  // Keywords
  //
  //////////////////////////////////////////////////////////////////////////////

  // As the database processes requests at a later date, all deletion is
  // done on the background thread.
  //
  // Many of the keyword related methods do not return a handle. This is because
  // the caller (TemplateURLModel) does not need to know when the request is
  // done.
  void AddKeyword(const TemplateURL& url);

  void RemoveKeyword(const TemplateURL& url);

  void UpdateKeyword(const TemplateURL& url);

  // Fetches the keywords.
  // On success, consumer is notified with WDResult<std::vector<TemplateURL*>.
  Handle GetKeywords(WebDataServiceConsumer* consumer);

  // Sets the keywords used for the default search provider.
  void SetDefaultSearchProvider(const TemplateURL* url);

  // Sets the version of the builtin keywords.
  void SetBuiltinKeywordVersion(int version);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Web Apps
  //
  //////////////////////////////////////////////////////////////////////////////

  // Sets the image for the specified web app. A web app can have any number of
  // images, but only one at a particular size. If there was an image for the
  // web app at the size of the given image it is replaced.
  void SetWebAppImage(const GURL& app_url, const SkBitmap& image);

  // Sets whether all the images have been downloaded for the specified web app.
  void SetWebAppHasAllImages(const GURL& app_url, bool has_all_images);

  // Removes all images for the specified web app.
  void RemoveWebApp(const GURL& app_url);

  // Fetches the images and whether all images have been downloaded for the
  // specified web app.
  Handle GetWebAppImages(const GURL& app_url, WebDataServiceConsumer* consumer);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Token Service
  //
  //////////////////////////////////////////////////////////////////////////////

  // Set a token to use for a specified service.
  void SetTokenForService(const std::string& service,
                          const std::string& token);

  // Remove all tokens stored in the web database.
  void RemoveAllTokens();

  // Null on failure. Success is WDResult<std::vector<std::string> >
  Handle GetAllTokens(WebDataServiceConsumer* consumer);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Password manager
  // NOTE: These methods are all deprecated; new clients should use
  // PasswordStore. These are only still here because Windows is (temporarily)
  // still using them for its PasswordStore implementation.
  //
  //////////////////////////////////////////////////////////////////////////////

  // Adds |form| to the list of remembered password forms.
  void AddLogin(const webkit_glue::PasswordForm& form);

  // Updates the remembered password form.
  void UpdateLogin(const webkit_glue::PasswordForm& form);

  // Removes |form| from the list of remembered password forms.
  void RemoveLogin(const webkit_glue::PasswordForm& form);

  // Removes all logins created in the specified daterange
  void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
                                  const base::Time& delete_end);

  // Removes all logins created on or after the date passed in.
  void RemoveLoginsCreatedAfter(const base::Time& delete_begin);

  // Gets a list of password forms that match |form|.
  // |consumer| will be notified when the request is done. The result is of
  // type WDResult<std::vector<PasswordForm*>>.
  // The result will be null on failure. The |consumer| owns all PasswordForm's.
  Handle GetLogins(const webkit_glue::PasswordForm& form,
                   WebDataServiceConsumer* consumer);

  // Gets the complete list of password forms that have not been blacklisted and
  // are thus auto-fillable.
  // |consumer| will be notified when the request is done. The result is of
  // type WDResult<std::vector<PasswordForm*>>.
  // The result will be null on failure.  The |consumer| owns all PasswordForms.
  Handle GetAutofillableLogins(WebDataServiceConsumer* consumer);

  // Gets the complete list of password forms that have been blacklisted.
  // |consumer| will be notified when the request is done. The result is of
  // type WDResult<std::vector<PasswordForm*>>.
  // The result will be null on failure. The |consumer| owns all PasswordForm's.
  Handle GetBlacklistLogins(WebDataServiceConsumer* consumer);

#if defined(OS_WIN)
  // Adds |info| to the list of imported passwords from ie7/ie8.
  void AddIE7Login(const IE7PasswordInfo& info);

  // Removes |info| from the list of imported passwords from ie7/ie8.
  void RemoveIE7Login(const IE7PasswordInfo& info);

  // Get the login matching the information in |info|. |consumer| will be
  // notified when the request is done. The result is of type
  // WDResult<IE7PasswordInfo>.
  // If there is no match, the fields of the IE7PasswordInfo will be empty.
  Handle GetIE7Login(const IE7PasswordInfo& info,
                     WebDataServiceConsumer* consumer);
#endif  // defined(OS_WIN)

  //////////////////////////////////////////////////////////////////////////////
  //
  // Autofill.
  //
  //////////////////////////////////////////////////////////////////////////////

  // Schedules a task to add form fields to the web database.
  virtual void AddFormFields(const std::vector<webkit_glue::FormField>& fields);

  // Initiates the request for a vector of values which have been entered in
  // form input fields named |name|.  The method OnWebDataServiceRequestDone of
  // |consumer| gets called back when the request is finished, with the vector
  // included in the argument |result|.
  Handle GetFormValuesForElementName(const string16& name,
                                     const string16& prefix,
                                     int limit,
                                     WebDataServiceConsumer* consumer);

  // Removes form elements recorded for Autocomplete from the database.
  void RemoveFormElementsAddedBetween(const base::Time& delete_begin,
                                      const base::Time& delete_end);
  void RemoveFormValueForElementName(const string16& name,
                                     const string16& value);

  // Schedules a task to add an Autofill profile to the web database.
  void AddAutofillProfile(const AutofillProfile& profile);

  // Schedules a task to update an Autofill profile in the web database.
  void UpdateAutofillProfile(const AutofillProfile& profile);

  // Schedules a task to remove an Autofill profile from the web database.
  // |guid| is the identifer of the profile to remove.
  void RemoveAutofillProfile(const std::string& guid);

  // Initiates the request for all Autofill profiles.  The method
  // OnWebDataServiceRequestDone of |consumer| gets called when the request is
  // finished, with the profiles included in the argument |result|.  The
  // consumer owns the profiles.
  Handle GetAutofillProfiles(WebDataServiceConsumer* consumer);

  // Remove "trashed" profile guids from the web database and optionally send
  // notifications to tell Sync that the items have been removed.
  void EmptyMigrationTrash(bool notify_sync);

  // Schedules a task to add credit card to the web database.
  void AddCreditCard(const CreditCard& credit_card);

  // Schedules a task to update credit card in the web database.
  void UpdateCreditCard(const CreditCard& credit_card);

  // Schedules a task to remove a credit card from the web database.
  // |guid| is identifer of the credit card to remove.
  void RemoveCreditCard(const std::string& guid);

  // Initiates the request for all credit cards.  The method
  // OnWebDataServiceRequestDone of |consumer| gets called when the request is
  // finished, with the credit cards included in the argument |result|.  The
  // consumer owns the credit cards.
  Handle GetCreditCards(WebDataServiceConsumer* consumer);

  // Removes Autofill records from the database.
  void RemoveAutofillProfilesAndCreditCardsModifiedBetween(
      const base::Time& delete_begin,
      const base::Time& delete_end);

  // Testing
#ifdef UNIT_TEST
  void set_failed_init(bool value) { failed_init_ = value; }
#endif

 protected:
  friend class TemplateURLModelTest;
  friend class TemplateURLModelTestingProfile;
  friend class WebDataServiceTest;
  friend class WebDataRequest;

  virtual ~WebDataService();

  // This is invoked by the unit test; path is the path of the Web Data file.
  bool InitWithPath(const FilePath& path);

  // Invoked by request implementations when a request has been processed.
  void RequestCompleted(Handle h);

  // Register the request as a pending request.
  void RegisterRequest(WebDataRequest* request);

  //////////////////////////////////////////////////////////////////////////////
  //
  // The following methods are only invoked in the web data service thread.
  //
  //////////////////////////////////////////////////////////////////////////////
 private:
#ifndef ANDROID
  friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
#endif
  friend class DeleteTask<WebDataService>;
  friend class ShutdownTask;

  typedef GenericRequest2<std::vector<const TemplateURL*>,
                          std::vector<TemplateURL*> > SetKeywordsRequest;

  // Invoked on the main thread if initializing the db fails.
  void DBInitFailed(sql::InitStatus init_status);

  // Initialize the database, if it hasn't already been initialized.
  void InitializeDatabaseIfNecessary();

  // The notification method.
  void NotifyDatabaseLoadedOnUIThread();

  // Commit any pending transaction and deletes the database.
  void ShutdownDatabase();

  // Commit the current transaction and creates a new one.
  void Commit();

  // Schedule a task on our worker thread.
  void ScheduleTask(Task* t);

  // Schedule a commit if one is not already pending.
  void ScheduleCommit();

  // Return the next request handle.
  int GetNextRequestHandle();

  //////////////////////////////////////////////////////////////////////////////
  //
  // Keywords.
  //
  //////////////////////////////////////////////////////////////////////////////
  void AddKeywordImpl(GenericRequest<TemplateURL>* request);
  void RemoveKeywordImpl(GenericRequest<TemplateURLID>* request);
  void UpdateKeywordImpl(GenericRequest<TemplateURL>* request);
  void GetKeywordsImpl(WebDataRequest* request);
  void SetDefaultSearchProviderImpl(GenericRequest<TemplateURLID>* r);
  void SetBuiltinKeywordVersionImpl(GenericRequest<int>* r);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Web Apps.
  //
  //////////////////////////////////////////////////////////////////////////////
  void SetWebAppImageImpl(GenericRequest2<GURL, SkBitmap>* request);
  void SetWebAppHasAllImagesImpl(GenericRequest2<GURL, bool>* request);
  void RemoveWebAppImpl(GenericRequest<GURL>* request);
  void GetWebAppImagesImpl(GenericRequest<GURL>* request);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Token Service.
  //
  //////////////////////////////////////////////////////////////////////////////

  void RemoveAllTokensImpl(GenericRequest<std::string>* request);
  void SetTokenForServiceImpl(
    GenericRequest2<std::string, std::string>* request);
  void GetAllTokensImpl(GenericRequest<std::string>* request);

  //////////////////////////////////////////////////////////////////////////////
  //
  // Password manager.
  //
  //////////////////////////////////////////////////////////////////////////////
  void AddLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request);
  void UpdateLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request);
  void RemoveLoginImpl(GenericRequest<webkit_glue::PasswordForm>* request);
  void RemoveLoginsCreatedBetweenImpl(
      GenericRequest2<base::Time, base::Time>* request);
  void GetLoginsImpl(GenericRequest<webkit_glue::PasswordForm>* request);
  void GetAutofillableLoginsImpl(WebDataRequest* request);
  void GetBlacklistLoginsImpl(WebDataRequest* request);
#if defined(OS_WIN)
  void AddIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request);
  void RemoveIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request);
  void GetIE7LoginImpl(GenericRequest<IE7PasswordInfo>* request);
#endif  // defined(OS_WIN)

  //////////////////////////////////////////////////////////////////////////////
  //
  // Autofill.
  //
  //////////////////////////////////////////////////////////////////////////////
  void AddFormElementsImpl(
      GenericRequest<std::vector<webkit_glue::FormField> >* request);
  void GetFormValuesForElementNameImpl(WebDataRequest* request,
      const string16& name, const string16& prefix, int limit);
  void RemoveFormElementsAddedBetweenImpl(
      GenericRequest2<base::Time, base::Time>* request);
  void RemoveFormValueForElementNameImpl(
      GenericRequest2<string16, string16>* request);
  void AddAutofillProfileImpl(GenericRequest<AutofillProfile>* request);
  void UpdateAutofillProfileImpl(GenericRequest<AutofillProfile>* request);
  void RemoveAutofillProfileImpl(GenericRequest<std::string>* request);
  void GetAutofillProfilesImpl(WebDataRequest* request);
  void EmptyMigrationTrashImpl(GenericRequest<bool>* request);
  void AddCreditCardImpl(GenericRequest<CreditCard>* request);
  void UpdateCreditCardImpl(GenericRequest<CreditCard>* request);
  void RemoveCreditCardImpl(GenericRequest<std::string>* request);
  void GetCreditCardsImpl(WebDataRequest* request);
  void RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
      GenericRequest2<base::Time, base::Time>* request);

  // True once initialization has started.
  bool is_running_;

  // The path with which to initialize the database.
  FilePath path_;

  // Our database.
  WebDatabase* db_;

  // Whether the database failed to initialize.  We use this to avoid
  // continually trying to reinit.
  bool failed_init_;

  // Whether we should commit the database.
  bool should_commit_;

  // A lock to protect pending requests and next request handle.
  base::Lock pending_lock_;

  // Next handle to be used for requests. Incremented for each use.
  Handle next_request_handle_;

  typedef std::map<Handle, WebDataRequest*> RequestMap;
  RequestMap pending_requests_;

  // MessageLoop the WebDataService is created on.
  MessageLoop* main_loop_;

  DISALLOW_COPY_AND_ASSIGN(WebDataService);
};

////////////////////////////////////////////////////////////////////////////////
//
// WebDataServiceConsumer.
//
// All requests to the web data service are asynchronous. When the request has
// been performed, the data consumer is notified using the following interface.
//
////////////////////////////////////////////////////////////////////////////////

class WebDataServiceConsumer {
 public:

  // Called when a request is done. h uniquely identifies the request.
  // result can be NULL, if no result is expected or if the database could
  // not be opened. The result object is destroyed after this call.
  virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
                                           const WDTypedResult* result) = 0;

 protected:
  virtual ~WebDataServiceConsumer() {}
};

#endif  // CHROME_BROWSER_WEBDATA_WEB_DATA_SERVICE_H__