| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" | 5 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 |
| 8 #include <utility> | 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/memory/ptr_util.h" |
| 11 #include "base/strings/string16.h" | 13 #include "base/strings/string16.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 13 #include "build/build_config.h" | 15 #include "build/build_config.h" |
| 14 #include "chrome/browser/extensions/tab_helper.h" | 16 #include "chrome/browser/extensions/tab_helper.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/search_engines/template_url_service_factory.h" | 18 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 17 #include "chrome/common/extensions/api/omnibox.h" | 19 #include "chrome/common/extensions/api/omnibox.h" |
| 18 #include "chrome/common/extensions/api/omnibox/omnibox_handler.h" | 20 #include "chrome/common/extensions/api/omnibox/omnibox_handler.h" |
| 19 #include "components/search_engines/template_url.h" | 21 #include "components/search_engines/template_url.h" |
| 20 #include "components/search_engines/template_url_service.h" | 22 #include "components/search_engines/template_url_service.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 47 static const int kOmniboxIconPaddingLeft = 2; | 49 static const int kOmniboxIconPaddingLeft = 2; |
| 48 static const int kOmniboxIconPaddingRight = 2; | 50 static const int kOmniboxIconPaddingRight = 2; |
| 49 #elif defined(OS_MACOSX) | 51 #elif defined(OS_MACOSX) |
| 50 static const int kOmniboxIconPaddingLeft = 0; | 52 static const int kOmniboxIconPaddingLeft = 0; |
| 51 static const int kOmniboxIconPaddingRight = 2; | 53 static const int kOmniboxIconPaddingRight = 2; |
| 52 #else | 54 #else |
| 53 static const int kOmniboxIconPaddingLeft = 0; | 55 static const int kOmniboxIconPaddingLeft = 0; |
| 54 static const int kOmniboxIconPaddingRight = 0; | 56 static const int kOmniboxIconPaddingRight = 0; |
| 55 #endif | 57 #endif |
| 56 | 58 |
| 57 scoped_ptr<omnibox::SuggestResult> GetOmniboxDefaultSuggestion( | 59 std::unique_ptr<omnibox::SuggestResult> GetOmniboxDefaultSuggestion( |
| 58 Profile* profile, | 60 Profile* profile, |
| 59 const std::string& extension_id) { | 61 const std::string& extension_id) { |
| 60 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile); | 62 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile); |
| 61 | 63 |
| 62 scoped_ptr<omnibox::SuggestResult> suggestion; | 64 std::unique_ptr<omnibox::SuggestResult> suggestion; |
| 63 const base::DictionaryValue* dict = NULL; | 65 const base::DictionaryValue* dict = NULL; |
| 64 if (prefs && prefs->ReadPrefAsDictionary(extension_id, | 66 if (prefs && prefs->ReadPrefAsDictionary(extension_id, |
| 65 kOmniboxDefaultSuggestion, | 67 kOmniboxDefaultSuggestion, |
| 66 &dict)) { | 68 &dict)) { |
| 67 suggestion.reset(new omnibox::SuggestResult); | 69 suggestion.reset(new omnibox::SuggestResult); |
| 68 omnibox::SuggestResult::Populate(*dict, suggestion.get()); | 70 omnibox::SuggestResult::Populate(*dict, suggestion.get()); |
| 69 } | 71 } |
| 70 return suggestion; | 72 return suggestion; |
| 71 } | 73 } |
| 72 | 74 |
| 73 // Tries to set the omnibox default suggestion; returns true on success or | 75 // Tries to set the omnibox default suggestion; returns true on success or |
| 74 // false on failure. | 76 // false on failure. |
| 75 bool SetOmniboxDefaultSuggestion( | 77 bool SetOmniboxDefaultSuggestion( |
| 76 Profile* profile, | 78 Profile* profile, |
| 77 const std::string& extension_id, | 79 const std::string& extension_id, |
| 78 const omnibox::DefaultSuggestResult& suggestion) { | 80 const omnibox::DefaultSuggestResult& suggestion) { |
| 79 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile); | 81 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile); |
| 80 if (!prefs) | 82 if (!prefs) |
| 81 return false; | 83 return false; |
| 82 | 84 |
| 83 scoped_ptr<base::DictionaryValue> dict = suggestion.ToValue(); | 85 std::unique_ptr<base::DictionaryValue> dict = suggestion.ToValue(); |
| 84 // Add the content field so that the dictionary can be used to populate an | 86 // Add the content field so that the dictionary can be used to populate an |
| 85 // omnibox::SuggestResult. | 87 // omnibox::SuggestResult. |
| 86 dict->SetWithoutPathExpansion(kSuggestionContent, new base::StringValue("")); | 88 dict->SetWithoutPathExpansion(kSuggestionContent, new base::StringValue("")); |
| 87 prefs->UpdateExtensionPref(extension_id, | 89 prefs->UpdateExtensionPref(extension_id, |
| 88 kOmniboxDefaultSuggestion, | 90 kOmniboxDefaultSuggestion, |
| 89 dict.release()); | 91 dict.release()); |
| 90 | 92 |
| 91 return true; | 93 return true; |
| 92 } | 94 } |
| 93 | 95 |
| 94 // Returns a string used as a template URL string of the extension. | 96 // Returns a string used as a template URL string of the extension. |
| 95 std::string GetTemplateURLStringForExtension(const std::string& extension_id) { | 97 std::string GetTemplateURLStringForExtension(const std::string& extension_id) { |
| 96 // This URL is not actually used for navigation. It holds the extension's ID. | 98 // This URL is not actually used for navigation. It holds the extension's ID. |
| 97 return std::string(extensions::kExtensionScheme) + "://" + | 99 return std::string(extensions::kExtensionScheme) + "://" + |
| 98 extension_id + "/?q={searchTerms}"; | 100 extension_id + "/?q={searchTerms}"; |
| 99 } | 101 } |
| 100 | 102 |
| 101 } // namespace | 103 } // namespace |
| 102 | 104 |
| 103 // static | 105 // static |
| 104 void ExtensionOmniboxEventRouter::OnInputStarted( | 106 void ExtensionOmniboxEventRouter::OnInputStarted( |
| 105 Profile* profile, const std::string& extension_id) { | 107 Profile* profile, const std::string& extension_id) { |
| 106 scoped_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_STARTED, | 108 std::unique_ptr<Event> event(new Event( |
| 107 omnibox::OnInputStarted::kEventName, | 109 events::OMNIBOX_ON_INPUT_STARTED, omnibox::OnInputStarted::kEventName, |
| 108 make_scoped_ptr(new base::ListValue()))); | 110 base::WrapUnique(new base::ListValue()))); |
| 109 event->restrict_to_browser_context = profile; | 111 event->restrict_to_browser_context = profile; |
| 110 EventRouter::Get(profile) | 112 EventRouter::Get(profile) |
| 111 ->DispatchEventToExtension(extension_id, std::move(event)); | 113 ->DispatchEventToExtension(extension_id, std::move(event)); |
| 112 } | 114 } |
| 113 | 115 |
| 114 // static | 116 // static |
| 115 bool ExtensionOmniboxEventRouter::OnInputChanged( | 117 bool ExtensionOmniboxEventRouter::OnInputChanged( |
| 116 Profile* profile, const std::string& extension_id, | 118 Profile* profile, const std::string& extension_id, |
| 117 const std::string& input, int suggest_id) { | 119 const std::string& input, int suggest_id) { |
| 118 EventRouter* event_router = EventRouter::Get(profile); | 120 EventRouter* event_router = EventRouter::Get(profile); |
| 119 if (!event_router->ExtensionHasEventListener( | 121 if (!event_router->ExtensionHasEventListener( |
| 120 extension_id, omnibox::OnInputChanged::kEventName)) | 122 extension_id, omnibox::OnInputChanged::kEventName)) |
| 121 return false; | 123 return false; |
| 122 | 124 |
| 123 scoped_ptr<base::ListValue> args(new base::ListValue()); | 125 std::unique_ptr<base::ListValue> args(new base::ListValue()); |
| 124 args->Set(0, new base::StringValue(input)); | 126 args->Set(0, new base::StringValue(input)); |
| 125 args->Set(1, new base::FundamentalValue(suggest_id)); | 127 args->Set(1, new base::FundamentalValue(suggest_id)); |
| 126 | 128 |
| 127 scoped_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_CHANGED, | 129 std::unique_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_CHANGED, |
| 128 omnibox::OnInputChanged::kEventName, | 130 omnibox::OnInputChanged::kEventName, |
| 129 std::move(args))); | 131 std::move(args))); |
| 130 event->restrict_to_browser_context = profile; | 132 event->restrict_to_browser_context = profile; |
| 131 event_router->DispatchEventToExtension(extension_id, std::move(event)); | 133 event_router->DispatchEventToExtension(extension_id, std::move(event)); |
| 132 return true; | 134 return true; |
| 133 } | 135 } |
| 134 | 136 |
| 135 // static | 137 // static |
| 136 void ExtensionOmniboxEventRouter::OnInputEntered( | 138 void ExtensionOmniboxEventRouter::OnInputEntered( |
| 137 content::WebContents* web_contents, | 139 content::WebContents* web_contents, |
| 138 const std::string& extension_id, | 140 const std::string& extension_id, |
| 139 const std::string& input, | 141 const std::string& input, |
| 140 WindowOpenDisposition disposition) { | 142 WindowOpenDisposition disposition) { |
| 141 Profile* profile = | 143 Profile* profile = |
| 142 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 144 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 143 | 145 |
| 144 const Extension* extension = | 146 const Extension* extension = |
| 145 ExtensionRegistry::Get(profile)->enabled_extensions().GetByID( | 147 ExtensionRegistry::Get(profile)->enabled_extensions().GetByID( |
| 146 extension_id); | 148 extension_id); |
| 147 CHECK(extension); | 149 CHECK(extension); |
| 148 extensions::TabHelper::FromWebContents(web_contents)-> | 150 extensions::TabHelper::FromWebContents(web_contents)-> |
| 149 active_tab_permission_granter()->GrantIfRequested(extension); | 151 active_tab_permission_granter()->GrantIfRequested(extension); |
| 150 | 152 |
| 151 scoped_ptr<base::ListValue> args(new base::ListValue()); | 153 std::unique_ptr<base::ListValue> args(new base::ListValue()); |
| 152 args->Set(0, new base::StringValue(input)); | 154 args->Set(0, new base::StringValue(input)); |
| 153 if (disposition == NEW_FOREGROUND_TAB) | 155 if (disposition == NEW_FOREGROUND_TAB) |
| 154 args->Set(1, new base::StringValue(kForegroundTabDisposition)); | 156 args->Set(1, new base::StringValue(kForegroundTabDisposition)); |
| 155 else if (disposition == NEW_BACKGROUND_TAB) | 157 else if (disposition == NEW_BACKGROUND_TAB) |
| 156 args->Set(1, new base::StringValue(kBackgroundTabDisposition)); | 158 args->Set(1, new base::StringValue(kBackgroundTabDisposition)); |
| 157 else | 159 else |
| 158 args->Set(1, new base::StringValue(kCurrentTabDisposition)); | 160 args->Set(1, new base::StringValue(kCurrentTabDisposition)); |
| 159 | 161 |
| 160 scoped_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_ENTERED, | 162 std::unique_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_ENTERED, |
| 161 omnibox::OnInputEntered::kEventName, | 163 omnibox::OnInputEntered::kEventName, |
| 162 std::move(args))); | 164 std::move(args))); |
| 163 event->restrict_to_browser_context = profile; | 165 event->restrict_to_browser_context = profile; |
| 164 EventRouter::Get(profile) | 166 EventRouter::Get(profile) |
| 165 ->DispatchEventToExtension(extension_id, std::move(event)); | 167 ->DispatchEventToExtension(extension_id, std::move(event)); |
| 166 | 168 |
| 167 content::NotificationService::current()->Notify( | 169 content::NotificationService::current()->Notify( |
| 168 extensions::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED, | 170 extensions::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED, |
| 169 content::Source<Profile>(profile), | 171 content::Source<Profile>(profile), |
| 170 content::NotificationService::NoDetails()); | 172 content::NotificationService::NoDetails()); |
| 171 } | 173 } |
| 172 | 174 |
| 173 // static | 175 // static |
| 174 void ExtensionOmniboxEventRouter::OnInputCancelled( | 176 void ExtensionOmniboxEventRouter::OnInputCancelled( |
| 175 Profile* profile, const std::string& extension_id) { | 177 Profile* profile, const std::string& extension_id) { |
| 176 scoped_ptr<Event> event(new Event(events::OMNIBOX_ON_INPUT_CANCELLED, | 178 std::unique_ptr<Event> event(new Event( |
| 177 omnibox::OnInputCancelled::kEventName, | 179 events::OMNIBOX_ON_INPUT_CANCELLED, omnibox::OnInputCancelled::kEventName, |
| 178 make_scoped_ptr(new base::ListValue()))); | 180 base::WrapUnique(new base::ListValue()))); |
| 179 event->restrict_to_browser_context = profile; | 181 event->restrict_to_browser_context = profile; |
| 180 EventRouter::Get(profile) | 182 EventRouter::Get(profile) |
| 181 ->DispatchEventToExtension(extension_id, std::move(event)); | 183 ->DispatchEventToExtension(extension_id, std::move(event)); |
| 182 } | 184 } |
| 183 | 185 |
| 184 OmniboxAPI::OmniboxAPI(content::BrowserContext* context) | 186 OmniboxAPI::OmniboxAPI(content::BrowserContext* context) |
| 185 : profile_(Profile::FromBrowserContext(context)), | 187 : profile_(Profile::FromBrowserContext(context)), |
| 186 url_service_(TemplateURLServiceFactory::GetForProfile(profile_)), | 188 url_service_(TemplateURLServiceFactory::GetForProfile(profile_)), |
| 187 extension_registry_observer_(this) { | 189 extension_registry_observer_(this) { |
| 188 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); | 190 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 } | 278 } |
| 277 | 279 |
| 278 template <> | 280 template <> |
| 279 void BrowserContextKeyedAPIFactory<OmniboxAPI>::DeclareFactoryDependencies() { | 281 void BrowserContextKeyedAPIFactory<OmniboxAPI>::DeclareFactoryDependencies() { |
| 280 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); | 282 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); |
| 281 DependsOn(ExtensionPrefsFactory::GetInstance()); | 283 DependsOn(ExtensionPrefsFactory::GetInstance()); |
| 282 DependsOn(TemplateURLServiceFactory::GetInstance()); | 284 DependsOn(TemplateURLServiceFactory::GetInstance()); |
| 283 } | 285 } |
| 284 | 286 |
| 285 bool OmniboxSendSuggestionsFunction::RunSync() { | 287 bool OmniboxSendSuggestionsFunction::RunSync() { |
| 286 scoped_ptr<SendSuggestions::Params> params( | 288 std::unique_ptr<SendSuggestions::Params> params( |
| 287 SendSuggestions::Params::Create(*args_)); | 289 SendSuggestions::Params::Create(*args_)); |
| 288 EXTENSION_FUNCTION_VALIDATE(params); | 290 EXTENSION_FUNCTION_VALIDATE(params); |
| 289 | 291 |
| 290 content::NotificationService::current()->Notify( | 292 content::NotificationService::current()->Notify( |
| 291 extensions::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY, | 293 extensions::NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY, |
| 292 content::Source<Profile>(GetProfile()->GetOriginalProfile()), | 294 content::Source<Profile>(GetProfile()->GetOriginalProfile()), |
| 293 content::Details<SendSuggestions::Params>(params.get())); | 295 content::Details<SendSuggestions::Params>(params.get())); |
| 294 | 296 |
| 295 return true; | 297 return true; |
| 296 } | 298 } |
| 297 | 299 |
| 298 bool OmniboxSetDefaultSuggestionFunction::RunSync() { | 300 bool OmniboxSetDefaultSuggestionFunction::RunSync() { |
| 299 scoped_ptr<SetDefaultSuggestion::Params> params( | 301 std::unique_ptr<SetDefaultSuggestion::Params> params( |
| 300 SetDefaultSuggestion::Params::Create(*args_)); | 302 SetDefaultSuggestion::Params::Create(*args_)); |
| 301 EXTENSION_FUNCTION_VALIDATE(params); | 303 EXTENSION_FUNCTION_VALIDATE(params); |
| 302 | 304 |
| 303 if (SetOmniboxDefaultSuggestion( | 305 if (SetOmniboxDefaultSuggestion( |
| 304 GetProfile(), extension_id(), params->suggestion)) { | 306 GetProfile(), extension_id(), params->suggestion)) { |
| 305 content::NotificationService::current()->Notify( | 307 content::NotificationService::current()->Notify( |
| 306 extensions::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED, | 308 extensions::NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED, |
| 307 content::Source<Profile>(GetProfile()->GetOriginalProfile()), | 309 content::Source<Profile>(GetProfile()->GetOriginalProfile()), |
| 308 content::NotificationService::NoDetails()); | 310 content::NotificationService::NoDetails()); |
| 309 } | 311 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 return match_classifications; | 363 return match_classifications; |
| 362 } | 364 } |
| 363 | 365 |
| 364 void ApplyDefaultSuggestionForExtensionKeyword( | 366 void ApplyDefaultSuggestionForExtensionKeyword( |
| 365 Profile* profile, | 367 Profile* profile, |
| 366 const TemplateURL* keyword, | 368 const TemplateURL* keyword, |
| 367 const base::string16& remaining_input, | 369 const base::string16& remaining_input, |
| 368 AutocompleteMatch* match) { | 370 AutocompleteMatch* match) { |
| 369 DCHECK(keyword->GetType() == TemplateURL::OMNIBOX_API_EXTENSION); | 371 DCHECK(keyword->GetType() == TemplateURL::OMNIBOX_API_EXTENSION); |
| 370 | 372 |
| 371 scoped_ptr<omnibox::SuggestResult> suggestion( | 373 std::unique_ptr<omnibox::SuggestResult> suggestion( |
| 372 GetOmniboxDefaultSuggestion(profile, keyword->GetExtensionId())); | 374 GetOmniboxDefaultSuggestion(profile, keyword->GetExtensionId())); |
| 373 if (!suggestion || suggestion->description.empty()) | 375 if (!suggestion || suggestion->description.empty()) |
| 374 return; // fall back to the universal default | 376 return; // fall back to the universal default |
| 375 | 377 |
| 376 const base::string16 kPlaceholderText(base::ASCIIToUTF16("%s")); | 378 const base::string16 kPlaceholderText(base::ASCIIToUTF16("%s")); |
| 377 const base::string16 kReplacementText(base::ASCIIToUTF16("<input>")); | 379 const base::string16 kReplacementText(base::ASCIIToUTF16("<input>")); |
| 378 | 380 |
| 379 base::string16 description = base::UTF8ToUTF16(suggestion->description); | 381 base::string16 description = base::UTF8ToUTF16(suggestion->description); |
| 380 ACMatchClassifications& description_styles = match->contents_class; | 382 ACMatchClassifications& description_styles = match->contents_class; |
| 381 description_styles = StyleTypesToACMatchClassifications(*suggestion); | 383 description_styles = StyleTypesToACMatchClassifications(*suggestion); |
| 382 | 384 |
| 383 // Replace "%s" with the user's input and adjust the style offsets to the | 385 // Replace "%s" with the user's input and adjust the style offsets to the |
| 384 // new length of the description. | 386 // new length of the description. |
| 385 size_t placeholder(description.find(kPlaceholderText, 0)); | 387 size_t placeholder(description.find(kPlaceholderText, 0)); |
| 386 if (placeholder != base::string16::npos) { | 388 if (placeholder != base::string16::npos) { |
| 387 base::string16 replacement = | 389 base::string16 replacement = |
| 388 remaining_input.empty() ? kReplacementText : remaining_input; | 390 remaining_input.empty() ? kReplacementText : remaining_input; |
| 389 description.replace(placeholder, kPlaceholderText.length(), replacement); | 391 description.replace(placeholder, kPlaceholderText.length(), replacement); |
| 390 | 392 |
| 391 for (size_t i = 0; i < description_styles.size(); ++i) { | 393 for (size_t i = 0; i < description_styles.size(); ++i) { |
| 392 if (description_styles[i].offset > placeholder) | 394 if (description_styles[i].offset > placeholder) |
| 393 description_styles[i].offset += replacement.length() - 2; | 395 description_styles[i].offset += replacement.length() - 2; |
| 394 } | 396 } |
| 395 } | 397 } |
| 396 | 398 |
| 397 match->contents.assign(description); | 399 match->contents.assign(description); |
| 398 } | 400 } |
| 399 | 401 |
| 400 } // namespace extensions | 402 } // namespace extensions |
| OLD | NEW |