• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/autocomplete/history_provider.h"
6 
7 #include <string>
8 
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/history/history_service.h"
13 #include "chrome/browser/history/history_service_factory.h"
14 #include "chrome/browser/history/in_memory_url_index_types.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/url_constants.h"
17 #include "components/bookmarks/browser/bookmark_model.h"
18 #include "components/omnibox/autocomplete_input.h"
19 #include "components/omnibox/autocomplete_match.h"
20 #include "url/url_util.h"
21 
DeleteMatch(const AutocompleteMatch & match)22 void HistoryProvider::DeleteMatch(const AutocompleteMatch& match) {
23   DCHECK(done_);
24   DCHECK(profile_);
25   DCHECK(match.deletable);
26 
27   HistoryService* const history_service =
28       HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
29 
30   // Delete the underlying URL along with all its visits from the history DB.
31   // The resulting HISTORY_URLS_DELETED notification will also cause all caches
32   // and indices to drop any data they might have stored pertaining to the URL.
33   DCHECK(history_service);
34   DCHECK(match.destination_url.is_valid());
35   history_service->DeleteURL(match.destination_url);
36 
37   DeleteMatchFromMatches(match);
38 }
39 
40 // static
PreventInlineAutocomplete(const AutocompleteInput & input)41 bool HistoryProvider::PreventInlineAutocomplete(
42     const AutocompleteInput& input) {
43   return input.prevent_inline_autocomplete() ||
44       (!input.text().empty() &&
45        IsWhitespace(input.text()[input.text().length() - 1]));
46 }
47 
HistoryProvider(Profile * profile,AutocompleteProvider::Type type)48 HistoryProvider::HistoryProvider(Profile* profile,
49                                  AutocompleteProvider::Type type)
50     : AutocompleteProvider(type),
51       profile_(profile) {
52 }
53 
~HistoryProvider()54 HistoryProvider::~HistoryProvider() {}
55 
DeleteMatchFromMatches(const AutocompleteMatch & match)56 void HistoryProvider::DeleteMatchFromMatches(const AutocompleteMatch& match) {
57   bool found = false;
58   BookmarkModel* bookmark_model = BookmarkModelFactory::GetForProfile(profile_);
59   for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) {
60     if (i->destination_url == match.destination_url && i->type == match.type) {
61       found = true;
62       if (i->is_history_what_you_typed_match ||
63           (bookmark_model &&
64            bookmark_model->IsBookmarked(i->destination_url))) {
65         // We can't get rid of What-You-Typed or Bookmarked matches,
66         // but we can make them look like they have no backing data.
67         i->deletable = false;
68         i->description.clear();
69         i->description_class.clear();
70       } else {
71         matches_.erase(i);
72       }
73       break;
74     }
75   }
76   DCHECK(found) << "Asked to delete a URL that isn't in our set of matches";
77 }
78 
79 // static
SpansFromTermMatch(const history::TermMatches & matches,size_t text_length,bool is_url)80 ACMatchClassifications HistoryProvider::SpansFromTermMatch(
81     const history::TermMatches& matches,
82     size_t text_length,
83     bool is_url) {
84   ACMatchClassification::Style url_style =
85       is_url ? ACMatchClassification::URL : ACMatchClassification::NONE;
86   ACMatchClassifications spans;
87   if (matches.empty()) {
88     if (text_length)
89       spans.push_back(ACMatchClassification(0, url_style));
90     return spans;
91   }
92   if (matches[0].offset)
93     spans.push_back(ACMatchClassification(0, url_style));
94   size_t match_count = matches.size();
95   for (size_t i = 0; i < match_count;) {
96     size_t offset = matches[i].offset;
97     spans.push_back(ACMatchClassification(offset,
98         ACMatchClassification::MATCH | url_style));
99     // Skip all adjacent matches.
100     do {
101       offset += matches[i].length;
102       ++i;
103     } while ((i < match_count) && (offset == matches[i].offset));
104     if (offset < text_length)
105       spans.push_back(ACMatchClassification(offset, url_style));
106   }
107 
108   return spans;
109 }
110