Home | History | Annotate | Download | only in autocomplete
      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 
     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
     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 
     48 HistoryProvider::HistoryProvider(Profile* profile,
     49                                  AutocompleteProvider::Type type)
     50     : AutocompleteProvider(type),
     51       profile_(profile) {
     52 }
     53 
     54 HistoryProvider::~HistoryProvider() {}
     55 
     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
     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