// Copyright (c) 2012 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 COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_BACKEND_H_ #define COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_BACKEND_H_ #include #include #include #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/scoped_observer.h" #include "base/sequenced_task_runner.h" #include "base/strings/string16.h" #include "base/synchronization/lock.h" #include "base/time/time.h" #include "components/history/core/browser/history_service_observer.h" #include "components/keyed_service/core/refcounted_keyed_service.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/shortcuts_database.h" #include "components/search_engines/search_terms_data.h" #include "url/gurl.h" class TemplateURLService; namespace history { class HistoryService; class ShortcutsDatabase; }; // namespace history // This class manages the shortcut provider backend - access to database on the // db thread, etc. class ShortcutsBackend : public RefcountedKeyedService, public history::HistoryServiceObserver { public: typedef std::multimap ShortcutMap; // For unit testing, set |suppress_db| to true to prevent creation // of the database, in which case all operations are performed in memory only. ShortcutsBackend(TemplateURLService* template_url_service, scoped_ptr search_terms_data, history::HistoryService* history_service, scoped_refptr db_runner, base::FilePath database_path, bool suppress_db); // The interface is guaranteed to be called on the thread AddObserver() // was called. class ShortcutsBackendObserver { public: // Called after the database is loaded and Init() completed. virtual void OnShortcutsLoaded() = 0; // Called when shortcuts changed (added/updated/removed) in the database. virtual void OnShortcutsChanged() {} protected: virtual ~ShortcutsBackendObserver() {} }; // Asynchronously initializes the ShortcutsBackend, it is safe to call // multiple times - only the first call will be processed. bool Init(); // All of the public functions *must* be called on UI thread only! bool initialized() const { return current_state_ == INITIALIZED; } const ShortcutMap& shortcuts_map() const { return shortcuts_map_; } // Deletes the Shortcuts with the url. bool DeleteShortcutsWithURL(const GURL& shortcut_url); // Deletes the Shortcuts that begin with the url. bool DeleteShortcutsBeginningWithURL(const GURL& shortcut_url); void AddObserver(ShortcutsBackendObserver* obs); void RemoveObserver(ShortcutsBackendObserver* obs); // Looks for an existing shortcut to match.destination_url that starts with // |text|. Updates that shortcut if found, otherwise adds a new shortcut. void AddOrUpdateShortcut(const base::string16& text, const AutocompleteMatch& match); private: friend class base::RefCountedThreadSafe; friend class ShortcutsProviderTest; friend class ShortcutsBackendTest; FRIEND_TEST_ALL_PREFIXES(ShortcutsBackendTest, EntitySuggestionTest); enum CurrentState { NOT_INITIALIZED, // Backend created but not initialized. INITIALIZING, // Init() called, but not completed yet. INITIALIZED, // Initialization completed, all accessors can be safely // called. }; typedef std::map GuidMap; ~ShortcutsBackend() override; static ShortcutsDatabase::Shortcut::MatchCore MatchToMatchCore( const AutocompleteMatch& match, TemplateURLService* template_url_service, SearchTermsData* search_terms_data); // RefcountedKeyedService: void ShutdownOnUIThread() override; // history::HistoryServiceObserver: void OnURLsDeleted(history::HistoryService* history_service, bool all_history, bool expired, const history::URLRows& deleted_rows, const std::set& favicon_urls) override; // Internal initialization of the back-end. Posted by Init() to the DB thread. // On completion posts InitCompleted() back to UI thread. void InitInternal(); // Finishes initialization on UI thread, notifies all observers. void InitCompleted(); // Adds the Shortcut to the database. bool AddShortcut(const ShortcutsDatabase::Shortcut& shortcut); // Updates timing and selection count for the Shortcut. bool UpdateShortcut(const ShortcutsDatabase::Shortcut& shortcut); // Deletes the Shortcuts with these IDs. bool DeleteShortcutsWithIDs( const ShortcutsDatabase::ShortcutIDs& shortcut_ids); // Deletes all shortcuts whose URLs begin with |url|. If |exact_match| is // true, only shortcuts from exactly |url| are deleted. bool DeleteShortcutsWithURL(const GURL& url, bool exact_match); // Deletes all of the shortcuts. bool DeleteAllShortcuts(); TemplateURLService* template_url_service_; scoped_ptr search_terms_data_; CurrentState current_state_; base::ObserverList observer_list_; scoped_refptr db_; // The |temp_shortcuts_map_| and |temp_guid_map_| used for temporary storage // between InitInternal() and InitComplete() to avoid doing a potentially huge // copy. scoped_ptr temp_shortcuts_map_; scoped_ptr temp_guid_map_; ShortcutMap shortcuts_map_; // This is a helper map for quick access to a shortcut by guid. GuidMap guid_map_; ScopedObserver history_service_observer_; scoped_refptr main_runner_; scoped_refptr db_runner_; // For some unit-test only. bool no_db_access_; DISALLOW_COPY_AND_ASSIGN(ShortcutsBackend); }; #endif // COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_BACKEND_H_