Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1516)

Side by Side Diff: chrome/browser/autocomplete/extension_app_provider.cc

Issue 6758031: Implement a simple Extension App Omnibox provider. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/autocomplete/extension_app_provider.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/extension_app_provider.h"
6
7 #include <algorithm>
8 #include <cmath>
9
10 #include "base/string16.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/history/history.h"
14 #include "chrome/browser/history/url_database.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "content/common/notification_service.h"
17 #include "ui/base/l10n/l10n_util.h"
18
19 ExtensionAppProvider::ExtensionAppProvider(ACProviderListener* listener,
20 Profile* profile)
21 : AutocompleteProvider(listener, profile, "ExtensionApps") {
22 RegisterForNotifications();
23 RefreshAppList();
24 }
25
26 void ExtensionAppProvider::Start(const AutocompleteInput& input,
27 bool minimal_changes) {
28 matches_.clear();
29
30 if (input.type() == AutocompleteInput::INVALID)
31 return;
32
33 if (!input.text().empty()) {
34 std::string input_utf8 = UTF16ToUTF8(input.text());
35 for (ExtensionApps::const_iterator app = extension_apps_.begin();
36 app != extension_apps_.end(); ++app) {
37 // See if the input matches this extension application.
38 const std::string& name = app->first;
39 const std::string& url = app->second;
40 std::string::const_iterator name_iter =
41 std::search(name.begin(),
42 name.end(),
43 input_utf8.begin(),
44 input_utf8.end(),
45 base::CaseInsensitiveCompare<char>());
46 std::string::const_iterator url_iter =
47 std::search(url.begin(),
48 url.end(),
49 input_utf8.begin(),
50 input_utf8.end(),
51 base::CaseInsensitiveCompare<char>());
52
53 bool matches_name = name_iter != name.end();
54 bool matches_url = url_iter != url.end() &&
55 input.type() != AutocompleteInput::FORCED_QUERY;
56 if (matches_name || matches_url) {
57 // We have a match, might be a partial match.
58 // TODO(finnur): Figure out what type to return here, might want to have
59 // the extension icon/a generic icon show up in the Omnibox.
60 AutocompleteMatch match(this, 0, false, AutocompleteMatch::HISTORY_URL);
61 match.fill_into_edit = UTF8ToUTF16(url);
62 match.destination_url = GURL(url);
63 match.inline_autocomplete_offset = string16::npos;
64 match.contents = UTF8ToUTF16(name);
65 HighlightMatch(input, &match.contents_class, name_iter, name);
66 match.description = UTF8ToUTF16(url);
67 HighlightMatch(input, &match.description_class, url_iter, url);
68 match.relevance = CalculateRelevance(input.type(),
69 input.text().length(),
70 matches_name ?
71 name.length() : url.length(),
72 GURL(url));
73 matches_.push_back(match);
74 }
75 }
76 }
77 }
78
79 ExtensionAppProvider::~ExtensionAppProvider() {
80 }
81
82 void ExtensionAppProvider::RefreshAppList() {
83 ExtensionService* extension_service = profile_->GetExtensionService();
84 if (!extension_service)
85 return; // During testing, there is no extension service.
86 const ExtensionList* extensions = extension_service->extensions();
87 extension_apps_.clear();
88 for (ExtensionList::const_iterator app = extensions->begin();
89 app != extensions->end(); ++app) {
90 if ((*app)->is_app() && !(*app)->launch_web_url().empty()) {
91 extension_apps_.push_back(std::make_pair((*app)->name(),
92 (*app)->launch_web_url()));
93 }
94 }
95 }
96
97 void ExtensionAppProvider::RegisterForNotifications() {
98 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
99 NotificationService::AllSources());
100 registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
101 NotificationService::AllSources());
102 }
103
104 void ExtensionAppProvider::Observe(NotificationType type,
105 const NotificationSource& source,
106 const NotificationDetails& details) {
107 RefreshAppList();
108 }
109
110 void ExtensionAppProvider::HighlightMatch(const AutocompleteInput& input,
111 ACMatchClassifications* match_class,
112 std::string::const_iterator iter,
113 const std::string& match_string) {
114 size_t pos = iter - match_string.begin();
115 bool match_found = iter != match_string.end();
116 if (!match_found || pos > 0) {
117 match_class->push_back(
118 ACMatchClassification(0, ACMatchClassification::DIM));
119 }
120 if (match_found) {
121 match_class->push_back(
122 ACMatchClassification(pos, ACMatchClassification::MATCH));
123 if (pos + input.text().length() < match_string.length()) {
124 match_class->push_back(ACMatchClassification(pos + input.text().length(),
125 ACMatchClassification::DIM));
126 }
127 }
128 }
129
130 int ExtensionAppProvider::CalculateRelevance(AutocompleteInput::Type type,
131 int input_length,
132 int target_length,
133 const GURL& url) {
134 // If you update the algorithm here, please remember to update the tables in
135 // autocomplete.h also.
136 const int kMaxRelevance = 1425;
137
138 if (input_length == target_length)
139 return kMaxRelevance;
140
141 // We give a boost proportionally based on how much of the input matches the
142 // app name, up to a maximum close to 200 (we can be close to, but we'll never
143 // reach 200 because the 100% match is taken care of above).
144 double fraction_boost = static_cast<double>(200) *
145 input_length / target_length;
146
147 // We also give a boost relative to how often the user has previously typed
148 // the Extension App URL/selected the Extension App suggestion from this
149 // provider (boost is between 200-400).
150 double type_count_boost = 0;
151 HistoryService* const history_service =
152 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
153 history::URLDatabase* url_db = history_service ?
154 history_service->InMemoryDatabase() : NULL;
155 if (url_db) {
156 history::URLRow info;
157 url_db->GetRowForURL(url, &info);
158 type_count_boost =
159 400 * (1.0 - (std::pow(static_cast<double>(2), -info.typed_count())));
160 }
161 int relevance = 575 + static_cast<int>(type_count_boost) +
162 static_cast<int>(fraction_boost);
163 DCHECK_LE(relevance, kMaxRelevance);
164 return relevance;
165 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/extension_app_provider.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698