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/ui/app_list/search_builder.h" | 5 #include "chrome/browser/ui/app_list/search_builder.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "ui/app_list/search_box_model.h" | 34 #include "ui/app_list/search_box_model.h" |
35 #include "ui/app_list/search_result.h" | 35 #include "ui/app_list/search_result.h" |
36 #include "ui/base/l10n/l10n_util.h" | 36 #include "ui/base/l10n/l10n_util.h" |
37 #include "ui/base/resource/resource_bundle.h" | 37 #include "ui/base/resource/resource_bundle.h" |
38 | 38 |
39 #if defined(OS_CHROMEOS) | 39 #if defined(OS_CHROMEOS) |
40 #include "base/memory/ref_counted.h" | 40 #include "base/memory/ref_counted.h" |
41 #include "chrome/browser/autocomplete/contact_provider_chromeos.h" | 41 #include "chrome/browser/autocomplete/contact_provider_chromeos.h" |
42 #include "chrome/browser/chromeos/contacts/contact.pb.h" | 42 #include "chrome/browser/chromeos/contacts/contact.pb.h" |
43 #include "chrome/browser/chromeos/contacts/contact_manager.h" | 43 #include "chrome/browser/chromeos/contacts/contact_manager.h" |
| 44 #include "chrome/browser/extensions/api/rtc_private/rtc_private_api.h" |
44 #include "chrome/browser/image_decoder.h" | 45 #include "chrome/browser/image_decoder.h" |
45 #include "chrome/common/chrome_switches.h" | 46 #include "chrome/common/chrome_switches.h" |
46 #endif | 47 #endif |
47 | 48 |
48 namespace { | 49 namespace { |
49 | 50 |
50 int ACMatchStyleToTagStyle(int styles) { | 51 int ACMatchStyleToTagStyle(int styles) { |
51 int tag_styles = 0; | 52 int tag_styles = 0; |
52 if (styles & ACMatchClassification::URL) | 53 if (styles & ACMatchClassification::URL) |
53 tag_styles |= app_list::SearchResult::Tag::URL; | 54 tag_styles |= app_list::SearchResult::Tag::URL; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 service->GetInstalledApp(url); | 102 service->GetInstalledApp(url); |
102 } | 103 } |
103 | 104 |
104 // SearchBuildResult is an app list SearchResult built from an | 105 // SearchBuildResult is an app list SearchResult built from an |
105 // AutocompleteMatch. | 106 // AutocompleteMatch. |
106 class SearchBuilderResult : public app_list::SearchResult { | 107 class SearchBuilderResult : public app_list::SearchResult { |
107 public: | 108 public: |
108 SearchBuilderResult() : profile_(NULL) {} | 109 SearchBuilderResult() : profile_(NULL) {} |
109 virtual ~SearchBuilderResult() {} | 110 virtual ~SearchBuilderResult() {} |
110 | 111 |
111 Profile* profile() { return profile_; } | 112 Profile* profile() const { return profile_; } |
112 const AutocompleteMatch& match() const { return match_; } | 113 const AutocompleteMatch& match() const { return match_; } |
113 | 114 |
114 virtual void Init(Profile* profile, const AutocompleteMatch& match) { | 115 virtual void Init(Profile* profile, const AutocompleteMatch& match) { |
115 profile_ = profile; | 116 profile_ = profile; |
116 match_ = match; | 117 match_ = match; |
117 UpdateIcon(); | 118 UpdateIcon(); |
118 UpdateTitleAndDetails(); | 119 UpdateTitleAndDetails(); |
119 } | 120 } |
120 | 121 |
121 protected: | 122 protected: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 class ContactResult : public SearchBuilderResult, | 199 class ContactResult : public SearchBuilderResult, |
199 public ImageDecoder::Delegate { | 200 public ImageDecoder::Delegate { |
200 public: | 201 public: |
201 ContactResult() {} | 202 ContactResult() {} |
202 | 203 |
203 virtual ~ContactResult() { | 204 virtual ~ContactResult() { |
204 if (photo_decoder_.get()) | 205 if (photo_decoder_.get()) |
205 photo_decoder_->set_delegate(NULL); | 206 photo_decoder_->set_delegate(NULL); |
206 } | 207 } |
207 | 208 |
| 209 // Returns the contact represented by this result, or NULL if the contact |
| 210 // can't be found (e.g. it's been deleted in the meantime). The returned |
| 211 // object is only valid until the UI message loop continues running. |
| 212 const contacts::Contact* GetContact() const { |
| 213 AutocompleteMatch::AdditionalInfo::const_iterator it = |
| 214 match().additional_info.find(ContactProvider::kMatchContactIdKey); |
| 215 DCHECK(it != match().additional_info.end()); |
| 216 return contacts::ContactManager::GetInstance()->GetContactById( |
| 217 profile(), it->second); |
| 218 } |
| 219 |
| 220 // Overridden from SearchBuilderResult: |
208 virtual void Init(Profile* profile, const AutocompleteMatch& match) OVERRIDE { | 221 virtual void Init(Profile* profile, const AutocompleteMatch& match) OVERRIDE { |
209 SearchBuilderResult::Init(profile, match); | 222 SearchBuilderResult::Init(profile, match); |
210 | 223 |
211 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 224 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
212 std::vector<app_list::SearchResult::ActionIconSet> icons; | 225 std::vector<app_list::SearchResult::ActionIconSet> icons; |
213 icons.push_back( | 226 icons.push_back( |
214 app_list::SearchResult::ActionIconSet( | 227 app_list::SearchResult::ActionIconSet( |
215 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT), | 228 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT), |
216 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT_H), | 229 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT_H), |
217 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT), | 230 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_CHAT), |
(...skipping 13 matching lines...) Expand all Loading... |
231 icons.push_back( | 244 icons.push_back( |
232 app_list::SearchResult::ActionIconSet( | 245 app_list::SearchResult::ActionIconSet( |
233 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL), | 246 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL), |
234 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL_H), | 247 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL_H), |
235 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL), | 248 *bundle.GetImageSkiaNamed(IDR_CONTACT_ACTION_EMAIL), |
236 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTACT_EMAIL_TOOLTIP))); | 249 l10n_util::GetStringUTF16(IDS_APP_LIST_CONTACT_EMAIL_TOOLTIP))); |
237 SetActionIcons(icons); | 250 SetActionIcons(icons); |
238 } | 251 } |
239 | 252 |
240 protected: | 253 protected: |
| 254 // Overridden from SearchBuilderResult: |
241 virtual void UpdateIcon() OVERRIDE { | 255 virtual void UpdateIcon() OVERRIDE { |
242 AutocompleteMatch::AdditionalInfo::const_iterator it = | 256 const contacts::Contact* contact = GetContact(); |
243 match().additional_info.find(ContactProvider::kMatchContactIdKey); | |
244 DCHECK(it != match().additional_info.end()); | |
245 const contacts::Contact* contact = | |
246 contacts::ContactManager::GetInstance()->GetContactById( | |
247 profile(), it->second); | |
248 if (contact && contact->has_raw_untrusted_photo()) { | 257 if (contact && contact->has_raw_untrusted_photo()) { |
249 photo_decoder_ = | 258 photo_decoder_ = |
250 new ImageDecoder( | 259 new ImageDecoder( |
251 this, | 260 this, |
252 contact->raw_untrusted_photo(), | 261 contact->raw_untrusted_photo(), |
253 ImageDecoder::DEFAULT_CODEC); | 262 ImageDecoder::DEFAULT_CODEC); |
254 photo_decoder_->Start(); | 263 photo_decoder_->Start(); |
255 } else { | 264 } else { |
256 SetIcon( | 265 SetIcon( |
257 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 266 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 if (match.type == AutocompleteMatch::EXTENSION_APP) { | 346 if (match.type == AutocompleteMatch::EXTENSION_APP) { |
338 const extensions::Extension* extension = | 347 const extensions::Extension* extension = |
339 GetExtensionByURL(profile_, match.destination_url); | 348 GetExtensionByURL(profile_, match.destination_url); |
340 if (extension) { | 349 if (extension) { |
341 content::RecordAction( | 350 content::RecordAction( |
342 content::UserMetricsAction("AppList_ClickOnAppFromSearch")); | 351 content::UserMetricsAction("AppList_ClickOnAppFromSearch")); |
343 list_controller_->ActivateApp(profile_, extension->id(), event_flags); | 352 list_controller_->ActivateApp(profile_, extension->id(), event_flags); |
344 } | 353 } |
345 #if defined(OS_CHROMEOS) | 354 #if defined(OS_CHROMEOS) |
346 } else if (match.type == AutocompleteMatch::CONTACT) { | 355 } else if (match.type == AutocompleteMatch::CONTACT) { |
347 NOTIMPLEMENTED(); | 356 // Pass 0 for |action_index| to trigger a chat request. |
| 357 InvokeResultAction(result, 0, event_flags); |
348 #endif | 358 #endif |
349 } else { | 359 } else { |
350 // TODO(xiyuan): What should we do for alternate url case? | 360 // TODO(xiyuan): What should we do for alternate url case? |
351 chrome::NavigateParams params(profile_, | 361 chrome::NavigateParams params(profile_, |
352 match.destination_url, | 362 match.destination_url, |
353 match.transition); | 363 match.transition); |
354 params.disposition = chrome::DispositionFromEventFlags(event_flags); | 364 params.disposition = chrome::DispositionFromEventFlags(event_flags); |
355 chrome::Navigate(¶ms); | 365 chrome::Navigate(¶ms); |
356 } | 366 } |
357 } | 367 } |
358 | 368 |
359 void SearchBuilder::InvokeResultAction(const app_list::SearchResult& result, | 369 void SearchBuilder::InvokeResultAction(const app_list::SearchResult& result, |
360 int action_index, | 370 int action_index, |
361 int event_flags) { | 371 int event_flags) { |
| 372 const SearchBuilderResult* builder_result = |
| 373 static_cast<const SearchBuilderResult*>(&result); |
| 374 const AutocompleteMatch& match = builder_result->match(); |
| 375 |
| 376 #if defined(OS_CHROMEOS) |
| 377 if (match.type == AutocompleteMatch::CONTACT) { |
| 378 const contacts::Contact* contact = |
| 379 static_cast<const ContactResult*>(builder_result)->GetContact(); |
| 380 if (!contact) |
| 381 return; |
| 382 |
| 383 // Cases match the order in which actions were added in |
| 384 // ContactResult::Init(). |
| 385 extensions::RtcPrivateEventRouter::LaunchAction launch_action = |
| 386 extensions::RtcPrivateEventRouter::LAUNCH_CHAT; |
| 387 switch (action_index) { |
| 388 case 0: |
| 389 launch_action = extensions::RtcPrivateEventRouter::LAUNCH_CHAT; |
| 390 break; |
| 391 case 1: |
| 392 launch_action = extensions::RtcPrivateEventRouter::LAUNCH_VIDEO; |
| 393 break; |
| 394 case 2: |
| 395 launch_action = extensions::RtcPrivateEventRouter::LAUNCH_VOICE; |
| 396 break; |
| 397 case 3: |
| 398 // TODO(derat): Send email. |
| 399 NOTIMPLEMENTED(); |
| 400 break; |
| 401 default: |
| 402 NOTREACHED() << "Unexpected action index " << action_index; |
| 403 } |
| 404 |
| 405 extensions::RtcPrivateEventRouter::DispatchLaunchEvent( |
| 406 builder_result->profile(), launch_action, contact); |
| 407 return; |
| 408 } |
| 409 #endif |
| 410 |
362 NOTIMPLEMENTED(); | 411 NOTIMPLEMENTED(); |
363 } | 412 } |
364 | 413 |
365 void SearchBuilder::PopulateFromACResult(const AutocompleteResult& ac_result) { | 414 void SearchBuilder::PopulateFromACResult(const AutocompleteResult& ac_result) { |
366 results_->DeleteAll(); | 415 results_->DeleteAll(); |
367 for (ACMatches::const_iterator it = ac_result.begin(); | 416 for (ACMatches::const_iterator it = ac_result.begin(); |
368 it != ac_result.end(); | 417 it != ac_result.end(); |
369 ++it) { | 418 ++it) { |
370 SearchBuilderResult* result = NULL; | 419 SearchBuilderResult* result = NULL; |
371 switch (it->type) { | 420 switch (it->type) { |
(...skipping 11 matching lines...) Expand all Loading... |
383 result->Init(profile_, *it); | 432 result->Init(profile_, *it); |
384 results_->Add(result); | 433 results_->Add(result); |
385 } | 434 } |
386 } | 435 } |
387 | 436 |
388 void SearchBuilder::OnResultChanged(bool default_match_changed) { | 437 void SearchBuilder::OnResultChanged(bool default_match_changed) { |
389 // TODO(xiyuan): Handle default match properly. | 438 // TODO(xiyuan): Handle default match properly. |
390 const AutocompleteResult& ac_result = controller_->result(); | 439 const AutocompleteResult& ac_result = controller_->result(); |
391 PopulateFromACResult(ac_result); | 440 PopulateFromACResult(ac_result); |
392 } | 441 } |
OLD | NEW |