Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2012 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_HISTORY_SHORTCUTS_BACKEND_H_
      6 #define CHROME_BROWSER_HISTORY_SHORTCUTS_BACKEND_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/files/file_path.h"
     13 #include "base/gtest_prod_util.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/observer_list.h"
     17 #include "base/strings/string16.h"
     18 #include "base/synchronization/lock.h"
     19 #include "base/time/time.h"
     20 #include "chrome/browser/autocomplete/autocomplete_match.h"
     21 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.h"
     22 #include "content/public/browser/notification_observer.h"
     23 #include "content/public/browser/notification_registrar.h"
     24 #include "url/gurl.h"
     25 
     26 class Profile;
     27 
     28 namespace history {
     29 
     30 class ShortcutsDatabase;
     31 
     32 // This class manages the shortcut provider backend - access to database on the
     33 // db thread, etc.
     34 class ShortcutsBackend : public RefcountedBrowserContextKeyedService,
     35                          public content::NotificationObserver {
     36  public:
     37   // The following struct encapsulates one previously selected omnibox shortcut.
     38   struct Shortcut {
     39     // The pieces of an AutocompleteMatch that we preserve in a shortcut.
     40     struct MatchCore {
     41       explicit MatchCore(const AutocompleteMatch& match);
     42       MatchCore(const base::string16& fill_into_edit,
     43                 const GURL& destination_url,
     44                 const base::string16& contents,
     45                 const ACMatchClassifications& contents_class,
     46                 const base::string16& description,
     47                 const ACMatchClassifications& description_class,
     48                 content::PageTransition transition,
     49                 AutocompleteMatch::Type type,
     50                 const base::string16& keyword);
     51       ~MatchCore();
     52 
     53       AutocompleteMatch ToMatch() const;
     54 
     55       base::string16 fill_into_edit;
     56       GURL destination_url;
     57       base::string16 contents;
     58       // For both contents_class and description_class, we strip MATCH
     59       // classifications; the ShortcutsProvider will re-mark MATCH regions based
     60       // on the user's current typing.
     61       ACMatchClassifications contents_class;
     62       base::string16 description;
     63       ACMatchClassifications description_class;
     64       content::PageTransition transition;
     65       AutocompleteMatch::Type type;
     66       base::string16 keyword;
     67     };
     68 
     69     Shortcut(const std::string& id,
     70              const base::string16& text,
     71              const MatchCore& match_core,
     72              const base::Time& last_access_time,
     73              int number_of_hits);
     74     // Required for STL, we don't use this directly.
     75     Shortcut();
     76     ~Shortcut();
     77 
     78     std::string id;  // Unique guid for the shortcut.
     79     base::string16 text;   // The user's original input string.
     80     MatchCore match_core;
     81     base::Time last_access_time;  // Last time shortcut was selected.
     82     int number_of_hits;           // How many times shortcut was selected.
     83   };
     84 
     85   typedef std::multimap<base::string16, const Shortcut> ShortcutMap;
     86 
     87   // |profile| is necessary for profile notifications only and can be NULL in
     88   // unit-tests. For unit testing, set |suppress_db| to true to prevent creation
     89   // of the database, in which case all operations are performed in memory only.
     90   ShortcutsBackend(Profile* profile, bool suppress_db);
     91 
     92   // The interface is guaranteed to be called on the thread AddObserver()
     93   // was called.
     94   class ShortcutsBackendObserver {
     95    public:
     96     // Called after the database is loaded and Init() completed.
     97     virtual void OnShortcutsLoaded() = 0;
     98     // Called when shortcuts changed (added/updated/removed) in the database.
     99     virtual void OnShortcutsChanged() {}
    100 
    101    protected:
    102     virtual ~ShortcutsBackendObserver() {}
    103   };
    104 
    105   // Asynchronously initializes the ShortcutsBackend, it is safe to call
    106   // multiple times - only the first call will be processed.
    107   bool Init();
    108 
    109   // All of the public functions *must* be called on UI thread only!
    110 
    111   bool initialized() const { return current_state_ == INITIALIZED; }
    112   const ShortcutMap& shortcuts_map() const { return shortcuts_map_; }
    113 
    114   // Deletes the Shortcuts with the url.
    115   bool DeleteShortcutsWithUrl(const GURL& shortcut_url);
    116 
    117   void AddObserver(ShortcutsBackendObserver* obs);
    118   void RemoveObserver(ShortcutsBackendObserver* obs);
    119 
    120   // Looks for an existing shortcut to match.destination_url that starts with
    121   // |text|.  Updates that shortcut if found, otherwise adds a new shortcut.
    122   void AddOrUpdateShortcut(const base::string16& text,
    123                            const AutocompleteMatch& match);
    124 
    125  private:
    126   friend class base::RefCountedThreadSafe<ShortcutsBackend>;
    127   friend class ShortcutsProviderTest;
    128   FRIEND_TEST_ALL_PREFIXES(ShortcutsBackendTest, AddAndUpdateShortcut);
    129   FRIEND_TEST_ALL_PREFIXES(ShortcutsBackendTest, DeleteShortcuts);
    130 
    131   enum CurrentState {
    132     NOT_INITIALIZED,  // Backend created but not initialized.
    133     INITIALIZING,     // Init() called, but not completed yet.
    134     INITIALIZED,      // Initialization completed, all accessors can be safely
    135                       // called.
    136   };
    137 
    138   typedef std::map<std::string, ShortcutMap::iterator> GuidMap;
    139 
    140   virtual ~ShortcutsBackend();
    141 
    142   // RefcountedBrowserContextKeyedService:
    143   virtual void ShutdownOnUIThread() OVERRIDE;
    144 
    145   // content::NotificationObserver:
    146   virtual void Observe(int type,
    147                        const content::NotificationSource& source,
    148                        const content::NotificationDetails& details) OVERRIDE;
    149 
    150   // Internal initialization of the back-end. Posted by Init() to the DB thread.
    151   // On completion posts InitCompleted() back to UI thread.
    152   void InitInternal();
    153 
    154   // Finishes initialization on UI thread, notifies all observers.
    155   void InitCompleted();
    156 
    157   // Adds the Shortcut to the database.
    158   bool AddShortcut(const Shortcut& shortcut);
    159 
    160   // Updates timing and selection count for the Shortcut.
    161   bool UpdateShortcut(const Shortcut& shortcut);
    162 
    163   // Deletes the Shortcuts with the id.
    164   bool DeleteShortcutsWithIds(const std::vector<std::string>& shortcut_ids);
    165 
    166   // Deletes all shortcuts whose URLs begin with |url|.  If |exact_match| is
    167   // true, only shortcuts from exactly |url| are deleted.
    168   bool DeleteShortcutsWithUrl(const GURL& url, bool exact_match);
    169 
    170   // Deletes all of the shortcuts.
    171   bool DeleteAllShortcuts();
    172 
    173   CurrentState current_state_;
    174   ObserverList<ShortcutsBackendObserver> observer_list_;
    175   scoped_refptr<ShortcutsDatabase> db_;
    176 
    177   // The |temp_shortcuts_map_| and |temp_guid_map_| used for temporary storage
    178   // between InitInternal() and InitComplete() to avoid doing a potentially huge
    179   // copy.
    180   scoped_ptr<ShortcutMap> temp_shortcuts_map_;
    181   scoped_ptr<GuidMap> temp_guid_map_;
    182 
    183   ShortcutMap shortcuts_map_;
    184   // This is a helper map for quick access to a shortcut by guid.
    185   GuidMap guid_map_;
    186 
    187   content::NotificationRegistrar notification_registrar_;
    188 
    189   // For some unit-test only.
    190   bool no_db_access_;
    191 
    192   DISALLOW_COPY_AND_ASSIGN(ShortcutsBackend);
    193 };
    194 
    195 }  // namespace history
    196 
    197 #endif  // CHROME_BROWSER_HISTORY_SHORTCUTS_BACKEND_H_
    198