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

Unified 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, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/autocomplete/extension_app_provider.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/autocomplete/extension_app_provider.cc
===================================================================
--- chrome/browser/autocomplete/extension_app_provider.cc (revision 0)
+++ chrome/browser/autocomplete/extension_app_provider.cc (revision 0)
@@ -0,0 +1,161 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/autocomplete/extension_app_provider.h"
+
+#include <algorithm>
+
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/history/url_database.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/common/notification_service.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ExtensionAppProvider::ExtensionAppProvider(ACProviderListener* listener,
+ Profile* profile)
+ : AutocompleteProvider(listener, profile, "ExtensionApps") {
+ RegisterForNotifications();
+ RefreshAppList();
+}
+
+void ExtensionAppProvider::Start(const AutocompleteInput& input,
+ bool minimal_changes) {
+ matches_.clear();
+
+ if (input.type() == AutocompleteInput::INVALID)
+ return;
+
+ if (!input.text().empty()) {
+ std::string input_utf8 = UTF16ToUTF8(input.text());
+ for (ExtensionApps::const_iterator app = extension_apps_.begin();
+ app != extension_apps_.end(); ++app) {
+ // See if the input matches this extension application.
+ const std::string& name = app->first;
+ const std::string& url = app->second;
+ std::string::const_iterator name_iter =
+ std::search(name.begin(),
+ name.end(),
+ input_utf8.begin(),
+ input_utf8.end(),
+ base::CaseInsensitiveCompare<char>());
+ std::string::const_iterator url_iter =
+ std::search(url.begin(),
+ url.end(),
+ input_utf8.begin(),
+ input_utf8.end(),
+ base::CaseInsensitiveCompare<char>());
+
+ bool matches_name = name_iter != name.end();
+ bool matches_url = url_iter != url.end() &&
+ input.type() != AutocompleteInput::FORCED_QUERY;
+ if (matches_name || matches_url) {
+ // We have a match, might be a partial match.
+ // TODO(finnur): Figure out what type to return here, might want to have
+ // the extension icon/a generic icon show up in the Omnibox.
+ AutocompleteMatch match(this, 0, false, AutocompleteMatch::HISTORY_URL);
+ match.fill_into_edit = UTF8ToUTF16(url);
+ match.destination_url = GURL(url);
+ match.inline_autocomplete_offset = string16::npos;
+ match.contents = UTF8ToUTF16(name);
+ HighlightMatch(input, &match.contents_class, name_iter, name);
+ match.description = UTF8ToUTF16(url);
+ HighlightMatch(input, &match.description_class, url_iter, url);
+ match.relevance = CalculateRelevance(input.type(),
+ input.text().length(),
+ matches_name ?
+ name.length() : url.length(),
+ GURL(url));
+ matches_.push_back(match);
+ }
+ }
+ }
+}
+
+ExtensionAppProvider::~ExtensionAppProvider() {
+}
+
+void ExtensionAppProvider::RefreshAppList() {
+ ExtensionService* extension_service = profile_->GetExtensionService();
+ if (!extension_service)
+ return; // During testing, there is no extension service.
+ const ExtensionList* extensions = extension_service->extensions();
+ extension_apps_.clear();
+ for (ExtensionList::const_iterator app = extensions->begin();
+ app != extensions->end(); ++app) {
+ if ((*app)->is_app() && !(*app)->launch_web_url().empty()) {
+ extension_apps_.push_back(std::make_pair((*app)->name(),
+ (*app)->launch_web_url()));
+ }
+ }
+}
+
+void ExtensionAppProvider::RegisterForNotifications() {
+ registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+ NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
+ NotificationService::AllSources());
+}
+
+void ExtensionAppProvider::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ RefreshAppList();
+}
+
+void ExtensionAppProvider::HighlightMatch(const AutocompleteInput& input,
+ ACMatchClassifications* match_class,
+ std::string::const_iterator iter,
+ const std::string& match_string) {
+ size_t pos = iter - match_string.begin();
+ bool match_found = iter != match_string.end();
+ if (!match_found || pos > 0) {
+ match_class->push_back(
+ ACMatchClassification(0, ACMatchClassification::DIM));
+ }
+ if (match_found) {
+ match_class->push_back(
+ ACMatchClassification(pos, ACMatchClassification::MATCH));
+ if (pos + input.text().length() < match_string.length()) {
+ match_class->push_back(ACMatchClassification(pos + input.text().length(),
+ ACMatchClassification::DIM));
+ }
+ }
+}
+
+int ExtensionAppProvider::CalculateRelevance(AutocompleteInput::Type type,
+ int input_length,
+ int target_length,
+ const GURL& url) {
+ // If you update the algorithm here, please remember to update the tables in
+ // autocomplete.h also.
+ const int kMaxRelevance = 1425;
+
+ if (input_length == target_length)
+ return kMaxRelevance;
+
+ // We give a boost proportionally based on how much of the input matches the
+ // app name, up to a maximum close to 200 (we can be close to, but we'll never
+ // reach 200 because the 100% match is taken care of above).
Peter Kasting 2011/04/05 17:50:46 This scoring algorithm looks better! I suggest th
+ double fraction_boost = static_cast<double>(200) *
+ input_length / target_length;
+
+ // We also give a boost of 40 points for each time the user has previously
+ // typed the Extension App URL (up to a 400 point maximum).
+ int type_count_boost = 0;
+ HistoryService* const history_service =
+ profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ history::URLDatabase* url_db = history_service ?
+ history_service->InMemoryDatabase() : NULL;
+ if (url_db) {
+ history::URLRow info;
+ url_db->GetRowForURL(url, &info);
+ type_count_boost = std::min(400, info.typed_count() * 40);
+ }
+ int relevance = 400 + type_count_boost + static_cast<int>(fraction_boost);
+ DCHECK_LE(relevance, kMaxRelevance);
+ return relevance;
+}
Property changes on: chrome\browser\autocomplete\extension_app_provider.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« 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