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/extensions/api/omnibox/omnibox_api.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/notification_details.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/notification_source.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_registry.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.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(
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Profile* profile,
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    KeywordProvider* provider)
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : KeywordExtensionsDelegate(provider),
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      profile_(profile),
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      provider_(provider) {
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(provider_);
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_input_id_ = 0;
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Extension suggestions always come from the original profile, since that's
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // where extensions run. We use the input ID to distinguish whether the
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // suggestions are meant for us.
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY,
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 content::Source<Profile>(profile_->GetOriginalProfile()));
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  registrar_.Add(
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      this,
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extensions::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED,
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      content::Source<Profile>(profile_->GetOriginalProfile()));
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED,
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 content::Source<Profile>(profile_));
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)KeywordExtensionsDelegateImpl::~KeywordExtensionsDelegateImpl() {
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void  KeywordExtensionsDelegateImpl::IncrementInputId() {
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_input_id_ = ++global_input_uid_;
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool KeywordExtensionsDelegateImpl::IsEnabledExtension(
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& extension_id) {
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const extensions::Extension* extension =
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionRegistry::Get(
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          profile_)->enabled_extensions().GetByID(extension_id);
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return extension &&
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      (!profile_->IsOffTheRecord() ||
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       extensions::util::IsIncognitoEnabled(extension_id, profile_));
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool KeywordExtensionsDelegateImpl::Start(
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AutocompleteInput& input,
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool minimal_changes,
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const TemplateURL* template_url,
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::string16& remaining_input) {
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(template_url);
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (input.want_asynchronous_matches()) {
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string extension_id = template_url->GetExtensionId();
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (extension_id != current_keyword_extension_id_)
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MaybeEndExtensionKeywordMode();
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (current_keyword_extension_id_.empty())
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      EnterExtensionKeywordMode(extension_id);
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  extensions::ApplyDefaultSuggestionForExtensionKeyword(
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      profile_, template_url, remaining_input, &matches()->front());
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (minimal_changes) {
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // If the input hasn't significantly changed, we can just use the
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // suggestions from last time. We need to readjust the relevance to
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // ensure it is less than the main match's relevance.
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (size_t i = 0; i < extension_suggest_matches_.size(); ++i) {
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->push_back(extension_suggest_matches_[i]);
8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->back().relevance = matches()->front().relevance - (i + 1);
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (input.want_asynchronous_matches()) {
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extension_suggest_last_input_ = input;
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extension_suggest_matches_.clear();
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // We only have to wait for suggest results if there are actually
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // extensions listening for input changes.
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (extensions::ExtensionOmniboxEventRouter::OnInputChanged(
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            profile_, template_url->GetExtensionId(),
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            base::UTF16ToUTF8(remaining_input), current_input_id_))
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_done(false);
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return input.want_asynchronous_matches();
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::EnterExtensionKeywordMode(
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& extension_id) {
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(current_keyword_extension_id_.empty());
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  current_keyword_extension_id_ = extension_id;
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  extensions::ExtensionOmniboxEventRouter::OnInputStarted(
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      profile_, current_keyword_extension_id_);
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::MaybeEndExtensionKeywordMode() {
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!current_keyword_extension_id_.empty()) {
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    extensions::ExtensionOmniboxEventRouter::OnInputCancelled(
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        profile_, current_keyword_extension_id_);
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    current_keyword_extension_id_.clear();
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::Observe(
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int type,
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const content::NotificationSource& source,
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const content::NotificationDetails& details) {
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  TemplateURLService* model = provider_->GetTemplateURLService();
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const AutocompleteInput& input = extension_suggest_last_input_;
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (type) {
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED:
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Input has been accepted, so we're done with this input session. Ensure
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // we don't send the OnInputCancelled event, or handle any more stray
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // suggestions_ready events.
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      current_keyword_extension_id_.clear();
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      current_input_id_ = 0;
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        : {
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // It's possible to change the default suggestion while not in an editing
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // session.
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::string16 keyword, remaining_input;
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (matches()->empty() || current_keyword_extension_id_.empty() ||
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          !KeywordProvider::ExtractKeywordFromInput(
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              input, &keyword, &remaining_input))
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return;
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const TemplateURL* template_url(
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          model->GetTemplateURLForKeyword(keyword));
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extensions::ApplyDefaultSuggestionForExtensionKeyword(
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          profile_, template_url, remaining_input, &matches()->front());
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OnProviderUpdate(true);
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY: {
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const omnibox_api::SendSuggestions::Params& suggestions =
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          *content::Details<
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              omnibox_api::SendSuggestions::Params>(details).ptr();
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (suggestions.request_id != current_input_id_)
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return;  // This is an old result. Just ignore.
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::string16 keyword, remaining_input;
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bool result = KeywordProvider::ExtractKeywordFromInput(
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          input, &keyword, &remaining_input);
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DCHECK(result);
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const TemplateURL* template_url =
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          model->GetTemplateURLForKeyword(keyword);
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // TODO(mpcomplete): consider clamping the number of suggestions to
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // AutocompleteProvider::kMaxMatches.
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      for (size_t i = 0; i < suggestions.suggest_results.size(); ++i) {
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        const omnibox_api::SuggestResult& suggestion =
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            *suggestions.suggest_results[i];
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // We want to order these suggestions in descending order, so start with
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // the relevance of the first result (added synchronously in Start()),
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // and subtract 1 for each subsequent suggestion from the extension.
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // We recompute the first match's relevance; we know that |complete|
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // is true, because we wouldn't get results from the extension unless
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // the full keyword had been typed.
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        int first_relevance = KeywordProvider::CalculateRelevance(
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            input.type(), true, true, input.prefer_keyword(),
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            input.allow_exact_keyword_match());
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // Because these matches are async, we should never let them become the
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // default match, lest we introduce race conditions in the omnibox user
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        // interaction.
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        extension_suggest_matches_.push_back(
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            provider_->CreateAutocompleteMatch(
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                template_url, input, keyword.length(),
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                base::UTF8ToUTF16(suggestion.content), false,
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                first_relevance - (i + 1)));
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        AutocompleteMatch* match = &extension_suggest_matches_.back();
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        match->contents.assign(base::UTF8ToUTF16(suggestion.description));
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        match->contents_class =
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            extensions::StyleTypesToACMatchClassifications(suggestion);
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_done(true);
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      matches()->insert(matches()->end(),
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        extension_suggest_matches_.begin(),
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                        extension_suggest_matches_.end());
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OnProviderUpdate(!extension_suggest_matches_.empty());
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    default:
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      NOTREACHED();
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void KeywordExtensionsDelegateImpl::OnProviderUpdate(bool updated_matches) {
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider_->listener_->OnProviderUpdate(updated_matches);
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
213