Index: chrome/browser/chromeos/app_mode/startup_app_launcher.cc |
=================================================================== |
--- chrome/browser/chromeos/app_mode/startup_app_launcher.cc (revision 246680) |
+++ chrome/browser/chromeos/app_mode/startup_app_launcher.cc (working copy) |
@@ -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" |
@@ -27,10 +29,18 @@ |
#include "chrome/common/chrome_switches.h" |
#include "chrome/common/extensions/extension.h" |
#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.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 "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; |
@@ -47,14 +57,124 @@ |
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) |
: profile_(profile), |
@@ -242,17 +362,33 @@ |
OnLaunchSuccess(); |
} |
-void StartupAppLauncher::BeginInstall() { |
+void StartupAppLauncher::MaybeInstall() { |
FOR_EACH_OBSERVER(Observer, observer_list_, OnInstallingApp()); |
- DVLOG(1) << "BeginInstall... connection = " |
- << net::NetworkChangeNotifier::GetConnectionType(); |
+ update_checker_.reset(new AppUpdateChecker(this)); |
+ update_checker_->Start(); |
+} |
- if (IsAppInstalled(profile_, app_id_)) { |
- OnReadyToLaunch(); |
- return; |
- } |
+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_, |
@@ -272,6 +408,13 @@ |
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; |
} |
@@ -292,10 +435,15 @@ |
DVLOG(1) << "Network up and running!"; |
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
- BeginInstall(); |
+ MaybeInstall(); |
} else { |
DVLOG(1) << "Network not running yet!"; |
} |
} |
+void StartupAppLauncher::UpdateAppData() { |
+ KioskAppManager::Get()->ClearAppData(app_id_); |
+ KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL); |
+} |
+ |
} // namespace chromeos |