keyword_extensions_delegate_impl.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/autocomplete/keyword_extensions_delegate_impl.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/notification_details.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/notification_source.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/browser/extension_system.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace omnibox_api = extensions::api::omnibox;
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int KeywordExtensionsDelegateImpl::global_input_uid_ = 0;
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)KeywordExtensionsDelegateImpl::KeywordExtensionsDelegateImpl(
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    KeywordProvider* provider)
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : KeywordExtensionsDelegate(provider),
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      provider_(provider) {
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(provider_);
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_input_id_ = 0;
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Extension suggestions always come from the original profile, since that's
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // where extensions run. We use the input ID to distinguish whether the
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // suggestions are meant for us.
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  registrar_.Add(
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      this, chrome::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY,
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      content::Source<Profile>(profile()->GetOriginalProfile()));
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  registrar_.Add(
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      this, chrome::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED,
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      content::Source<Profile>(profile()->GetOriginalProfile()));
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  registrar_.Add(
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      this, chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED,
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      content::Source<Profile>(profile()));
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)KeywordExtensionsDelegateImpl::~KeywordExtensionsDelegateImpl() {
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void  KeywordExtensionsDelegateImpl::IncrementInputId() {
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_input_id_ = ++global_input_uid_;
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool KeywordExtensionsDelegateImpl::IsEnabledExtension(
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    Profile* profile,
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& extension_id) {
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExtensionService* extension_service =
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const extensions::Extension* extension =
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extension_service->GetExtensionById(extension_id, false);
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return extension &&
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      (!profile->IsOffTheRecord() ||
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       !extensions::util::IsIncognitoEnabled(extension_id, profile));
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool KeywordExtensionsDelegateImpl::Start(
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AutocompleteInput& input,
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool minimal_changes,
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const TemplateURL* template_url,
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::string16& remaining_input) {
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(template_url);
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (input.want_asynchronous_matches()) {
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string extension_id = template_url->GetExtensionId();
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (extension_id != current_keyword_extension_id_)
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MaybeEndExtensionKeywordMode();
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (current_keyword_extension_id_.empty())
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      EnterExtensionKeywordMode(extension_id);
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  extensions::ApplyDefaultSuggestionForExtensionKeyword(
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      profile(), template_url, remaining_input, &matches()->front());
7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (minimal_changes) {
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // If the input hasn't significantly changed, we can just use the
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // suggestions from last time. We need to readjust the relevance to
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // ensure it is less than the main match's relevance.
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (size_t i = 0; i < extension_suggest_matches_.size(); ++i) {
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->push_back(extension_suggest_matches_[i]);
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->back().relevance = matches()->front().relevance - (i + 1);
8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (input.want_asynchronous_matches()) {
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extension_suggest_last_input_ = input;
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extension_suggest_matches_.clear();
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // We only have to wait for suggest results if there are actually
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // extensions listening for input changes.
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (extensions::ExtensionOmniboxEventRouter::OnInputChanged(
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            profile(), template_url->GetExtensionId(),
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            base::UTF16ToUTF8(remaining_input), current_input_id_))
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_done(false);
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return input.want_asynchronous_matches();
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::EnterExtensionKeywordMode(
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& extension_id) {
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(current_keyword_extension_id_.empty());
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_keyword_extension_id_ = extension_id;
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  extensions::ExtensionOmniboxEventRouter::OnInputStarted(
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      profile(), current_keyword_extension_id_);
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::MaybeEndExtensionKeywordMode() {
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!current_keyword_extension_id_.empty()) {
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extensions::ExtensionOmniboxEventRouter::OnInputCancelled(
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        profile(), current_keyword_extension_id_);
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    current_keyword_extension_id_.clear();
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::Observe(
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int type,
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const content::NotificationSource& source,
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const content::NotificationDetails& details) {
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  TemplateURLService* model = provider_->GetTemplateURLService();
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const AutocompleteInput& input = extension_suggest_last_input_;
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (type) {
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED:
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Input has been accepted, so we're done with this input session. Ensure
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // we don't send the OnInputCancelled event, or handle any more stray
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // suggestions_ready events.
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      current_keyword_extension_id_.clear();
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      current_input_id_ = 0;
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED: {
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // It's possible to change the default suggestion while not in an editing
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // session.
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::string16 keyword, remaining_input;
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (matches()->empty() || current_keyword_extension_id_.empty() ||
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          !KeywordProvider::ExtractKeywordFromInput(
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              input, &keyword, &remaining_input))
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return;
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const TemplateURL* template_url(
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          model->GetTemplateURLForKeyword(keyword));
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extensions::ApplyDefaultSuggestionForExtensionKeyword(
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          profile(), template_url, remaining_input, &matches()->front());
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OnProviderUpdate(true);
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY: {
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const omnibox_api::SendSuggestions::Params& suggestions =
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          *content::Details<
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              omnibox_api::SendSuggestions::Params>(details).ptr();
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (suggestions.request_id != current_input_id_)
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return;  // This is an old result. Just ignore.
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::string16 keyword, remaining_input;
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bool result = KeywordProvider::ExtractKeywordFromInput(
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          input, &keyword, &remaining_input);
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DCHECK(result);
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const TemplateURL* template_url =
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          model->GetTemplateURLForKeyword(keyword);
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // TODO(mpcomplete): consider clamping the number of suggestions to
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // AutocompleteProvider::kMaxMatches.
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      for (size_t i = 0; i < suggestions.suggest_results.size(); ++i) {
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        const omnibox_api::SuggestResult& suggestion =
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            *suggestions.suggest_results[i];
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // We want to order these suggestions in descending order, so start with
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // the relevance of the first result (added synchronously in Start()),
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // and subtract 1 for each subsequent suggestion from the extension.
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // We recompute the first match's relevance; we know that |complete|
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // is true, because we wouldn't get results from the extension unless
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // the full keyword had been typed.
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        int first_relevance = KeywordProvider::CalculateRelevance(
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            input.type(), true, true, input.prefer_keyword(),
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            input.allow_exact_keyword_match());
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // Because these matches are async, we should never let them become the
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // default match, lest we introduce race conditions in the omnibox user
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // interaction.
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        extension_suggest_matches_.push_back(
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            provider_->CreateAutocompleteMatch(
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                template_url, input, keyword.length(),
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                base::UTF8ToUTF16(suggestion.content), false,
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                first_relevance - (i + 1)));
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        AutocompleteMatch* match = &extension_suggest_matches_.back();
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        match->contents.assign(base::UTF8ToUTF16(suggestion.description));
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        match->contents_class =
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            extensions::StyleTypesToACMatchClassifications(suggestion);
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_done(true);
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->insert(matches()->end(),
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        extension_suggest_matches_.begin(),
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        extension_suggest_matches_.end());
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OnProviderUpdate(!extension_suggest_matches_.empty());
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    default:
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      NOTREACHED();
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::OnProviderUpdate(bool updated_matches) {
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider_->listener_->OnProviderUpdate(updated_matches);
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
211