1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_omnibox_api.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_writer.h"
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
10201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/utf_string_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_event_router.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
15201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/search_engines/template_url.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace events {
194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kOnInputStarted[] = "omnibox.onInputStarted";
204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kOnInputChanged[] = "omnibox.onInputChanged";
214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kOnInputEntered[] = "omnibox.onInputEntered";
224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kOnInputCancelled[] = "omnibox.onInputCancelled";
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};  // namespace events
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kDescriptionStylesOrderError[] =
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Suggestion descriptionStyles must be in increasing non-overlapping order.";
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kDescriptionStylesLengthError[] =
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Suggestion descriptionStyles contains an offset longer than the"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    " description text";
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kSuggestionContent[] = "content";
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kSuggestionDescription[] = "description";
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kSuggestionDescriptionStyles[] = "descriptionStyles";
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kDescriptionStylesType[] = "type";
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kDescriptionStylesOffset[] = "offset";
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char kDescriptionStylesLength[] = "length";
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<PropertyAccessor<ExtensionOmniboxSuggestion> >
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    g_extension_omnibox_suggestion_property_accessor(base::LINKER_INITIALIZED);
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPropertyAccessor<ExtensionOmniboxSuggestion>& GetPropertyAccessor() {
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return g_extension_omnibox_suggestion_property_accessor.Get();
44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
46201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Returns the suggestion object set by the extension via the
47201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// omnibox.setDefaultSuggestion call, or NULL if it was never set.
48201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst ExtensionOmniboxSuggestion* GetDefaultSuggestionForExtension(
49201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    Profile* profile, const std::string& extension_id) {
50201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const Extension* extension =
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      profile->GetExtensionService()->GetExtensionById(extension_id, false);
52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!extension)
53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return NULL;
54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return GetPropertyAccessor().GetProperty(
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      profile->GetExtensionService()->GetPropertyBag(extension));
56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};  // namespace
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionOmniboxEventRouter::OnInputStarted(
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile, const std::string& extension_id) {
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  profile->GetExtensionEventRouter()->DispatchEventToExtension(
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      extension_id, events::kOnInputStarted, "[]", profile, GURL());
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionOmniboxEventRouter::OnInputChanged(
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile, const std::string& extension_id,
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& input, int suggest_id) {
71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!profile->GetExtensionEventRouter()->ExtensionHasEventListener(
72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        extension_id, events::kOnInputChanged))
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue args;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args.Set(0, Value::CreateStringValue(input));
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args.Set(1, Value::CreateIntegerValue(suggest_id));
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json_args;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json_args);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  profile->GetExtensionEventRouter()->DispatchEventToExtension(
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      extension_id, events::kOnInputChanged, json_args, profile, GURL());
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionOmniboxEventRouter::OnInputEntered(
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile, const std::string& extension_id,
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& input) {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue args;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args.Set(0, Value::CreateStringValue(input));
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json_args;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json_args);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  profile->GetExtensionEventRouter()->DispatchEventToExtension(
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      extension_id, events::kOnInputEntered, json_args, profile, GURL());
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Source<Profile>(profile), NotificationService::NoDetails());
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionOmniboxEventRouter::OnInputCancelled(
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile, const std::string& extension_id) {
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  profile->GetExtensionEventRouter()->DispatchEventToExtension(
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      extension_id, events::kOnInputCancelled, "[]", profile, GURL());
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool OmniboxSendSuggestionsFunction::RunImpl() {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExtensionOmniboxSuggestions suggestions;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue* suggestions_value;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &suggestions.request_id));
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetList(1, &suggestions_value));
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  suggestions.suggestions.resize(suggestions_value->GetSize());
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < suggestions_value->GetSize(); ++i) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ExtensionOmniboxSuggestion& suggestion = suggestions.suggestions[i];
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* suggestion_value;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(suggestions_value->GetDictionary(
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        i, &suggestion_value));
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXTENSION_FUNCTION_VALIDATE(suggestion_value->GetString(
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSuggestionContent, &suggestion.content));
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXTENSION_FUNCTION_VALIDATE(suggestion_value->GetString(
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSuggestionDescription, &suggestion.description));
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (suggestion_value->HasKey(kSuggestionDescriptionStyles)) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ListValue* styles;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXTENSION_FUNCTION_VALIDATE(
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          suggestion_value->GetList(kSuggestionDescriptionStyles, &styles));
1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      EXTENSION_FUNCTION_VALIDATE(suggestion.ReadStylesFromValue(*styles));
1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    } else {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      suggestion.description_styles.clear();
1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      suggestion.description_styles.push_back(
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ACMatchClassification(0, ACMatchClassification::NONE));
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY,
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Source<Profile>(profile_),
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Details<ExtensionOmniboxSuggestions>(&suggestions));
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool OmniboxSetDefaultSuggestionFunction::RunImpl() {
148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ExtensionOmniboxSuggestion suggestion;
149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DictionaryValue* suggestion_value;
150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &suggestion_value));
151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXTENSION_FUNCTION_VALIDATE(suggestion_value->GetString(
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kSuggestionDescription, &suggestion.description));
153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (suggestion_value->HasKey(kSuggestionDescriptionStyles)) {
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ListValue* styles;
156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXTENSION_FUNCTION_VALIDATE(
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        suggestion_value->GetList(kSuggestionDescriptionStyles, &styles));
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXTENSION_FUNCTION_VALIDATE(suggestion.ReadStylesFromValue(*styles));
159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else {
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    suggestion.description_styles.clear();
161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    suggestion.description_styles.push_back(
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ACMatchClassification(0, ACMatchClassification::NONE));
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Store the suggestion in the extension's runtime data.
166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  GetPropertyAccessor().SetProperty(
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      profile_->GetExtensionService()->GetPropertyBag(GetExtension()),
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      suggestion);
169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NotificationService::current()->Notify(
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED,
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      Source<Profile>(profile_),
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NotificationService::NoDetails());
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return true;
176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
178731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionOmniboxSuggestion::ExtensionOmniboxSuggestion() {}
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
180731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionOmniboxSuggestion::~ExtensionOmniboxSuggestion() {}
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool ExtensionOmniboxSuggestion::ReadStylesFromValue(
1834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const ListValue& styles_value) {
1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  description_styles.clear();
1854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Step 1: Build a vector of styles, 1 per character of description text.
1874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  std::vector<int> styles;
1884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  styles.resize(description.length());  // sets all styles to 0
1894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 0; i < styles_value.GetSize(); ++i) {
1914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DictionaryValue* style;
1924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    std::string type;
1934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int offset;
1944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int length;
1954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!styles_value.GetDictionary(i, &style))
1964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!style->GetString(kDescriptionStylesType, &type))
1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!style->GetInteger(kDescriptionStylesOffset, &offset))
2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
2014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!style->GetInteger(kDescriptionStylesLength, &length) || length < 0)
2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      length = description.length();
2034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (offset < 0)
2054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      offset = std::max(0, static_cast<int>(description.length()) + offset);
2064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int type_class =
2084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        (type == "url") ? ACMatchClassification::URL :
2094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        (type == "match") ? ACMatchClassification::MATCH :
2104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        (type == "dim") ? ACMatchClassification::DIM : -1;
2114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (type_class == -1)
2124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
2134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    for (int j = offset;
2154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch         j < offset + length && j < static_cast<int>(styles.size()); ++j)
2164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      styles[j] |= type_class;
2174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
2184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Step 2: Convert the vector into continuous runs of common styles.
2204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 0; i < styles.size(); ++i) {
2214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (i == 0 || styles[i] != styles[i-1])
2224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      description_styles.push_back(ACMatchClassification(i, styles[i]));
2234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
2244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
2264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
2274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
228513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtensionOmniboxSuggestions::ExtensionOmniboxSuggestions() : request_id(0) {}
229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
230731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionOmniboxSuggestions::~ExtensionOmniboxSuggestions() {}
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ApplyDefaultSuggestionForExtensionKeyword(
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    Profile* profile,
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const TemplateURL* keyword,
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const string16& remaining_input,
236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    AutocompleteMatch* match) {
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(keyword->IsExtensionKeyword());
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const ExtensionOmniboxSuggestion* suggestion =
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      GetDefaultSuggestionForExtension(profile, keyword->GetExtensionId());
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!suggestion)
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;  // fall back to the universal default
242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const string16 kPlaceholderText(ASCIIToUTF16("%s"));
244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const string16 kReplacementText(ASCIIToUTF16("<input>"));
245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  string16 description = suggestion->description;
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ACMatchClassifications& description_styles = match->contents_class;
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  description_styles = suggestion->description_styles;
249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Replace "%s" with the user's input and adjust the style offsets to the
251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // new length of the description.
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t placeholder(suggestion->description.find(kPlaceholderText, 0));
253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (placeholder != string16::npos) {
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    string16 replacement =
255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        remaining_input.empty() ? kReplacementText : remaining_input;
256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    description.replace(placeholder, kPlaceholderText.length(), replacement);
257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    for (size_t i = 0; i < description_styles.size(); ++i) {
259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (description_styles[i].offset > placeholder)
260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        description_styles[i].offset += replacement.length() - 2;
261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  match->contents.assign(description);
265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
266