Chromium Code Reviews| Index: chrome/browser/chromeos/app_mode/startup_app_launcher.cc |
| diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc |
| index 1339567b1a7206c6469f95d1ee03c814fb1bd3b2..f7bd39c031826a3a1141e3c96ad6a8ed13dd34ad 100644 |
| --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc |
| +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc |
| @@ -16,6 +16,8 @@ |
| #include "chrome/browser/chromeos/login/user_manager.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| +#include "chrome/browser/extensions/updater/manifest_fetch_data.h" |
| +#include "chrome/browser/extensions/updater/safe_manifest_parser.h" |
| #include "chrome/browser/extensions/webstore_startup_installer.h" |
| #include "chrome/browser/lifetime/application_lifetime.h" |
| #include "chrome/browser/signin/profile_oauth2_token_service.h" |
| @@ -23,12 +25,20 @@ |
| #include "chrome/browser/ui/extensions/application_launch.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| +#include "chrome/common/chrome_version_info.h" |
| +#include "chrome/common/extensions/manifest_url_handler.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/notification_service.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/manifest_handlers/kiosk_mode_info.h" |
| #include "google_apis/gaia/gaia_auth_consumer.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/url_request/url_fetcher.h" |
| +#include "net/url_request/url_fetcher_delegate.h" |
| +#include "net/url_request/url_request_context_getter.h" |
| +#include "net/url_request/url_request_status.h" |
| +#include "url/gurl.h" |
| using content::BrowserThread; |
| using extensions::Extension; |
| @@ -45,13 +55,116 @@ const char kOAuthClientSecret[] = "client_secret"; |
| const base::FilePath::CharType kOAuthFileName[] = |
| FILE_PATH_LITERAL("kiosk_auth"); |
| -bool IsAppInstalled(Profile* profile, const std::string& app_id) { |
| - return extensions::ExtensionSystem::Get(profile)->extension_service()-> |
| - GetInstalledExtension(app_id); |
| -} |
| - |
| } // namespace |
| +class StartupAppLauncher::AppUpdateChecker |
| + : public base::SupportsWeakPtr<AppUpdateChecker>, |
| + public net::URLFetcherDelegate { |
| + public: |
| + explicit AppUpdateChecker(StartupAppLauncher* launcher) |
| + : launcher_(launcher), |
| + profile_(launcher->profile_), |
| + app_id_(launcher->app_id_) {} |
| + virtual ~AppUpdateChecker() {} |
| + |
| + void Start() { |
| + const Extension* app = GetInstalledApp(); |
| + if (!app) { |
| + launcher_->OnUpdateCheckNotInstalled(); |
| + return; |
| + } |
| + |
| + GURL update_url = extensions::ManifestURL::GetUpdateURL(app); |
| + manifest_fetch_data_.reset( |
| + new extensions::ManifestFetchData(update_url, 0)); |
| + manifest_fetch_data_->AddExtension( |
| + app_id_, app->version()->GetString(), NULL, "", ""); |
| + |
| + manifest_fetcher_.reset(net::URLFetcher::Create( |
| + manifest_fetch_data_->full_url(), net::URLFetcher::GET, this)); |
| + manifest_fetcher_->SetRequestContext(profile_->GetRequestContext()); |
| + manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| + net::LOAD_DO_NOT_SAVE_COOKIES | |
| + net::LOAD_DISABLE_CACHE); |
| + manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| + manifest_fetcher_->Start(); |
| + } |
| + |
| + private: |
| + const Extension* GetInstalledApp() { |
| + ExtensionService* extension_service = |
| + extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| + return extension_service->GetInstalledExtension(app_id_); |
| + } |
| + |
| + void HandleManifestResults(const extensions::ManifestFetchData& fetch_data, |
| + const UpdateManifest::Results* results) { |
| + if (!results || results->list.empty()) { |
| + launcher_->OnUpdateCheckNoUpdate(); |
| + return; |
| + } |
| + |
| + DCHECK_EQ(1u, results->list.size()); |
| + |
| + const UpdateManifest::Result& update = results->list[0]; |
| + |
| + if (update.browser_min_version.length() > 0) { |
| + Version browser_version; |
| + chrome::VersionInfo version_info; |
| + if (version_info.is_valid()) |
| + browser_version = Version(version_info.Version()); |
| + |
| + Version browser_min_version(update.browser_min_version); |
| + if (browser_version.IsValid() && |
| + browser_min_version.IsValid() && |
| + browser_min_version.CompareTo(browser_version) > 0) { |
| + launcher_->OnUpdateCheckNoUpdate(); |
| + return; |
| + } |
| + } |
| + |
| + const Version& existing_version = *GetInstalledApp()->version(); |
| + Version update_version(update.version); |
| + if (existing_version.IsValid() && |
| + update_version.IsValid() && |
| + update_version.CompareTo(existing_version) <= 0) { |
| + launcher_->OnUpdateCheckNoUpdate(); |
| + return; |
| + } |
| + |
| + launcher_->OnUpdateCheckUpdateAvailable(); |
| + } |
| + |
| + // net::URLFetcherDelegate implementation. |
| + virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { |
| + DCHECK_EQ(source, manifest_fetcher_.get()); |
| + |
| + if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS || |
| + source->GetResponseCode() != 200) { |
| + launcher_->OnUpdateCheckNoUpdate(); |
| + return; |
| + } |
| + |
| + std::string data; |
| + source->GetResponseAsString(&data); |
| + scoped_refptr<extensions::SafeManifestParser> safe_parser( |
| + new extensions::SafeManifestParser( |
| + data, |
| + manifest_fetch_data_.release(), |
| + base::Bind(&AppUpdateChecker::HandleManifestResults, |
| + AsWeakPtr()))); |
| + safe_parser->Start(); |
| + } |
| + |
| + StartupAppLauncher* launcher_; |
| + Profile* profile_; |
| + const std::string app_id_; |
| + |
| + scoped_ptr<extensions::ManifestFetchData> manifest_fetch_data_; |
| + scoped_ptr<net::URLFetcher> manifest_fetcher_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AppUpdateChecker); |
| +}; |
| StartupAppLauncher::StartupAppLauncher(Profile* profile, |
| const std::string& app_id, |
| @@ -80,7 +193,7 @@ void StartupAppLauncher::ContinueWithNetworkReady() { |
| // Starts install if it is not started. |
| if (!install_attempted_) { |
| install_attempted_ = true; |
| - BeginInstall(); |
| + MaybeInstall(); |
| } |
| } |
| @@ -183,17 +296,6 @@ void StartupAppLauncher::OnRefreshTokensLoaded() { |
| InitializeNetwork(); |
| } |
| -void StartupAppLauncher::OnLaunchSuccess() { |
| - delegate_->OnLaunchSucceeded(); |
| -} |
| - |
| -void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { |
| - LOG(ERROR) << "App launch failed, error: " << error; |
| - DCHECK_NE(KioskAppLaunchError::NONE, error); |
| - |
| - delegate_->OnLaunchFailed(error); |
| -} |
| - |
| void StartupAppLauncher::LaunchApp() { |
| if (!ready_to_launch_) { |
| NOTREACHED(); |
| @@ -225,14 +327,44 @@ void StartupAppLauncher::LaunchApp() { |
| OnLaunchSuccess(); |
| } |
| -void StartupAppLauncher::BeginInstall() { |
| +void StartupAppLauncher::OnLaunchSuccess() { |
| + delegate_->OnLaunchSucceeded(); |
| +} |
| + |
| +void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { |
| + LOG(ERROR) << "App launch failed, error: " << error; |
| + DCHECK_NE(KioskAppLaunchError::NONE, error); |
| + |
| + delegate_->OnLaunchFailed(error); |
| +} |
| + |
| +void StartupAppLauncher::MaybeInstall() { |
| delegate_->OnInstallingApp(); |
| - if (IsAppInstalled(profile_, app_id_)) { |
| - OnReadyToLaunch(); |
| - return; |
| - } |
| + update_checker_.reset(new AppUpdateChecker(this)); |
| + update_checker_->Start(); |
| +} |
| + |
| +void StartupAppLauncher::OnUpdateCheckNotInstalled() { |
| + BeginInstall(); |
| +} |
| +void StartupAppLauncher::OnUpdateCheckUpdateAvailable() { |
| + // Uninstall to force a re-install. |
| + // TODO(xiyuan): Find a better way. Either download CRX and install it |
| + // directly or integrate with ExtensionUpdater in someway. |
| + ExtensionService* extension_service = |
| + extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| + extension_service->UninstallExtension(app_id_, false, NULL); |
| + |
| + OnUpdateCheckNotInstalled(); |
| +} |
| + |
| +void StartupAppLauncher::OnUpdateCheckNoUpdate() { |
| + OnReadyToLaunch(); |
| +} |
| + |
| +void StartupAppLauncher::BeginInstall() { |
| installer_ = new WebstoreStartupInstaller( |
| app_id_, |
| profile_, |
| @@ -252,6 +384,13 @@ void StartupAppLauncher::InstallCallback(bool success, |
| FROM_HERE, |
| base::Bind(&StartupAppLauncher::OnReadyToLaunch, |
| AsWeakPtr())); |
| + |
| + // Schedule app data update after installation. |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind(&StartupAppLauncher::UpdateAppData, |
| + AsWeakPtr())); |
| return; |
| } |
| @@ -264,4 +403,8 @@ void StartupAppLauncher::OnReadyToLaunch() { |
| delegate_->OnReadyToLaunch(); |
| } |
| +void StartupAppLauncher::UpdateAppData() { |
|
Tim Song
2014/01/13 23:41:08
Can't hurt to call ClearAppData here as well.
xiyuan
2014/01/14 00:15:07
Done.
|
| + KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL); |
| +} |
| + |
| } // namespace chromeos |