15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/autocomplete/shortcuts_backend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/guid.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/shortcuts_database.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/omnibox/omnibox_log.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/search_engines/template_url_service_factory.h" 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/search_engines/ui_thread_search_terms_data.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/common/chrome_constants.h" 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_input.h" 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match.h" 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match_type.h" 286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/autocomplete_result.h" 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/base_search_provider.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h" 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Takes Match classification vector and removes all matched positions, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compacting repetitions if necessary. 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)std::string StripMatchMarkers(const ACMatchClassifications& matches) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassifications unmatched; 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ACMatchClassifications::const_iterator i(matches.begin()); 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) i != matches.end(); ++i) { 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AutocompleteMatch::AddLastClassificationIfNecessary( 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &unmatched, i->offset, i->style & ~ACMatchClassification::MATCH); 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return AutocompleteMatch::ClassificationsToString(unmatched); 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Normally shortcuts have the same match type as the original match they were 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// created from, but for certain match types, we should modify the shortcut's 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// type slightly to reflect that the origin of the shortcut is historical. 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AutocompleteMatch::Type GetTypeForShortcut(AutocompleteMatch::Type type) { 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (type) { 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case AutocompleteMatchType::URL_WHAT_YOU_TYPED: 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case AutocompleteMatchType::NAVSUGGEST: 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case AutocompleteMatchType::NAVSUGGEST_PERSONALIZED: 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return AutocompleteMatchType::HISTORY_URL; 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case AutocompleteMatchType::SEARCH_OTHER_ENGINE: 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return type; 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return AutocompleteMatch::IsSearchType(type) ? 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AutocompleteMatchType::SEARCH_HISTORY : type; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ShortcutsBackend ----------------------------------------------------------- 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShortcutsBackend::ShortcutsBackend(Profile* profile, bool suppress_db) 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : profile_(profile), 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch current_state_(NOT_INITIALIZED), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) no_db_access_(suppress_db) { 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!suppress_db) { 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_ = new history::ShortcutsDatabase( 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) profile->GetPath().Append(chrome::kShortcutsDatabaseName)); 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |profile| can be NULL in tests. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile) { 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) notification_registrar_.Add( 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this, 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::Source<Profile>(profile)); 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) notification_registrar_.Add( 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::Source<Profile>(profile)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShortcutsBackend::Init() { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_state_ != NOT_INITIALIZED) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (no_db_access_) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_state_ = INITIALIZED; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_state_ = INITIALIZING; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ShortcutsBackend::InitInternal, this)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsBackend::DeleteShortcutsWithURL(const GURL& shortcut_url) { 11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return initialized() && DeleteShortcutsWithURL(shortcut_url, true); 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::AddObserver(ShortcutsBackendObserver* obs) { 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) observer_list_.AddObserver(obs); 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::RemoveObserver(ShortcutsBackendObserver* obs) { 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) observer_list_.RemoveObserver(obs); 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ShortcutsBackend::AddOrUpdateShortcut(const base::string16& text, 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const AutocompleteMatch& match) { 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16 text_lowercase(base::i18n::ToLower(text)); 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::Time now(base::Time::Now()); 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ShortcutMap::const_iterator it( 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shortcuts_map_.lower_bound(text_lowercase)); 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it != shortcuts_map_.end() && 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StartsWith(it->first, text_lowercase, true); ++it) { 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (match.destination_url == it->second.match_core.destination_url) { 13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UpdateShortcut(history::ShortcutsDatabase::Shortcut( 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it->second.id, text, MatchToMatchCore(match, profile_), now, 13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) it->second.number_of_hits + 1)); 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AddShortcut(history::ShortcutsDatabase::Shortcut( 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::GenerateGUID(), text, MatchToMatchCore(match, profile_), now, 1)); 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShortcutsBackend::~ShortcutsBackend() { 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)history::ShortcutsDatabase::Shortcut::MatchCore 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ShortcutsBackend::MatchToMatchCore(const AutocompleteMatch& match, 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Profile* profile) { 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const AutocompleteMatch::Type match_type = GetTypeForShortcut(match.type); 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TemplateURLService* service = 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TemplateURLServiceFactory::GetForProfile(profile); 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const AutocompleteMatch& normalized_match = 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AutocompleteMatch::IsSpecializedSearchType(match.type) ? 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BaseSearchProvider::CreateSearchSuggestion( 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch match.search_terms_args->search_terms, match_type, 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (match.transition == ui::PAGE_TRANSITION_KEYWORD), 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch match.GetTemplateURL(service, false), 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UIThreadSearchTermsData(profile)) : 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch match; 15923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return history::ShortcutsDatabase::Shortcut::MatchCore( 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch normalized_match.fill_into_edit, normalized_match.destination_url, 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch normalized_match.contents, 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StripMatchMarkers(normalized_match.contents_class), 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch normalized_match.description, 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StripMatchMarkers(normalized_match.description_class), 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch normalized_match.transition, match_type, normalized_match.keyword); 16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 16723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::ShutdownOnUIThread() { 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) || 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::UI)); 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) notification_registrar_.RemoveAll(); 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::Observe(int type, 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationSource& source, 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationDetails& details) { 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!initialized()) 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED) { 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // When an extension is unloaded, we want to remove any Shortcuts associated 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // with it. 18323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DeleteShortcutsWithURL(content::Details<extensions::UnloadedExtensionInfo>( 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) details)->extension->url(), false); 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(chrome::NOTIFICATION_HISTORY_URLS_DELETED, type); 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const history::URLsDeletedDetails* deleted_details = 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::Details<const history::URLsDeletedDetails>(details).ptr(); 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (deleted_details->all_history) { 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DeleteAllShortcuts(); 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const history::URLRows& rows(deleted_details->rows); 19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) history::ShortcutsDatabase::ShortcutIDs shortcut_ids; 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (GuidMap::const_iterator it(guid_map_.begin()); it != guid_map_.end(); 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ++it) { 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (std::find_if( 20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) rows.begin(), rows.end(), history::URLRow::URLRowHasURL( 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it->second->second.match_core.destination_url)) != rows.end()) 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shortcut_ids.push_back(it->first); 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DeleteShortcutsWithIDs(shortcut_ids); 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::InitInternal() { 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(current_state_ == INITIALIZING); 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) db_->Init(); 21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) history::ShortcutsDatabase::GuidToShortcutMap shortcuts; 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) db_->LoadShortcuts(&shortcuts); 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_shortcuts_map_.reset(new ShortcutMap); 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_guid_map_.reset(new GuidMap); 21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (history::ShortcutsDatabase::GuidToShortcutMap::const_iterator it( 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shortcuts.begin()); it != shortcuts.end(); ++it) { 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (*temp_guid_map_)[it->first] = temp_shortcuts_map_->insert( 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::make_pair(base::i18n::ToLower(it->second.text), it->second)); 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&ShortcutsBackend::InitCompleted, this)); 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsBackend::InitCompleted() { 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_guid_map_->swap(guid_map_); 2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_shortcuts_map_->swap(shortcuts_map_); 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_shortcuts_map_.reset(NULL); 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_guid_map_.reset(NULL); 2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) current_state_ = INITIALIZED; 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnShortcutsLoaded()); 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsBackend::AddShortcut( 23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const history::ShortcutsDatabase::Shortcut& shortcut) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized()) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(guid_map_.find(shortcut.id) == guid_map_.end()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guid_map_[shortcut.id] = shortcuts_map_.insert( 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::make_pair(base::i18n::ToLower(shortcut.text), shortcut)); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsChanged()); 24323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return no_db_access_ || 24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::PostTask( 24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(base::IgnoreResult( 24723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &history::ShortcutsDatabase::AddShortcut), 24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_.get(), shortcut)); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsBackend::UpdateShortcut( 25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const history::ShortcutsDatabase::Shortcut& shortcut) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized()) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GuidMap::iterator it(guid_map_.find(shortcut.id)); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != guid_map_.end()) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcuts_map_.erase(it->second); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guid_map_[shortcut.id] = shortcuts_map_.insert( 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::make_pair(base::i18n::ToLower(shortcut.text), shortcut)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsChanged()); 26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return no_db_access_ || 26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::PostTask( 26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(base::IgnoreResult( 26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &history::ShortcutsDatabase::UpdateShortcut), 26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_.get(), shortcut)); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsBackend::DeleteShortcutsWithIDs( 27123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const history::ShortcutsDatabase::ShortcutIDs& shortcut_ids) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized()) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < shortcut_ids.size(); ++i) { 2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GuidMap::iterator it(guid_map_.find(shortcut_ids[i])); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != guid_map_.end()) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcuts_map_.erase(it->second); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guid_map_.erase(it); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsChanged()); 28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return no_db_access_ || 28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::PostTask( 28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(base::IgnoreResult( 28723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &history::ShortcutsDatabase::DeleteShortcutsWithIDs), 28823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_.get(), shortcut_ids)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsBackend::DeleteShortcutsWithURL(const GURL& url, 2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool exact_match) { 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& url_spec = url.spec(); 29423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) history::ShortcutsDatabase::ShortcutIDs shortcut_ids; 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (GuidMap::iterator it(guid_map_.begin()); it != guid_map_.end(); ) { 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (exact_match ? 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (it->second->second.match_core.destination_url == url) : 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StartsWithASCII(it->second->second.match_core.destination_url.spec(), 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) url_spec, true)) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_ids.push_back(it->first); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcuts_map_.erase(it->second); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guid_map_.erase(it++); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsChanged()); 3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return no_db_access_ || 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BrowserThread::PostTask( 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 31223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(base::IgnoreResult( 31323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &history::ShortcutsDatabase::DeleteShortcutsWithURL), 31423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_.get(), url_spec)); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShortcutsBackend::DeleteAllShortcuts() { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized()) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcuts_map_.clear(); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guid_map_.clear(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsChanged()); 32423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return no_db_access_ || 32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::PostTask( 32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BrowserThread::DB, FROM_HERE, 32723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(base::IgnoreResult( 32823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &history::ShortcutsDatabase::DeleteAllShortcuts), 32923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) db_.get())); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 331