Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: chrome/browser/android/banners/app_banner_manager.cc

Issue 914813002: [App banners] Start addressing race conditions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revamping Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/banners/app_banner_manager.cc
diff --git a/chrome/browser/android/banners/app_banner_manager.cc b/chrome/browser/android/banners/app_banner_manager.cc
index 0f0dcb56ae3f0191bd1af44bada9142329f874aa..ef8aedfa4af292b0299beb81232507b1bef73d8c 100644
--- a/chrome/browser/android/banners/app_banner_manager.cc
+++ b/chrome/browser/android/banners/app_banner_manager.cc
@@ -45,15 +45,61 @@ using base::android::ConvertUTF16ToJavaString;
namespace {
const char kBannerTag[] = "google-play-id";
base::TimeDelta gTimeDeltaForTesting;
-}
+} // namespace
namespace banners {
+// Fetches a bitmap and deletes itself when completed.
+class AppBannerManager::BannerBitmapFetcher
+ : public chrome::BitmapFetcher,
+ public chrome::BitmapFetcherDelegate {
+ public:
+ BannerBitmapFetcher(const GURL& image_url,
+ banners::AppBannerManager* delegate);
benwells 2015/02/18 06:01:18 Nit: calling this 'delegate' is a bit confusing, a
gone 2015/02/18 18:33:29 Done.
+
+ // Prevents informing the AppBannerManager that the fetch has completed.
+ void Cancel();
+
+ // chrome::BitmapFetcherDelegate overrides
+ void OnFetchComplete(const GURL url, const SkBitmap* icon) override;
+
+ private:
+ banners::AppBannerManager* delegate_;
+ bool is_cancelled_;
+};
+
+AppBannerManager::BannerBitmapFetcher::BannerBitmapFetcher(
+ const GURL& image_url,
+ banners::AppBannerManager* delegate)
+ : chrome::BitmapFetcher(image_url, this),
+ delegate_(delegate),
+ is_cancelled_(false) {
+}
+
+void AppBannerManager::BannerBitmapFetcher::Cancel() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ is_cancelled_ = true;
+}
+
+void AppBannerManager::BannerBitmapFetcher::OnFetchComplete(
+ const GURL url,
+ const SkBitmap* icon) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ if (!is_cancelled_)
+ delegate_->OnFetchComplete(this, url, icon);
+
+ delete this;
+}
+
AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj)
- : weak_java_banner_view_manager_(env, obj), weak_factory_(this) {
+ : fetcher_(nullptr),
+ weak_java_banner_view_manager_(env, obj),
+ weak_factory_(this) {
}
AppBannerManager::~AppBannerManager() {
+ CancelActiveFetcher();
}
void AppBannerManager::Destroy(JNIEnv* env, jobject obj) {
@@ -72,7 +118,7 @@ void AppBannerManager::DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) {
// Clear current state.
- fetcher_.reset();
+ CancelActiveFetcher();
app_title_ = base::string16();
web_app_data_ = content::Manifest();
native_app_data_.Reset();
@@ -162,6 +208,14 @@ bool AppBannerManager::CheckIfShouldShow(
return true;
}
+void AppBannerManager::CancelActiveFetcher() {
+ // Fetchers delete themselves.
+ if (fetcher_ != nullptr) {
+ fetcher_->Cancel();
+ fetcher_ = nullptr;
+ }
+}
+
bool AppBannerManager::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message)
@@ -172,12 +226,15 @@ bool AppBannerManager::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) {
- fetcher_.reset();
- if (!bitmap || url != app_icon_url_) {
- DVLOG(1) << "Failed to retrieve image: " << url;
+void AppBannerManager::OnFetchComplete(BannerBitmapFetcher* fetcher,
+ const GURL url,
+ const SkBitmap* bitmap) {
+ if (fetcher_ != fetcher)
+ return;
+ fetcher_ = nullptr;
+
+ if (!bitmap || url != app_icon_url_)
return;
- }
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
@@ -259,8 +316,8 @@ bool AppBannerManager::OnAppDetailsRetrieved(JNIEnv* env,
return FetchIcon(GURL(image_url));
}
-int AppBannerManager::GetNumActiveFetchers(JNIEnv* env, jobject obj) {
- return fetcher_.get() ? 1 : 0;
+bool AppBannerManager::IsFetcherActive(JNIEnv* env, jobject obj) {
+ return fetcher_ != nullptr;
}
bool AppBannerManager::FetchIcon(const GURL& image_url) {
@@ -270,8 +327,10 @@ bool AppBannerManager::FetchIcon(const GURL& image_url) {
// Begin asynchronously fetching the app icon.
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
- fetcher_.reset(new chrome::BitmapFetcher(image_url, this));
- fetcher_.get()->Start(
+
+ CancelActiveFetcher();
+ fetcher_ = new BannerBitmapFetcher(image_url, this);
+ fetcher_->Start(
profile->GetRequestContext(),
std::string(),
net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,

Powered by Google App Engine
This is Rietveld 408576698