blob: ce8536ebbe2b865c01abe9c8da228d6c659881cc [file] [log] [blame]
// 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 <map>
#include <memory>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.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 ShortcutsBackend;
class TemplateURLService;
struct TestShortcutData;
void PopulateShortcutsBackendWithTestData(
scoped_refptr<ShortcutsBackend> backend,
TestShortcutData* db,
size_t db_size);
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<base::string16, const ShortcutsDatabase::Shortcut>
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,
std::unique_ptr<SearchTermsData> search_terms_data,
history::HistoryService* history_service,
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<ShortcutsBackend>;
friend class ShortcutsBackendTest;
friend void PopulateShortcutsBackendWithTestData(
scoped_refptr<ShortcutsBackend> backend,
TestShortcutData* db,
size_t db_size);
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<std::string, ShortcutMap::iterator> 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<GURL>& 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_;
std::unique_ptr<SearchTermsData> search_terms_data_;
CurrentState current_state_;
base::ObserverList<ShortcutsBackendObserver> observer_list_;
scoped_refptr<ShortcutsDatabase> db_;
// The |temp_shortcuts_map_| and |temp_guid_map_| used for temporary storage
// between InitInternal() and InitComplete() to avoid doing a potentially huge
// copy.
std::unique_ptr<ShortcutMap> temp_shortcuts_map_;
std::unique_ptr<GuidMap> temp_guid_map_;
ShortcutMap shortcuts_map_;
// This is a helper map for quick access to a shortcut by guid.
GuidMap guid_map_;
ScopedObserver<history::HistoryService, history::HistoryServiceObserver>
history_service_observer_;
scoped_refptr<base::SequencedTaskRunner> main_runner_;
scoped_refptr<base::SequencedTaskRunner> db_runner_;
// For some unit-test only.
bool no_db_access_;
DISALLOW_COPY_AND_ASSIGN(ShortcutsBackend);
};
#endif // COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_BACKEND_H_