| 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,165 @@
|
| +// 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 <cmath>
|
| +
|
| +#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).
|
| + double fraction_boost = static_cast<double>(200) *
|
| + input_length / target_length;
|
| +
|
| + // We also give a boost relative to how often the user has previously typed
|
| + // the Extension App URL/selected the Extension App suggestion from this
|
| + // provider (boost is between 200-400).
|
| + double 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 =
|
| + 400 * (1.0 - (std::pow(static_cast<double>(2), -info.typed_count())));
|
| + }
|
| + int relevance = 575 + static_cast<int>(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
|
|
|
|
|