diff options
7 files changed, 159 insertions, 204 deletions
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc index c3305b7..c107c06 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc @@ -16,8 +16,7 @@ #include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/updater/manifest_fetch_data.h" -#include "chrome/browser/extensions/updater/safe_manifest_parser.h" +#include "chrome/browser/extensions/updater/extension_updater.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" @@ -61,122 +60,6 @@ const base::FilePath::CharType kOAuthFileName[] = } // 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(); - const Version update_version(update.version); - if (!update_version.IsValid() || - (existing_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, bool diagnostic_mode, @@ -374,27 +257,24 @@ void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { void StartupAppLauncher::MaybeInstall() { delegate_->OnInstallingApp(); - 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); + if (!extension_service->GetInstalledExtension(app_id_)) { + BeginInstall(); + return; + } - OnUpdateCheckNotInstalled(); + extensions::ExtensionUpdater::CheckParams check_params; + check_params.ids.push_back(app_id_); + check_params.install_immediately = true; + check_params.callback = + base::Bind(&StartupAppLauncher::OnUpdateCheckFinished, AsWeakPtr()); + extension_service->updater()->CheckNow(check_params); } -void StartupAppLauncher::OnUpdateCheckNoUpdate() { +void StartupAppLauncher::OnUpdateCheckFinished() { OnReadyToLaunch(); + UpdateAppData(); } void StartupAppLauncher::BeginInstall() { @@ -417,13 +297,6 @@ 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; } diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h index 1a74699..a128c71 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h @@ -79,20 +79,13 @@ class StartupAppLauncher std::string client_secret; }; - // A class to check if the app has an update. It invokes BeginInstall - // if the app is not installed or not up-to-date. Otherwise, it invokes - // OnReadyToLaunch. - class AppUpdateChecker; - void OnLaunchSuccess(); void OnLaunchFailure(KioskAppLaunchError::Error error); void MaybeInstall(); - // Callbacks from AppUpdateChecker - void OnUpdateCheckNotInstalled(); - void OnUpdateCheckUpdateAvailable(); - void OnUpdateCheckNoUpdate(); + // Callbacks from ExtensionUpdater. + void OnUpdateCheckFinished(); void BeginInstall(); void InstallCallback(bool success, const std::string& error); @@ -120,8 +113,6 @@ class StartupAppLauncher scoped_refptr<extensions::WebstoreStandaloneInstaller> installer_; KioskOAuthParams auth_params_; - scoped_ptr<AppUpdateChecker> update_checker_; - DISALLOW_COPY_AND_ASSIGN(StartupAppLauncher); }; diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 4550b1f..1bb019b 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc @@ -9,6 +9,7 @@ #include "ash/desktop_background/desktop_background_controller_observer.h" #include "ash/shell.h" #include "base/path_service.h" +#include "base/strings/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" @@ -37,6 +38,13 @@ #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_switches.h" #include "google_apis/gaia/gaia_urls.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" + +using net::test_server::BasicHttpResponse; +using net::test_server::HttpRequest; +using net::test_server::HttpResponse; namespace em = enterprise_management; @@ -619,55 +627,6 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchInDiagnosticMode) { WaitForAppLaunchSuccess(); } -IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppNoNetwork) { - set_test_app_id(kTestOfflineEnabledKioskApp); - SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); - - PrepareAppLaunch(); - SimulateNetworkOffline(); - - LaunchApp(test_app_id(), false); - WaitForAppLaunchSuccess(); -} - -IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppNoUpdate) { - set_test_app_id(kTestOfflineEnabledKioskApp); - SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); - - GURL webstore_url = GetTestWebstoreUrl(); - CommandLine::ForCurrentProcess()->AppendSwitchASCII( - ::switches::kAppsGalleryUpdateURL, - webstore_url.Resolve( - "/chromeos/app_mode/webstore/update_check/no_update.xml").spec()); - - PrepareAppLaunch(); - SimulateNetworkOnline(); - - LaunchApp(test_app_id(), false); - WaitForAppLaunchSuccess(); - - EXPECT_EQ("1.0.0", GetInstalledAppVersion().GetString()); -} - -IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppHasUpdate) { - set_test_app_id(kTestOfflineEnabledKioskApp); - SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); - - GURL webstore_url = GetTestWebstoreUrl(); - CommandLine::ForCurrentProcess()->AppendSwitchASCII( - ::switches::kAppsGalleryUpdateURL, - webstore_url.Resolve( - "/chromeos/app_mode/webstore/update_check/has_update.xml").spec()); - - PrepareAppLaunch(); - SimulateNetworkOnline(); - - LaunchApp(test_app_id(), false); - WaitForAppLaunchSuccess(); - - EXPECT_EQ("2.0.0", GetInstalledAppVersion().GetString()); -} - IN_PROC_BROWSER_TEST_F(KioskTest, AutolaunchWarningCancel) { EnableConsumerKioskMode(); // Start UI, find menu entry for this app and launch it. @@ -893,6 +852,132 @@ IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableAfter2ndSigninScreen) { content::NotificationService::AllSources()).Wait(); } +class KioskUpdateTest : public KioskTest { + public: + KioskUpdateTest() {} + virtual ~KioskUpdateTest() {} + + protected: + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + // Needs background networking so that ExtensionDownloader works. + needs_background_networking_ = true; + + KioskTest::SetUpCommandLine(command_line); + } + + virtual void SetUpOnMainThread() OVERRIDE { + KioskTest::SetUpOnMainThread(); + + GURL webstore_url = GetTestWebstoreUrl(); + CommandLine::ForCurrentProcess()->AppendSwitchASCII( + ::switches::kAppsGalleryUpdateURL, + webstore_url.Resolve("/update_check.xml").spec()); + + embedded_test_server()->RegisterRequestHandler( + base::Bind(&KioskUpdateTest::HandleRequest, + base::Unretained(this))); + } + + void SetUpdateCheckContent(const std::string& update_check_file, + const std::string& app_id, + const GURL& crx_download_url, + const std::string& crx_fp, + const std::string& crx_size, + const std::string& version) { + base::FilePath test_data_dir; + PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); + base::FilePath update_file = + test_data_dir.AppendASCII(update_check_file.c_str()); + ASSERT_TRUE(base::ReadFileToString(update_file, &update_check_content_)); + + ReplaceSubstringsAfterOffset(&update_check_content_, 0, "$AppId", app_id); + ReplaceSubstringsAfterOffset( + &update_check_content_, 0, "$CrxDownloadUrl", crx_download_url.spec()); + ReplaceSubstringsAfterOffset(&update_check_content_, 0, "$FP", crx_fp); + ReplaceSubstringsAfterOffset(&update_check_content_, 0, "$Size", crx_size); + ReplaceSubstringsAfterOffset( + &update_check_content_, 0, "$Version", version); + } + + private: + scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { + GURL request_url = GURL("http://localhost").Resolve(request.relative_url); + std::string request_path = request_url.path(); + if (!update_check_content_.empty() && + request_path == "/update_check.xml") { + scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); + http_response->set_code(net::HTTP_OK); + http_response->set_content_type("text/xml"); + http_response->set_content(update_check_content_); + return http_response.PassAs<HttpResponse>(); + } + + return scoped_ptr<HttpResponse>(); + } + + std::string update_check_content_; + + DISALLOW_COPY_AND_ASSIGN(KioskUpdateTest); +}; + +IN_PROC_BROWSER_TEST_F(KioskUpdateTest, LaunchOfflineEnabledAppNoNetwork) { + set_test_app_id(kTestOfflineEnabledKioskApp); + SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); + + PrepareAppLaunch(); + SimulateNetworkOffline(); + + LaunchApp(test_app_id(), false); + WaitForAppLaunchSuccess(); +} + +IN_PROC_BROWSER_TEST_F(KioskUpdateTest, LaunchOfflineEnabledAppNoUpdate) { + set_test_app_id(kTestOfflineEnabledKioskApp); + SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); + + SetUpdateCheckContent( + "chromeos/app_mode/webstore/update_check/no_update.xml", + kTestOfflineEnabledKioskApp, + GURL(), + "", + "", + ""); + + PrepareAppLaunch(); + SimulateNetworkOnline(); + + LaunchApp(test_app_id(), false); + WaitForAppLaunchSuccess(); + + EXPECT_EQ("1.0.0", GetInstalledAppVersion().GetString()); +} + +IN_PROC_BROWSER_TEST_F(KioskUpdateTest, LaunchOfflineEnabledAppHasUpdate) { + set_test_app_id(kTestOfflineEnabledKioskApp); + SetupAppProfile("chromeos/app_mode/offline_enabled_app_profile"); + + GURL webstore_url = GetTestWebstoreUrl(); + GURL crx_download_url = webstore_url.Resolve( + "/chromeos/app_mode/webstore/downloads/" + "ajoggoflpgplnnjkjamcmbepjdjdnpdp.crx"); + + SetUpdateCheckContent( + "chromeos/app_mode/webstore/update_check/has_update.xml", + kTestOfflineEnabledKioskApp, + crx_download_url, + "ca08d1d120429f49a2b5b1d4db67ce4234390f0758b580e25fba5226a0526209", + "2294", + "2.0.0"); + + PrepareAppLaunch(); + SimulateNetworkOnline(); + + LaunchApp(test_app_id(), false); + WaitForAppLaunchSuccess(); + + EXPECT_EQ("2.0.0", GetInstalledAppVersion().GetString()); +} + class KioskEnterpriseTest : public KioskTest { protected: KioskEnterpriseTest() {} diff --git a/chrome/browser/chromeos/login/oobe_base_test.cc b/chrome/browser/chromeos/login/oobe_base_test.cc index 26d53b5..6cff4f3 100644 --- a/chrome/browser/chromeos/login/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/oobe_base_test.cc @@ -36,7 +36,8 @@ const char kStubEthernetServicePath[] = "eth1"; OobeBaseTest::OobeBaseTest() : fake_gaia_(new FakeGaia()), - network_portal_detector_(NULL) { + network_portal_detector_(NULL), + needs_background_networking_(false) { set_exit_when_last_browser_closes(false); set_chromeos_user_ = false; } @@ -90,7 +91,8 @@ void OobeBaseTest::SetUpCommandLine(CommandLine* command_line) { ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitch(chromeos::switches::kLoginManager); command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); - command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); + if (!needs_background_networking_) + command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); // Create gaia and webstore URL from test server url but using different diff --git a/chrome/browser/chromeos/login/oobe_base_test.h b/chrome/browser/chromeos/login/oobe_base_test.h index f40fe4d..ae36c3b 100644 --- a/chrome/browser/chromeos/login/oobe_base_test.h +++ b/chrome/browser/chromeos/login/oobe_base_test.h @@ -64,6 +64,10 @@ class OobeBaseTest : public ExtensionApiTest { scoped_ptr<FakeGaia> fake_gaia_; NetworkPortalDetectorTestImpl* network_portal_detector_; + + // Whether to use background networking. Note this is only effective when it + // is set before SetUpCommandLine is invoked. + bool needs_background_networking_; }; } // namespace chromeos diff --git a/chrome/test/data/chromeos/app_mode/webstore/update_check/has_update.xml b/chrome/test/data/chromeos/app_mode/webstore/update_check/has_update.xml index a1c9c4b..3d7ae43 100644 --- a/chrome/test/data/chromeos/app_mode/webstore/update_check/has_update.xml +++ b/chrome/test/data/chromeos/app_mode/webstore/update_check/has_update.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="2569" elapsed_seconds="36478"/><app appid="ajoggoflpgplnnjkjamcmbepjdjdnpdp" status="ok"><updatecheck codebase="https://webstore/chromeos/app_mode/webstore/downloads/ajoggoflpgplnnjkjamcmbepjdjdnpdp.crx" fp="1.ca08d1d120429f49a2b5b1d4db67ce4234390f0758b580e25fba5226a0526209" hash="" hash_sha256="ca08d1d120429f49a2b5b1d4db67ce4234390f0758b580e25fba5226a0526209" size="2294" status="ok" version="2.0.0"/></app></gupdate> +<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="2569" elapsed_seconds="36478"/><app appid="$AppId" status="ok"><updatecheck codebase="$CrxDownloadUrl" fp="1.$FP" hash="" hash_sha256="$FP" size="$Size" status="ok" version="$Version"/></app></gupdate> diff --git a/chrome/test/data/chromeos/app_mode/webstore/update_check/no_update.xml b/chrome/test/data/chromeos/app_mode/webstore/update_check/no_update.xml index ec8cb7f..f2648f0 100644 --- a/chrome/test/data/chromeos/app_mode/webstore/update_check/no_update.xml +++ b/chrome/test/data/chromeos/app_mode/webstore/update_check/no_update.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="2569" elapsed_seconds="35454"/><app appid="ajoggoflpgplnnjkjamcmbepjdjdnpdp" status="ok"><updatecheck status="noupdate"/></app></gupdate> +<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="2569" elapsed_seconds="35454"/><app appid="$AppId" status="ok"><updatecheck status="noupdate"/></app></gupdate> |