diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index 7bca13ed8781a..b51f66bdaee4b 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc @@ -562,6 +562,7 @@ KioskAppManager::KioskAppManager() this, true /* always_check_updates */, false /* wait_for_cache_initialization */)); + external_cache_->set_flush_on_put(true); UpdateAppData(); local_accounts_subscription_ = CrosSettings::Get()->AddSettingsObserver( diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc index 01e9c9fb1f179..151562451ca3f 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc @@ -34,6 +34,7 @@ #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" +#include "extensions/common/file_util.h" #include "extensions/common/manifest_handlers/kiosk_mode_info.h" #include "extensions/common/manifest_handlers/offline_enabled_info.h" #include "extensions/common/manifest_url_handlers.h" @@ -435,6 +436,7 @@ void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { } void StartupAppLauncher::BeginInstall() { + extensions::file_util::SetUseSafeInstallation(true); KioskAppManager::Get()->InstallFromCache(app_id_); if (extensions::ExtensionSystem::Get(profile_) ->extension_service() diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc index df59b97f6abc9..04433b15e7710 100644 --- a/chrome/browser/chromeos/extensions/external_cache.cc +++ b/chrome/browser/chromeos/extensions/external_cache.cc @@ -28,6 +28,16 @@ namespace chromeos { +namespace { + +void FlushFile(const base::FilePath& path) { + base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_WRITE); + file.Flush(); + file.Close(); +} + +} // namespace + ExternalCache::ExternalCache(const base::FilePath& cache_dir, net::URLRequestContextGetter* request_context, const scoped_refptr& @@ -320,6 +330,11 @@ void ExternalCache::OnPutExtension(const std::string& id, return; } + if (flush_on_put_) { + backend_task_runner_->PostTask(FROM_HERE, + base::Bind(&FlushFile, file_path)); + } + std::string update_url; if (entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl, &update_url) && diff --git a/chrome/browser/chromeos/extensions/external_cache.h b/chrome/browser/chromeos/extensions/external_cache.h index 9da6d1f1d5379..c57ddf3a424b6 100644 --- a/chrome/browser/chromeos/extensions/external_cache.h +++ b/chrome/browser/chromeos/extensions/external_cache.h @@ -134,6 +134,8 @@ class ExternalCache : public content::NotificationObserver, const std::string& version, const PutExternalExtensionCallback& callback); + void set_flush_on_put(bool flush_on_put) { flush_on_put_ = flush_on_put; } + private: // Notifies the that the cache has been updated, providing // extensions loader with an updated list of extensions. @@ -171,6 +173,9 @@ class ExternalCache : public content::NotificationObserver, // Set to true if cache should wait for initialization flag file. bool wait_for_cache_initialization_; + // Whether to flush the crx file after putting into |local_cache_|. + bool flush_on_put_ = false; + // This is the list of extensions currently configured. scoped_ptr extensions_; diff --git a/extensions/common/file_util.cc b/extensions/common/file_util.cc index b6156291ab792..8ec4c99971e37 100644 --- a/extensions/common/file_util.cc +++ b/extensions/common/file_util.cc @@ -45,6 +45,13 @@ namespace extensions { namespace file_util { namespace { +enum SafeInstallationFlag { + DEFAULT, // Default case, controlled by a field trial. + DISABLED, // Safe installation is disabled. + ENABLED, // Safe installation is enabled. +}; +SafeInstallationFlag g_use_safe_installation = DEFAULT; + // Returns true if the given file path exists and is not zero-length. bool ValidateFilePath(const base::FilePath& path) { int64 size = 0; @@ -97,6 +104,10 @@ void FlushFilesInDir(const base::FilePath& path, const base::FilePath::CharType kTempDirectoryName[] = FILE_PATH_LITERAL("Temp"); +void SetUseSafeInstallation(bool use_safe_installation) { + g_use_safe_installation = use_safe_installation ? ENABLED : DISABLED; +} + base::FilePath InstallExtension(const base::FilePath& unpacked_source_dir, const std::string& id, const std::string& version, diff --git a/extensions/common/file_util.h b/extensions/common/file_util.h index 5bb128746bbae..3fda56ad8f0d0 100644 --- a/extensions/common/file_util.h +++ b/extensions/common/file_util.h @@ -31,6 +31,9 @@ namespace file_util { extern const base::FilePath::CharType kTempDirectoryName[]; +// Sets the flag to enable safe installation (i.e. flush all installed files). +void SetUseSafeInstallation(bool use_safe_installation); + // Copies |unpacked_source_dir| into the right location under |extensions_dir|. // The destination directory is returned on success, or empty path is returned // on failure.