| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/start_page_service.h" | 5 #include "chrome/browser/ui/app_list/start_page_service.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/json/json_string_value_serializer.h" |
| 11 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
| 12 #include "base/metrics/user_metrics.h" | 13 #include "base/metrics/user_metrics.h" |
| 13 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
| 14 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
| 15 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/google/google_profile_helper.h" |
| 16 #include "chrome/browser/media/media_stream_infobar_delegate.h" | 18 #include "chrome/browser/media/media_stream_infobar_delegate.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/search/hotword_service.h" | 20 #include "chrome/browser/search/hotword_service.h" |
| 19 #include "chrome/browser/search/hotword_service_factory.h" | 21 #include "chrome/browser/search/hotword_service_factory.h" |
| 20 #include "chrome/browser/ui/app_list/speech_auth_helper.h" | 22 #include "chrome/browser/ui/app_list/speech_auth_helper.h" |
| 21 #include "chrome/browser/ui/app_list/speech_recognizer.h" | 23 #include "chrome/browser/ui/app_list/speech_recognizer.h" |
| 22 #include "chrome/browser/ui/app_list/start_page_observer.h" | 24 #include "chrome/browser/ui/app_list/start_page_observer.h" |
| 23 #include "chrome/browser/ui/app_list/start_page_service_factory.h" | 25 #include "chrome/browser/ui/app_list/start_page_service_factory.h" |
| 24 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
| 26 #include "chrome/common/url_constants.h" | 28 #include "chrome/common/url_constants.h" |
| 29 #include "components/google/core/browser/google_util.h" |
| 27 #include "components/ui/zoom/zoom_controller.h" | 30 #include "components/ui/zoom/zoom_controller.h" |
| 28 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/notification_details.h" | 32 #include "content/public/browser/notification_details.h" |
| 30 #include "content/public/browser/notification_observer.h" | 33 #include "content/public/browser/notification_observer.h" |
| 31 #include "content/public/browser/notification_registrar.h" | 34 #include "content/public/browser/notification_registrar.h" |
| 32 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_service.h" |
| 33 #include "content/public/browser/notification_source.h" | 36 #include "content/public/browser/notification_source.h" |
| 34 #include "content/public/browser/speech_recognition_session_preamble.h" | 37 #include "content/public/browser/speech_recognition_session_preamble.h" |
| 35 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
| 36 #include "content/public/browser/web_contents_delegate.h" | 39 #include "content/public/browser/web_contents_delegate.h" |
| 37 #include "extensions/browser/extension_system_provider.h" | 40 #include "extensions/browser/extension_system_provider.h" |
| 38 #include "extensions/browser/extensions_browser_client.h" | 41 #include "extensions/browser/extensions_browser_client.h" |
| 39 #include "extensions/common/extension.h" | 42 #include "extensions/common/extension.h" |
| 43 #include "net/base/load_flags.h" |
| 40 #include "net/base/network_change_notifier.h" | 44 #include "net/base/network_change_notifier.h" |
| 45 #include "net/url_request/url_fetcher.h" |
| 41 #include "ui/app_list/app_list_switches.h" | 46 #include "ui/app_list/app_list_switches.h" |
| 42 | 47 |
| 43 #if defined(OS_CHROMEOS) | 48 #if defined(OS_CHROMEOS) |
| 44 #include "chromeos/audio/cras_audio_handler.h" | 49 #include "chromeos/audio/cras_audio_handler.h" |
| 45 #endif | 50 #endif |
| 46 | 51 |
| 47 using base::RecordAction; | 52 using base::RecordAction; |
| 48 using base::UserMetricsAction; | 53 using base::UserMetricsAction; |
| 49 | 54 |
| 50 namespace app_list { | 55 namespace app_list { |
| 51 | 56 |
| 52 namespace { | 57 namespace { |
| 53 | 58 |
| 59 // Path to google.com's doodle JSON. |
| 60 const char kDoodleJsonPath[] = "async/ddljson"; |
| 61 |
| 62 // Delay between checking for a new doodle when no doodle is found. |
| 63 const int kDefaultDoodleRecheckDelayMinutes = 30; |
| 64 |
| 54 bool InSpeechRecognition(SpeechRecognitionState state) { | 65 bool InSpeechRecognition(SpeechRecognitionState state) { |
| 55 return state == SPEECH_RECOGNITION_RECOGNIZING || | 66 return state == SPEECH_RECOGNITION_RECOGNIZING || |
| 56 state == SPEECH_RECOGNITION_IN_SPEECH; | 67 state == SPEECH_RECOGNITION_IN_SPEECH; |
| 57 } | 68 } |
| 58 | 69 |
| 70 GURL GetGoogleBaseURL(Profile* profile) { |
| 71 GURL base_url(google_util::CommandLineGoogleBaseURL()); |
| 72 if (!base_url.is_valid()) |
| 73 base_url = google_profile_helper::GetGoogleHomePageURL(profile); |
| 74 |
| 75 return base_url; |
| 76 } |
| 77 |
| 59 } // namespace | 78 } // namespace |
| 60 | 79 |
| 61 class StartPageService::ProfileDestroyObserver | 80 class StartPageService::ProfileDestroyObserver |
| 62 : public content::NotificationObserver { | 81 : public content::NotificationObserver { |
| 63 public: | 82 public: |
| 64 explicit ProfileDestroyObserver(StartPageService* service) | 83 explicit ProfileDestroyObserver(StartPageService* service) |
| 65 : service_(service) { | 84 : service_(service) { |
| 66 registrar_.Add(this, | 85 registrar_.Add(this, |
| 67 chrome::NOTIFICATION_PROFILE_DESTROYED, | 86 chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 68 content::Source<Profile>(service_->profile())); | 87 content::Source<Profile>(service_->profile())); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 void StartPageService::WebUILoaded() { | 484 void StartPageService::WebUILoaded() { |
| 466 // There's a race condition between the WebUI loading, and calling its JS | 485 // There's a race condition between the WebUI loading, and calling its JS |
| 467 // functions. Specifically, calling LoadContents() doesn't mean that the page | 486 // functions. Specifically, calling LoadContents() doesn't mean that the page |
| 468 // has loaded, but several code paths make this assumption. This function | 487 // has loaded, but several code paths make this assumption. This function |
| 469 // allows us to defer calling JS functions until after the page has finished | 488 // allows us to defer calling JS functions until after the page has finished |
| 470 // loading. | 489 // loading. |
| 471 webui_finished_loading_ = true; | 490 webui_finished_loading_ = true; |
| 472 for (const auto& cb : pending_webui_callbacks_) | 491 for (const auto& cb : pending_webui_callbacks_) |
| 473 cb.Run(); | 492 cb.Run(); |
| 474 pending_webui_callbacks_.clear(); | 493 pending_webui_callbacks_.clear(); |
| 494 |
| 495 FetchDoodleJson(); |
| 475 } | 496 } |
| 476 | 497 |
| 477 void StartPageService::LoadContents() { | 498 void StartPageService::LoadContents() { |
| 478 contents_.reset(content::WebContents::Create( | 499 contents_.reset(content::WebContents::Create( |
| 479 content::WebContents::CreateParams(profile_))); | 500 content::WebContents::CreateParams(profile_))); |
| 480 contents_delegate_.reset(new StartPageWebContentsDelegate()); | 501 contents_delegate_.reset(new StartPageWebContentsDelegate()); |
| 481 contents_->SetDelegate(contents_delegate_.get()); | 502 contents_->SetDelegate(contents_delegate_.get()); |
| 482 | 503 |
| 483 // The ZoomController needs to be created before the web contents is observed | 504 // The ZoomController needs to be created before the web contents is observed |
| 484 // by this object. Otherwise it will react to DidNavigateMainFrame after this | 505 // by this object. Otherwise it will react to DidNavigateMainFrame after this |
| 485 // object does, resetting the zoom mode in the process. | 506 // object does, resetting the zoom mode in the process. |
| 486 ui_zoom::ZoomController::CreateForWebContents(contents_.get()); | 507 ui_zoom::ZoomController::CreateForWebContents(contents_.get()); |
| 487 Observe(contents_.get()); | 508 Observe(contents_.get()); |
| 488 | 509 |
| 489 contents_->GetController().LoadURL( | 510 contents_->GetController().LoadURL( |
| 490 GURL(chrome::kChromeUIAppListStartPageURL), | 511 GURL(chrome::kChromeUIAppListStartPageURL), |
| 491 content::Referrer(), | 512 content::Referrer(), |
| 492 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, | 513 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 493 std::string()); | 514 std::string()); |
| 494 } | 515 } |
| 495 | 516 |
| 496 void StartPageService::UnloadContents() { | 517 void StartPageService::UnloadContents() { |
| 497 contents_.reset(); | 518 contents_.reset(); |
| 498 webui_finished_loading_ = false; | 519 webui_finished_loading_ = false; |
| 499 } | 520 } |
| 500 | 521 |
| 522 void StartPageService::FetchDoodleJson() { |
| 523 // SetPathStr() requires its argument to stay in scope as long as |
| 524 // |replacements| is, so a std::string is needed, instead of a char*. |
| 525 std::string path = kDoodleJsonPath; |
| 526 GURL::Replacements replacements; |
| 527 replacements.SetPathStr(path); |
| 528 |
| 529 GURL doodle_url = GetGoogleBaseURL(profile_).ReplaceComponents(replacements); |
| 530 doodle_fetcher_.reset( |
| 531 net::URLFetcher::Create(0, doodle_url, net::URLFetcher::GET, this)); |
| 532 doodle_fetcher_->SetRequestContext(profile_->GetRequestContext()); |
| 533 doodle_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); |
| 534 doodle_fetcher_->Start(); |
| 535 } |
| 536 |
| 537 void StartPageService::OnURLFetchComplete(const net::URLFetcher* source) { |
| 538 std::string json_data; |
| 539 source->GetResponseAsString(&json_data); |
| 540 |
| 541 // Remove XSSI guard for JSON parsing. |
| 542 size_t json_start_index = json_data.find("{"); |
| 543 if (json_start_index != std::string::npos) |
| 544 json_data.erase(0, json_start_index); |
| 545 |
| 546 JSONStringValueSerializer deserializer(json_data); |
| 547 deserializer.set_allow_trailing_comma(true); |
| 548 int error_code = 0; |
| 549 scoped_ptr<base::Value> doodle_json( |
| 550 deserializer.Deserialize(&error_code, nullptr)); |
| 551 |
| 552 base::TimeDelta recheck_delay = |
| 553 base::TimeDelta::FromMinutes(kDefaultDoodleRecheckDelayMinutes); |
| 554 |
| 555 if (error_code == 0) { |
| 556 base::DictionaryValue* doodle_dictionary = nullptr; |
| 557 // Use the supplied TTL as the recheck delay if available. |
| 558 if (doodle_json->GetAsDictionary(&doodle_dictionary)) { |
| 559 int time_to_live = 0; |
| 560 if (doodle_dictionary->GetInteger("ddljson.time_to_live_ms", |
| 561 &time_to_live)) { |
| 562 recheck_delay = base::TimeDelta::FromMilliseconds(time_to_live); |
| 563 } |
| 564 } |
| 565 |
| 566 contents_->GetWebUI()->CallJavascriptFunction( |
| 567 "appList.startPage.onAppListDoodleUpdated", *doodle_json, |
| 568 base::StringValue(GetGoogleBaseURL(profile_).spec())); |
| 569 } |
| 570 |
| 571 // Check for a new doodle. |
| 572 content::BrowserThread::PostDelayedTask( |
| 573 content::BrowserThread::UI, FROM_HERE, |
| 574 base::Bind(&StartPageService::FetchDoodleJson, |
| 575 weak_factory_.GetWeakPtr()), |
| 576 recheck_delay); |
| 577 } |
| 578 |
| 501 } // namespace app_list | 579 } // namespace app_list |
| OLD | NEW |