Commit 76a80d50 authored by Ran Ji's avatar Ran Ji Committed by Commit Bot

Free cache if necessary when install, fail back to shortcut if no enough space

Fail back to shortcut if there is no enough space to install WebApk even after
freeing cache.

Free cache and install if there is no enough space but the space requirement
can be satisfied using the cache storage.

Bug: 774513,736457
Change-Id: I1beec2b3c26ebfb09e03014038a2657b27185284
Reviewed-on: https://chromium-review.googlesource.com/794532Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Commit-Queue: Ran Ji <ranj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#525321}
parent 029dd979
...@@ -343,6 +343,7 @@ java_cpp_enum("chrome_android_java_enums_srcjar") { ...@@ -343,6 +343,7 @@ java_cpp_enum("chrome_android_java_enums_srcjar") {
"//chrome/browser/android/shortcut_info.h", "//chrome/browser/android/shortcut_info.h",
"//chrome/browser/android/tab_android.h", "//chrome/browser/android/tab_android.h",
"//chrome/browser/android/webapk/webapk_install_service.h", "//chrome/browser/android/webapk/webapk_install_service.h",
"//chrome/browser/android/webapk/webapk_installer.h",
"//chrome/browser/android/webapk/webapk_types.h", "//chrome/browser/android/webapk/webapk_types.h",
"//chrome/browser/banners/app_banner_settings_helper.h", "//chrome/browser/banners/app_banner_settings_helper.h",
"//chrome/browser/notifications/notification_channels_provider_android.h", "//chrome/browser/notifications/notification_channels_provider_android.h",
......
...@@ -244,8 +244,7 @@ public class WebApkUma { ...@@ -244,8 +244,7 @@ public class WebApkUma {
@Override @Override
protected Void doInBackground(Void... params) { protected Void doInBackground(Void... params) {
mAvailableSpaceInByte = getAvailableSpaceAboveLowSpaceLimit(); mAvailableSpaceInByte = getAvailableSpaceAboveLowSpaceLimit();
mCacheSizeInByte = mCacheSizeInByte = getCacheDirSize();
getDirectorySizeInByte(ContextUtils.getApplicationContext().getCacheDir());
return null; return null;
} }
...@@ -310,8 +309,12 @@ public class WebApkUma { ...@@ -310,8 +309,12 @@ public class WebApkUma {
return sizeInByte; return sizeInByte;
} }
/**
* @return The available space that can be used to install WebAPK. Negative value means there is
* less free space available than the system's minimum by the given amount.
*/
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static long getAvailableSpaceAboveLowSpaceLimit() { public static long getAvailableSpaceAboveLowSpaceLimit() {
long partitionAvailableBytes; long partitionAvailableBytes;
long partitionTotalBytes; long partitionTotalBytes;
StatFs partitionStats = new StatFs(Environment.getDataDirectory().getAbsolutePath()); StatFs partitionStats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
...@@ -329,6 +332,13 @@ public class WebApkUma { ...@@ -329,6 +332,13 @@ public class WebApkUma {
return partitionAvailableBytes - minimumFreeBytes; return partitionAvailableBytes - minimumFreeBytes;
} }
/**
* @return Size of the cache directory.
*/
public static long getCacheDirSize() {
return getDirectorySizeInByte(ContextUtils.getApplicationContext().getCacheDir());
}
/** /**
* Mirror the system-derived calculation of reserved bytes and return that value. * Mirror the system-derived calculation of reserved bytes and return that value.
*/ */
......
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.webapps; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.webapps;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.AsyncTask;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
...@@ -123,6 +124,29 @@ public class WebApkInstaller { ...@@ -123,6 +124,29 @@ public class WebApkInstaller {
mInstallDelegate.updateAsync(packageName, version, title, token, callback); mInstallDelegate.updateAsync(packageName, version, title, token, callback);
} }
@CalledByNative
private void checkFreeSpace() {
new AsyncTask<Void, Void, Integer>() {
@Override
protected Integer doInBackground(Void... params) {
long availableSpaceInBytes = WebApkUma.getAvailableSpaceAboveLowSpaceLimit();
if (availableSpaceInBytes > 0) return SpaceStatus.ENOUGH_SPACE;
long cacheSizeInBytes = WebApkUma.getCacheDirSize();
if (cacheSizeInBytes + availableSpaceInBytes > 0) {
return SpaceStatus.ENOUGH_SPACE_AFTER_FREE_UP_CACHE;
}
return SpaceStatus.NOT_ENOUGH_SPACE;
}
@Override
protected void onPostExecute(Integer result) {
nativeOnGotSpaceStatus(mNativePointer, result);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private boolean isWebApkInstalled(String packageName) { private boolean isWebApkInstalled(String packageName) {
PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager(); PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
return InstallerDelegate.isInstalled(packageManager, packageName); return InstallerDelegate.isInstalled(packageManager, packageName);
...@@ -130,4 +154,5 @@ public class WebApkInstaller { ...@@ -130,4 +154,5 @@ public class WebApkInstaller {
private native void nativeOnInstallFinished( private native void nativeOnInstallFinished(
long nativeWebApkInstaller, @WebApkInstallResult int result); long nativeWebApkInstaller, @WebApkInstallResult int result);
private native void nativeOnGotSpaceStatus(long nativeWebApkInstaller, int status);
} }
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/android/path_utils.h" #include "base/android/path_utils.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
...@@ -31,16 +32,17 @@ ...@@ -31,16 +32,17 @@
#include "chrome/browser/android/webapk/webapk_icon_hasher.h" #include "chrome/browser/android/webapk/webapk_icon_hasher.h"
#include "chrome/browser/android/webapk/webapk_install_service.h" #include "chrome/browser/android/webapk/webapk_install_service.h"
#include "chrome/browser/android/webapk/webapk_metrics.h" #include "chrome/browser/android/webapk/webapk_metrics.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/common/manifest_util.h" #include "content/public/common/manifest_util.h"
#include "jni/WebApkInstaller_jni.h" #include "jni/WebApkInstaller_jni.h"
#include "net/base/load_flags.h" #include "net/base/load_flags.h"
#include "net/http/http_status_code.h" #include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
...@@ -60,6 +62,44 @@ const char kProtoMimeType[] = "application/x-protobuf"; ...@@ -60,6 +62,44 @@ const char kProtoMimeType[] = "application/x-protobuf";
// the WebAPK server. // the WebAPK server.
const int kWebApkDownloadUrlTimeoutMs = 60000; const int kWebApkDownloadUrlTimeoutMs = 60000;
class CacheClearer : public content::BrowsingDataRemover::Observer {
public:
~CacheClearer() override { remover_->RemoveObserver(this); }
// Clear Chrome's cache. Run |callback| once clearing the cache is complete.
static void FreeCacheAsync(content::BrowsingDataRemover* remover,
base::OnceClosure callback) {
// CacheClearer manages its own lifetime and deletes itself when finished.
auto* cache_clearer = new CacheClearer(remover, std::move(callback));
remover->AddObserver(cache_clearer);
remover->RemoveAndReply(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_CACHE,
ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES,
cache_clearer);
}
private:
CacheClearer(content::BrowsingDataRemover* remover,
base::OnceClosure callback)
: remover_(remover), install_callback_(std::move(callback)) {}
void OnBrowsingDataRemoverDone() override {
std::move(install_callback_).Run();
delete this; // Matches the new in FreeCacheAsync()
}
content::BrowsingDataRemover* remover_;
base::OnceClosure install_callback_;
DISALLOW_COPY_AND_ASSIGN(CacheClearer);
};
net::URLRequestContextGetter* GetRequestContext(
content::BrowserContext* browser_context) {
return Profile::FromBrowserContext(browser_context)->GetRequestContext();
}
// Returns the WebAPK server URL based on the command line. // Returns the WebAPK server URL based on the command line.
GURL GetServerUrl() { GURL GetServerUrl() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
...@@ -404,8 +444,7 @@ void WebApkInstaller::OnResult(WebApkInstallResult result) { ...@@ -404,8 +444,7 @@ void WebApkInstaller::OnResult(WebApkInstallResult result) {
} }
WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context) WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context)
: request_context_getter_( : browser_context_(browser_context),
Profile::FromBrowserContext(browser_context)->GetRequestContext()),
server_url_(GetServerUrl()), server_url_(GetServerUrl()),
webapk_server_timeout_ms_(kWebApkDownloadUrlTimeoutMs), webapk_server_timeout_ms_(kWebApkDownloadUrlTimeoutMs),
relax_updates_(false), relax_updates_(false),
...@@ -433,18 +472,33 @@ void WebApkInstaller::InstallAsync(const ShortcutInfo& shortcut_info, ...@@ -433,18 +472,33 @@ void WebApkInstaller::InstallAsync(const ShortcutInfo& shortcut_info,
finish_callback_ = finish_callback; finish_callback_ = finish_callback;
task_type_ = INSTALL; task_type_ = INSTALL;
// We need to take the hash of the bitmap at the icon URL prior to any CheckFreeSpace();
// transformations being applied to the bitmap (such as encoding/decoding }
// the bitmap). The icon hash is used to determine whether the icon that
// the user sees matches the icon of a WebAPK that the WebAPK server void WebApkInstaller::CheckFreeSpace() {
// generated for another user. (The icon can be dynamically generated.) JNIEnv* env = base::android::AttachCurrentThread();
// Java_WebApkInstaller_checkFreeSpace(env, java_ref_);
// We redownload the icon in order to take the Murmur2 hash. The redownload }
// should be fast because the icon should be in the HTTP cache.
WebApkIconHasher::DownloadAndComputeMurmur2Hash( void WebApkInstaller::OnGotSpaceStatus(
request_context_getter_, install_shortcut_info_->best_primary_icon_url, JNIEnv* env,
base::Bind(&WebApkInstaller::OnGotPrimaryIconMurmur2Hash, const base::android::JavaParamRef<jobject>& obj,
weak_ptr_factory_.GetWeakPtr())); jint status) {
SpaceStatus space_status = static_cast<SpaceStatus>(status);
if (space_status == SpaceStatus::NOT_ENOUGH_SPACE) {
OnResult(WebApkInstallResult::FAILURE);
return;
}
if (space_status == SpaceStatus::ENOUGH_SPACE_AFTER_FREE_UP_CACHE) {
CacheClearer::FreeCacheAsync(
content::BrowserContext::GetBrowsingDataRemover(browser_context_),
base::BindOnce(&WebApkInstaller::OnHaveSufficientSpaceForInstall,
weak_ptr_factory_.GetWeakPtr()));
} else {
OnHaveSufficientSpaceForInstall();
}
} }
void WebApkInstaller::UpdateAsync(const base::FilePath& update_request_path, void WebApkInstaller::UpdateAsync(const base::FilePath& update_request_path,
...@@ -514,6 +568,22 @@ void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { ...@@ -514,6 +568,22 @@ void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) {
InstallOrUpdateWebApk(response->package_name(), version, token); InstallOrUpdateWebApk(response->package_name(), version, token);
} }
void WebApkInstaller::OnHaveSufficientSpaceForInstall() {
// We need to take the hash of the bitmap at the icon URL prior to any
// transformations being applied to the bitmap (such as encoding/decoding
// the bitmap). The icon hash is used to determine whether the icon that
// the user sees matches the icon of a WebAPK that the WebAPK server
// generated for another user. (The icon can be dynamically generated.)
//
// We redownload the icon in order to take the Murmur2 hash. The redownload
// should be fast because the icon should be in the HTTP cache.
WebApkIconHasher::DownloadAndComputeMurmur2Hash(
GetRequestContext(browser_context_),
install_shortcut_info_->best_primary_icon_url,
base::Bind(&WebApkInstaller::OnGotPrimaryIconMurmur2Hash,
weak_ptr_factory_.GetWeakPtr()));
}
void WebApkInstaller::OnGotPrimaryIconMurmur2Hash( void WebApkInstaller::OnGotPrimaryIconMurmur2Hash(
const std::string& primary_icon_hash) { const std::string& primary_icon_hash) {
// An empty hash indicates an error during hash calculation. // An empty hash indicates an error during hash calculation.
...@@ -526,7 +596,8 @@ void WebApkInstaller::OnGotPrimaryIconMurmur2Hash( ...@@ -526,7 +596,8 @@ void WebApkInstaller::OnGotPrimaryIconMurmur2Hash(
install_shortcut_info_->best_badge_icon_url != install_shortcut_info_->best_badge_icon_url !=
install_shortcut_info_->best_primary_icon_url) { install_shortcut_info_->best_primary_icon_url) {
WebApkIconHasher::DownloadAndComputeMurmur2Hash( WebApkIconHasher::DownloadAndComputeMurmur2Hash(
request_context_getter_, install_shortcut_info_->best_badge_icon_url, GetRequestContext(browser_context_),
install_shortcut_info_->best_badge_icon_url,
base::Bind(&WebApkInstaller::OnGotBadgeIconMurmur2Hash, base::Bind(&WebApkInstaller::OnGotBadgeIconMurmur2Hash,
weak_ptr_factory_.GetWeakPtr(), true, primary_icon_hash)); weak_ptr_factory_.GetWeakPtr(), true, primary_icon_hash));
} else { } else {
...@@ -571,7 +642,7 @@ void WebApkInstaller::SendRequest( ...@@ -571,7 +642,7 @@ void WebApkInstaller::SendRequest(
url_fetcher_ = url_fetcher_ =
net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this); net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this);
url_fetcher_->SetRequestContext(request_context_getter_); url_fetcher_->SetRequestContext(GetRequestContext(browser_context_));
url_fetcher_->SetUploadData(kProtoMimeType, *serialized_proto); url_fetcher_->SetUploadData(kProtoMimeType, *serialized_proto);
url_fetcher_->SetLoadFlags( url_fetcher_->SetLoadFlags(
net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES |
......
...@@ -31,6 +31,14 @@ namespace content { ...@@ -31,6 +31,14 @@ namespace content {
class BrowserContext; class BrowserContext;
} }
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.webapps
enum class SpaceStatus {
ENOUGH_SPACE = 0,
ENOUGH_SPACE_AFTER_FREE_UP_CACHE = 1,
NOT_ENOUGH_SPACE = 2,
};
// Talks to Chrome WebAPK server to download metadata about a WebAPK and issue // Talks to Chrome WebAPK server to download metadata about a WebAPK and issue
// a request for it to be installed. The native WebApkInstaller owns the Java // a request for it to be installed. The native WebApkInstaller owns the Java
// WebApkInstaller counterpart. // WebApkInstaller counterpart.
...@@ -79,6 +87,14 @@ class WebApkInstaller : public net::URLFetcherDelegate { ...@@ -79,6 +87,14 @@ class WebApkInstaller : public net::URLFetcherDelegate {
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& obj,
jint result); jint result);
// Checks if there is enough space to install a WebAPK.
// If yes, continue the WebAPK installation process. If there is not enough
// space to install (even after clearing Chrome's cache), fails the
// installation process immediately.
void OnGotSpaceStatus(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint status);
// Asynchronously builds the WebAPK proto on a background thread for an update // Asynchronously builds the WebAPK proto on a background thread for an update
// or install request. Runs |callback| on the calling thread when complete. // or install request. Runs |callback| on the calling thread when complete.
static void BuildProto( static void BuildProto(
...@@ -115,6 +131,9 @@ class WebApkInstaller : public net::URLFetcherDelegate { ...@@ -115,6 +131,9 @@ class WebApkInstaller : public net::URLFetcherDelegate {
int version, int version,
const std::string& token); const std::string& token);
// Checks if there is enough space to install a WebAPK.
virtual void CheckFreeSpace();
// Called when the install or update process has completed or failed. // Called when the install or update process has completed or failed.
void OnResult(WebApkInstallResult result); void OnResult(WebApkInstallResult result);
...@@ -143,6 +162,12 @@ class WebApkInstaller : public net::URLFetcherDelegate { ...@@ -143,6 +162,12 @@ class WebApkInstaller : public net::URLFetcherDelegate {
void UpdateAsync(const base::FilePath& update_request_path, void UpdateAsync(const base::FilePath& update_request_path,
const FinishCallback& finish_callback); const FinishCallback& finish_callback);
// Called once there is sufficient space on the user's device to install a
// WebAPK. The user may already have had sufficient space on their device
// prior to initiating the install process. This method might be called as a
// result of freeing up memory by clearing Chrome's cache.
void OnHaveSufficientSpaceForInstall();
// Called with the contents of the update request file. // Called with the contents of the update request file.
void OnReadUpdateRequest(std::unique_ptr<std::string> update_request); void OnReadUpdateRequest(std::unique_ptr<std::string> update_request);
...@@ -164,7 +189,7 @@ class WebApkInstaller : public net::URLFetcherDelegate { ...@@ -164,7 +189,7 @@ class WebApkInstaller : public net::URLFetcherDelegate {
// Google Play. // Google Play.
void SendRequest(std::unique_ptr<std::string> serialized_proto); void SendRequest(std::unique_ptr<std::string> serialized_proto);
net::URLRequestContextGetter* request_context_getter_; content::BrowserContext* browser_context_;
// Sends HTTP request to WebAPK server. // Sends HTTP request to WebAPK server.
std::unique_ptr<net::URLFetcher> url_fetcher_; std::unique_ptr<net::URLFetcher> url_fetcher_;
......
...@@ -65,8 +65,9 @@ const char* kDownloadedWebApkPackageName = "party.unicode"; ...@@ -65,8 +65,9 @@ const char* kDownloadedWebApkPackageName = "party.unicode";
// WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay() are stubbed out. // WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay() are stubbed out.
class TestWebApkInstaller : public WebApkInstaller { class TestWebApkInstaller : public WebApkInstaller {
public: public:
explicit TestWebApkInstaller(content::BrowserContext* browser_context) explicit TestWebApkInstaller(content::BrowserContext* browser_context,
: WebApkInstaller(browser_context) {} SpaceStatus status)
: WebApkInstaller(browser_context), test_space_status_(status) {}
void InstallOrUpdateWebApk(const std::string& package_name, void InstallOrUpdateWebApk(const std::string& package_name,
int version, int version,
...@@ -82,6 +83,14 @@ class TestWebApkInstaller : public WebApkInstaller { ...@@ -82,6 +83,14 @@ class TestWebApkInstaller : public WebApkInstaller {
} }
private: private:
void CheckFreeSpace() override {
OnGotSpaceStatus(nullptr, base::android::JavaParamRef<jobject>(nullptr),
static_cast<int>(test_space_status_));
}
// The space status used in tests.
SpaceStatus test_space_status_;
DISALLOW_COPY_AND_ASSIGN(TestWebApkInstaller); DISALLOW_COPY_AND_ASSIGN(TestWebApkInstaller);
}; };
...@@ -90,10 +99,12 @@ class WebApkInstallerRunner { ...@@ -90,10 +99,12 @@ class WebApkInstallerRunner {
public: public:
WebApkInstallerRunner(content::BrowserContext* browser_context, WebApkInstallerRunner(content::BrowserContext* browser_context,
const GURL& best_primary_icon_url, const GURL& best_primary_icon_url,
const GURL& best_badge_icon_url) const GURL& best_badge_icon_url,
SpaceStatus test_space_status)
: browser_context_(browser_context), : browser_context_(browser_context),
best_primary_icon_url_(best_primary_icon_url), best_primary_icon_url_(best_primary_icon_url),
best_badge_icon_url_(best_badge_icon_url) {} best_badge_icon_url_(best_badge_icon_url),
test_space_status_(test_space_status) {}
~WebApkInstallerRunner() {} ~WebApkInstallerRunner() {}
...@@ -126,7 +137,8 @@ class WebApkInstallerRunner { ...@@ -126,7 +137,8 @@ class WebApkInstallerRunner {
WebApkInstaller* CreateWebApkInstaller() { WebApkInstaller* CreateWebApkInstaller() {
// WebApkInstaller owns itself. // WebApkInstaller owns itself.
WebApkInstaller* installer = new TestWebApkInstaller(browser_context_); WebApkInstaller* installer =
new TestWebApkInstaller(browser_context_, test_space_status_);
installer->SetTimeoutMs(100); installer->SetTimeoutMs(100);
return installer; return installer;
} }
...@@ -147,6 +159,9 @@ class WebApkInstallerRunner { ...@@ -147,6 +159,9 @@ class WebApkInstallerRunner {
const GURL best_primary_icon_url_; const GURL best_primary_icon_url_;
const GURL best_badge_icon_url_; const GURL best_badge_icon_url_;
// The space status used in tests.
SpaceStatus test_space_status_;
// Called after the installation process has succeeded or failed. // Called after the installation process has succeeded or failed.
base::Closure on_completed_callback_; base::Closure on_completed_callback_;
...@@ -312,9 +327,14 @@ class WebApkInstallerTest : public ::testing::Test { ...@@ -312,9 +327,14 @@ class WebApkInstallerTest : public ::testing::Test {
webapk_response_builder_ = builder; webapk_response_builder_ = builder;
} }
// Sets the function that should be used to build the response to the
// WebAPK creation request.
void SetSpaceStatus(const SpaceStatus status) { test_space_status_ = status; }
std::unique_ptr<WebApkInstallerRunner> CreateWebApkInstallerRunner() { std::unique_ptr<WebApkInstallerRunner> CreateWebApkInstallerRunner() {
return std::unique_ptr<WebApkInstallerRunner>(new WebApkInstallerRunner( return std::unique_ptr<WebApkInstallerRunner>(
profile_.get(), best_primary_icon_url_, best_badge_icon_url_)); new WebApkInstallerRunner(profile_.get(), best_primary_icon_url_,
best_badge_icon_url_, test_space_status_));
} }
std::unique_ptr<BuildProtoRunner> CreateBuildProtoRunner() { std::unique_ptr<BuildProtoRunner> CreateBuildProtoRunner() {
...@@ -330,6 +350,7 @@ class WebApkInstallerTest : public ::testing::Test { ...@@ -330,6 +350,7 @@ class WebApkInstallerTest : public ::testing::Test {
SetBestBadgeIconUrl(test_server_.GetURL(kBestBadgeIconUrl)); SetBestBadgeIconUrl(test_server_.GetURL(kBestBadgeIconUrl));
SetWebApkServerUrl(test_server_.GetURL(kServerUrl)); SetWebApkServerUrl(test_server_.GetURL(kServerUrl));
SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, kToken)); SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, kToken));
SetSpaceStatus(SpaceStatus::ENOUGH_SPACE);
} }
std::unique_ptr<net::test_server::HttpResponse> HandleWebApkRequest( std::unique_ptr<net::test_server::HttpResponse> HandleWebApkRequest(
...@@ -350,6 +371,9 @@ class WebApkInstallerTest : public ::testing::Test { ...@@ -350,6 +371,9 @@ class WebApkInstallerTest : public ::testing::Test {
// Builds response to the WebAPK creation request. // Builds response to the WebAPK creation request.
WebApkResponseBuilder webapk_response_builder_; WebApkResponseBuilder webapk_response_builder_;
// The space status used in tests.
SpaceStatus test_space_status_;
DISALLOW_COPY_AND_ASSIGN(WebApkInstallerTest); DISALLOW_COPY_AND_ASSIGN(WebApkInstallerTest);
}; };
...@@ -360,6 +384,14 @@ TEST_F(WebApkInstallerTest, Success) { ...@@ -360,6 +384,14 @@ TEST_F(WebApkInstallerTest, Success) {
EXPECT_EQ(WebApkInstallResult::SUCCESS, runner->result()); EXPECT_EQ(WebApkInstallResult::SUCCESS, runner->result());
} }
// Test that installation fails if there is not enough space on device.
TEST_F(WebApkInstallerTest, FailOnLowSpace) {
SetSpaceStatus(SpaceStatus::NOT_ENOUGH_SPACE);
std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner();
runner->RunInstallWebApk();
EXPECT_EQ(WebApkInstallResult::FAILURE, runner->result());
}
// Test that installation fails if fetching the bitmap at the best primary icon // Test that installation fails if fetching the bitmap at the best primary icon
// URL returns no content. In a perfect world the fetch would always succeed // URL returns no content. In a perfect world the fetch would always succeed
// because the fetch for the same icon succeeded recently. // because the fetch for the same icon succeeded recently.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment