| 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..8561504d7f5c18da08210027a64f2c63521239ab 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,123 @@ 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);
|
| + if (update_url.is_empty())
|
| + update_url = extension_urls::GetWebstoreUpdateUrl();
|
| + if (!update_url.is_valid()) {
|
| + launcher_->OnUpdateCheckNoUpdate();
|
| + return;
|
| + }
|
| +
|
| + 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 +200,7 @@ void StartupAppLauncher::ContinueWithNetworkReady() {
|
| // Starts install if it is not started.
|
| if (!install_attempted_) {
|
| install_attempted_ = true;
|
| - BeginInstall();
|
| + MaybeInstall();
|
| }
|
| }
|
|
|
| @@ -183,17 +303,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 +334,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 +391,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 +410,9 @@ void StartupAppLauncher::OnReadyToLaunch() {
|
| delegate_->OnReadyToLaunch();
|
| }
|
|
|
| +void StartupAppLauncher::UpdateAppData() {
|
| + KioskAppManager::Get()->ClearAppData(app_id_);
|
| + KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
|
| +}
|
| +
|
| } // namespace chromeos
|
|
|