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     Shortcut(const std::string& id,
     40              const string16& text,
     41              const GURL& url,
     42              const string16& contents,
     43              const ACMatchClassifications& contents_class,
     44              const string16& description,
     45              const ACMatchClassifications& description_class,
     46              const base::Time& last_access_time,
     47              int number_of_hits);
     48     // Required for STL, we don't use this directly.
     49     Shortcut();
     50     ~Shortcut();
     51 
     52     std::string id;  // Unique guid for the shortcut.
     53     string16 text;   // The user's original input string.
     54     GURL url;        // The corresponding destination URL.
     55 
     56     // Contents and description from the original match, along with their
     57     // corresponding markup. We need these in order to correctly mark which
     58     // parts are URLs, dim, etc. However, we strip all MATCH classifications
     59     // from these since we'll mark the matching portions ourselves as we match
     60     // the user's current typing against these Shortcuts.
     61     string16 contents;
     62     ACMatchClassifications contents_class;
     63     string16 description;
     64     ACMatchClassifications description_class;
     65 
     66     base::Time last_access_time;  // Last time shortcut was selected.
     67     int number_of_hits;           // How many times shortcut was selected.
     68   };
     69 
     70   typedef std::multimap<string16, ShortcutsBackend::Shortcut> ShortcutMap;
     71 
     72   // |profile| is necessary for profile notifications only and can be NULL in
     73   // unit-tests. For unit testing, set |suppress_db| to true to prevent creation
     74   // of the database, in which case all operations are performed in memory only.
     75   ShortcutsBackend(Profile* profile, bool suppress_db);
     76 
     77   // The interface is guaranteed to be called on the thread AddObserver()
     78   // was called.
     79   class ShortcutsBackendObserver {
     80    public:
     81     // Called after the database is loaded and Init() completed.
     82     virtual void OnShortcutsLoaded() = 0;
     83     // Called when shortcuts changed (added/updated/removed) in the database.
     84     virtual void OnShortcutsChanged() {}
     85 
     86    protected:
     87     virtual ~ShortcutsBackendObserver() {}
     88   };
     89 
     90   // Asynchronously initializes the ShortcutsBackend, it is safe to call
     91   // multiple times - only the first call will be processed.
     92   bool Init();
     93 
     94   bool initialized() const { return current_state_ == INITIALIZED; }
     95 
     96   // All of the public functions *must* be called on UI thread only!
     97 
     98   // Adds the Shortcut to the database.
     99   bool AddShortcut(const ShortcutsBackend::Shortcut& shortcut);
    100 
    101   // Updates timing and selection count for the Shortcut.
    102   bool UpdateShortcut(const ShortcutsBackend::Shortcut& shortcut);
    103 
    104   // Deletes the Shortcuts with the id.
    105   bool DeleteShortcutsWithIds(const std::vector<std::string>& shortcut_ids);
    106 
    107   // Deletes the Shortcuts with the url.
    108   bool DeleteShortcutsWithUrl(const GURL& shortcut_url);
    109 
    110   // Deletes all of the shortcuts.
    111   bool DeleteAllShortcuts();
    112 
    113   const ShortcutMap& shortcuts_map() const {
    114     return shortcuts_map_;
    115   }
    116 
    117   void AddObserver(ShortcutsBackendObserver* obs) {
    118     observer_list_.AddObserver(obs);
    119   }
    120 
    121   void RemoveObserver(ShortcutsBackendObserver* obs) {
    122     observer_list_.RemoveObserver(obs);
    123   }
    124 
    125  private:
    126   friend class base::RefCountedThreadSafe<ShortcutsBackend>;
    127 
    128   typedef std::map<std::string, ShortcutMap::iterator>
    129       GuidToShortcutsIteratorMap;
    130 
    131   virtual ~ShortcutsBackend();
    132 
    133   // Internal initialization of the back-end. Posted by Init() to the DB thread.
    134   // On completion posts InitCompleted() back to UI thread.
    135   void InitInternal();
    136 
    137   // Finishes initialization on UI thread, notifies all observers.
    138   void InitCompleted();
    139 
    140   // content::NotificationObserver:
    141   virtual void Observe(int type,
    142                        const content::NotificationSource& source,
    143                        const content::NotificationDetails& details) OVERRIDE;
    144 
    145   // RefcountedBrowserContextKeyedService
    146   virtual void ShutdownOnUIThread() OVERRIDE;
    147 
    148   enum CurrentState {
    149     NOT_INITIALIZED,  // Backend created but not initialized.
    150     INITIALIZING,  // Init() called, but not completed yet.
    151     INITIALIZED,  // Initialization completed, all accessors can be safely
    152                   // called.
    153   };
    154 
    155   CurrentState current_state_;
    156   ObserverList<ShortcutsBackendObserver> observer_list_;
    157   scoped_refptr<ShortcutsDatabase> db_;
    158 
    159   // The |temp_shortcuts_map_| and |temp_guid_map_| used for temporary storage
    160   // between InitInternal() and InitComplete() to avoid doing a potentially huge
    161   // copy.
    162   scoped_ptr<ShortcutMap> temp_shortcuts_map_;
    163   scoped_ptr<GuidToShortcutsIteratorMap> temp_guid_map_;
    164 
    165   ShortcutMap shortcuts_map_;
    166   // This is a helper map for quick access to a shortcut by guid.
    167   GuidToShortcutsIteratorMap guid_map_;
    168 
    169   content::NotificationRegistrar notification_registrar_;
    170 
    171   // For some unit-test only.
    172   bool no_db_access_;
    173 
    174   DISALLOW_COPY_AND_ASSIGN(ShortcutsBackend);
    175 };
    176 
    177 }  // namespace history
    178 
    179 #endif  // CHROME_BROWSER_HISTORY_SHORTCUTS_BACKEND_H_
    180