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

Side by Side 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: Nits 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 unified diff | Download patch
« no previous file with comments | « chrome/browser/android/banners/app_banner_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/banners/app_banner_manager.h" 5 #include "chrome/browser/android/banners/app_banner_manager.h"
6 6
7 #include "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 8 #include "base/android/jni_string.h"
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 27 matching lines...) Expand all
38 #include "ui/gfx/screen.h" 38 #include "ui/gfx/screen.h"
39 39
40 using base::android::ConvertJavaStringToUTF8; 40 using base::android::ConvertJavaStringToUTF8;
41 using base::android::ConvertJavaStringToUTF16; 41 using base::android::ConvertJavaStringToUTF16;
42 using base::android::ConvertUTF8ToJavaString; 42 using base::android::ConvertUTF8ToJavaString;
43 using base::android::ConvertUTF16ToJavaString; 43 using base::android::ConvertUTF16ToJavaString;
44 44
45 namespace { 45 namespace {
46 const char kBannerTag[] = "google-play-id"; 46 const char kBannerTag[] = "google-play-id";
47 base::TimeDelta gTimeDeltaForTesting; 47 base::TimeDelta gTimeDeltaForTesting;
48 } 48 } // namespace
49 49
50 namespace banners { 50 namespace banners {
51 51
52 // Fetches a bitmap and deletes itself when completed.
53 class AppBannerManager::BannerBitmapFetcher
54 : public chrome::BitmapFetcher,
55 public chrome::BitmapFetcherDelegate {
56 public:
57 BannerBitmapFetcher(const GURL& image_url,
58 banners::AppBannerManager* manager);
59
60 // Prevents informing the AppBannerManager that the fetch has completed.
61 void Cancel();
62
63 // chrome::BitmapFetcherDelegate overrides
64 void OnFetchComplete(const GURL url, const SkBitmap* icon) override;
65
66 private:
67 banners::AppBannerManager* manager_;
68 bool is_cancelled_;
69 };
70
71 AppBannerManager::BannerBitmapFetcher::BannerBitmapFetcher(
72 const GURL& image_url,
73 banners::AppBannerManager* manager)
74 : chrome::BitmapFetcher(image_url, this),
75 manager_(manager),
76 is_cancelled_(false) {
77 }
78
79 void AppBannerManager::BannerBitmapFetcher::Cancel() {
80 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
81 is_cancelled_ = true;
82 }
83
84 void AppBannerManager::BannerBitmapFetcher::OnFetchComplete(
85 const GURL url,
86 const SkBitmap* icon) {
87 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
88
89 if (!is_cancelled_)
90 manager_->OnFetchComplete(this, url, icon);
91
92 delete this;
93 }
94
52 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) 95 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj)
53 : weak_java_banner_view_manager_(env, obj), weak_factory_(this) { 96 : fetcher_(nullptr),
97 weak_java_banner_view_manager_(env, obj),
98 weak_factory_(this) {
54 } 99 }
55 100
56 AppBannerManager::~AppBannerManager() { 101 AppBannerManager::~AppBannerManager() {
102 CancelActiveFetcher();
57 } 103 }
58 104
59 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) { 105 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) {
60 delete this; 106 delete this;
61 } 107 }
62 108
63 void AppBannerManager::ReplaceWebContents(JNIEnv* env, 109 void AppBannerManager::ReplaceWebContents(JNIEnv* env,
64 jobject obj, 110 jobject obj,
65 jobject jweb_contents) { 111 jobject jweb_contents) {
66 content::WebContents* web_contents = 112 content::WebContents* web_contents =
67 content::WebContents::FromJavaWebContents(jweb_contents); 113 content::WebContents::FromJavaWebContents(jweb_contents);
68 Observe(web_contents); 114 Observe(web_contents);
69 } 115 }
70 116
71 void AppBannerManager::DidNavigateMainFrame( 117 void AppBannerManager::DidNavigateMainFrame(
72 const content::LoadCommittedDetails& details, 118 const content::LoadCommittedDetails& details,
73 const content::FrameNavigateParams& params) { 119 const content::FrameNavigateParams& params) {
74 // Clear current state. 120 // Clear current state.
75 fetcher_.reset(); 121 CancelActiveFetcher();
76 app_title_ = base::string16(); 122 app_title_ = base::string16();
77 web_app_data_ = content::Manifest(); 123 web_app_data_ = content::Manifest();
78 native_app_data_.Reset(); 124 native_app_data_.Reset();
79 native_app_package_ = std::string(); 125 native_app_package_ = std::string();
80 } 126 }
81 127
82 void AppBannerManager::DidFinishLoad( 128 void AppBannerManager::DidFinishLoad(
83 content::RenderFrameHost* render_frame_host, 129 content::RenderFrameHost* render_frame_host,
84 const GURL& validated_url) { 130 const GURL& validated_url) {
85 if (render_frame_host->GetParent()) 131 if (render_frame_host->GetParent())
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 GetCurrentTime())) { 201 GetCurrentTime())) {
156 return false; 202 return false;
157 } 203 }
158 204
159 AppBannerSettingsHelper::RecordBannerEvent( 205 AppBannerSettingsHelper::RecordBannerEvent(
160 web_contents(), validated_url_, package_or_start_url, 206 web_contents(), validated_url_, package_or_start_url,
161 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW, GetCurrentTime()); 207 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW, GetCurrentTime());
162 return true; 208 return true;
163 } 209 }
164 210
211 void AppBannerManager::CancelActiveFetcher() {
212 // Fetchers delete themselves.
213 if (fetcher_ != nullptr) {
214 fetcher_->Cancel();
215 fetcher_ = nullptr;
216 }
217 }
218
165 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { 219 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) {
166 bool handled = true; 220 bool handled = true;
167 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) 221 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message)
168 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, 222 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent,
169 OnDidRetrieveMetaTagContent) 223 OnDidRetrieveMetaTagContent)
170 IPC_MESSAGE_UNHANDLED(handled = false) 224 IPC_MESSAGE_UNHANDLED(handled = false)
171 IPC_END_MESSAGE_MAP() 225 IPC_END_MESSAGE_MAP()
172 return handled; 226 return handled;
173 } 227 }
174 228
175 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { 229 void AppBannerManager::OnFetchComplete(BannerBitmapFetcher* fetcher,
176 fetcher_.reset(); 230 const GURL url,
177 if (!bitmap || url != app_icon_url_) { 231 const SkBitmap* bitmap) {
178 DVLOG(1) << "Failed to retrieve image: " << url; 232 if (fetcher_ != fetcher)
179 return; 233 return;
180 } 234 fetcher_ = nullptr;
235
236 if (!bitmap || url != app_icon_url_)
237 return;
181 238
182 JNIEnv* env = base::android::AttachCurrentThread(); 239 JNIEnv* env = base::android::AttachCurrentThread();
183 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); 240 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
184 if (jobj.is_null()) 241 if (jobj.is_null())
185 return; 242 return;
186 243
187 InfoBarService* service = InfoBarService::FromWebContents(web_contents()); 244 InfoBarService* service = InfoBarService::FromWebContents(web_contents());
188 245
189 AppBannerInfoBar* weak_infobar_ptr = nullptr; 246 AppBannerInfoBar* weak_infobar_ptr = nullptr;
190 if (!native_app_data_.is_null()) { 247 if (!native_app_data_.is_null()) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 if (validated_url_ != web_contents()->GetURL()) 309 if (validated_url_ != web_contents()->GetURL())
253 return false; 310 return false;
254 311
255 std::string image_url = ConvertJavaStringToUTF8(env, jicon_url); 312 std::string image_url = ConvertJavaStringToUTF8(env, jicon_url);
256 app_title_ = ConvertJavaStringToUTF16(env, japp_title); 313 app_title_ = ConvertJavaStringToUTF16(env, japp_title);
257 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package); 314 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
258 native_app_data_.Reset(env, japp_data); 315 native_app_data_.Reset(env, japp_data);
259 return FetchIcon(GURL(image_url)); 316 return FetchIcon(GURL(image_url));
260 } 317 }
261 318
262 int AppBannerManager::GetNumActiveFetchers(JNIEnv* env, jobject obj) { 319 bool AppBannerManager::IsFetcherActive(JNIEnv* env, jobject obj) {
263 return fetcher_.get() ? 1 : 0; 320 return fetcher_ != nullptr;
264 } 321 }
265 322
266 bool AppBannerManager::FetchIcon(const GURL& image_url) { 323 bool AppBannerManager::FetchIcon(const GURL& image_url) {
267 if (!web_contents()) 324 if (!web_contents())
268 return false; 325 return false;
269 326
270 // Begin asynchronously fetching the app icon. 327 // Begin asynchronously fetching the app icon.
271 Profile* profile = 328 Profile* profile =
272 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 329 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
273 fetcher_.reset(new chrome::BitmapFetcher(image_url, this)); 330
274 fetcher_.get()->Start( 331 CancelActiveFetcher();
332 fetcher_ = new BannerBitmapFetcher(image_url, this);
333 fetcher_->Start(
275 profile->GetRequestContext(), 334 profile->GetRequestContext(),
276 std::string(), 335 std::string(),
277 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, 336 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
278 net::LOAD_NORMAL); 337 net::LOAD_NORMAL);
279 app_icon_url_ = image_url; 338 app_icon_url_ = image_url;
280 return true; 339 return true;
281 } 340 }
282 341
283 int AppBannerManager::GetPreferredIconSize() { 342 int AppBannerManager::GetPreferredIconSize() {
284 JNIEnv* env = base::android::AttachCurrentThread(); 343 JNIEnv* env = base::android::AttachCurrentThread();
(...skipping 30 matching lines...) Expand all
315 void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) { 374 void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) {
316 gTimeDeltaForTesting = base::TimeDelta::FromDays(days); 375 gTimeDeltaForTesting = base::TimeDelta::FromDays(days);
317 } 376 }
318 377
319 // Register native methods 378 // Register native methods
320 bool RegisterAppBannerManager(JNIEnv* env) { 379 bool RegisterAppBannerManager(JNIEnv* env) {
321 return RegisterNativesImpl(env); 380 return RegisterNativesImpl(env);
322 } 381 }
323 382
324 } // namespace banners 383 } // namespace banners
OLDNEW
« no previous file with comments | « chrome/browser/android/banners/app_banner_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698