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

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: Rebasing, split off the important unit tests 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
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 } // namespace
49
50 // Fetches a bitmap and deletes itself when completed.
51 class BannerBitmapFetcher : public chrome::BitmapFetcher,
52 public chrome::BitmapFetcherDelegate {
53 public:
54 BannerBitmapFetcher(const GURL& image_url,
55 banners::AppBannerManager* delegate);
56
57 // Prevents informing the AppBannerManager that the fetch has completed.
58 void Cancel();
benwells 2015/02/16 01:58:43 This doesn't appear to be called by anything.
gone 2015/02/17 22:56:52 Fixed, good catch.
59
60 // chrome::BitmapFetcherDelegate overrides
61 void OnFetchComplete(const GURL url, const SkBitmap* icon) override;
62
63 private:
64 banners::AppBannerManager* delegate_;
65 bool is_cancelled_;
66 };
67
68 BannerBitmapFetcher::BannerBitmapFetcher(
69 const GURL& image_url,
70 banners::AppBannerManager* delegate)
71 : chrome::BitmapFetcher(image_url, this),
72 delegate_(delegate),
73 is_cancelled_(false) {
74 }
75
76 void BannerBitmapFetcher::Cancel() {
77 is_cancelled_ = true;
78 }
79
80 void BannerBitmapFetcher::OnFetchComplete(const GURL url,
81 const SkBitmap* icon) {
82 if (!is_cancelled_)
83 delegate_->OnFetchComplete(this, url, icon);
84
85 delete this;
48 } 86 }
49 87
50 namespace banners { 88 namespace banners {
51 89
52 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) 90 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj)
53 : weak_java_banner_view_manager_(env, obj), weak_factory_(this) { 91 : weak_java_banner_view_manager_(env, obj), weak_factory_(this) {
54 } 92 }
55 93
56 AppBannerManager::~AppBannerManager() { 94 AppBannerManager::~AppBannerManager() {
57 } 95 }
58 96
59 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) { 97 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) {
60 delete this; 98 delete this;
61 } 99 }
62 100
63 void AppBannerManager::ReplaceWebContents(JNIEnv* env, 101 void AppBannerManager::ReplaceWebContents(JNIEnv* env,
64 jobject obj, 102 jobject obj,
65 jobject jweb_contents) { 103 jobject jweb_contents) {
66 content::WebContents* web_contents = 104 content::WebContents* web_contents =
67 content::WebContents::FromJavaWebContents(jweb_contents); 105 content::WebContents::FromJavaWebContents(jweb_contents);
68 Observe(web_contents); 106 Observe(web_contents);
69 } 107 }
70 108
71 void AppBannerManager::DidNavigateMainFrame( 109 void AppBannerManager::DidNavigateMainFrame(
72 const content::LoadCommittedDetails& details, 110 const content::LoadCommittedDetails& details,
73 const content::FrameNavigateParams& params) { 111 const content::FrameNavigateParams& params) {
74 // Clear current state. 112 // Clear current state.
75 fetcher_.reset();
76 app_title_ = base::string16(); 113 app_title_ = base::string16();
77 web_app_data_ = content::Manifest(); 114 web_app_data_ = content::Manifest();
78 native_app_data_.Reset(); 115 native_app_data_.Reset();
79 native_app_package_ = std::string(); 116 native_app_package_ = std::string();
80 } 117 }
81 118
82 void AppBannerManager::DidFinishLoad( 119 void AppBannerManager::DidFinishLoad(
83 content::RenderFrameHost* render_frame_host, 120 content::RenderFrameHost* render_frame_host,
84 const GURL& validated_url) { 121 const GURL& validated_url) {
85 if (render_frame_host->GetParent()) 122 if (render_frame_host->GetParent())
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { 202 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) {
166 bool handled = true; 203 bool handled = true;
167 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) 204 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message)
168 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, 205 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent,
169 OnDidRetrieveMetaTagContent) 206 OnDidRetrieveMetaTagContent)
170 IPC_MESSAGE_UNHANDLED(handled = false) 207 IPC_MESSAGE_UNHANDLED(handled = false)
171 IPC_END_MESSAGE_MAP() 208 IPC_END_MESSAGE_MAP()
172 return handled; 209 return handled;
173 } 210 }
174 211
175 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { 212 void AppBannerManager::OnFetchComplete(BannerBitmapFetcher* fetcher,
176 fetcher_.reset(); 213 const GURL url,
177 if (!bitmap || url != app_icon_url_) { 214 const SkBitmap* icon) {
215 for (BitmapFetcherVector::iterator itr = active_fetchers_.begin();
216 itr != active_fetchers_.end();
217 ++itr) {
218 if (*itr == fetcher) {
219 active_fetchers_.erase(itr);
220 break;
221 }
222 }
223
224 if (!icon || url != app_icon_url_) {
178 DVLOG(1) << "Failed to retrieve image: " << url; 225 DVLOG(1) << "Failed to retrieve image: " << url;
benwells 2015/02/16 01:58:43 Nit: This log message is kind of inaccurate if url
gone 2015/02/17 22:56:52 Just removed the message. It's not useful in the
179 return; 226 return;
180 } 227 }
181 228
182 JNIEnv* env = base::android::AttachCurrentThread(); 229 JNIEnv* env = base::android::AttachCurrentThread();
183 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); 230 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
184 if (jobj.is_null()) 231 if (jobj.is_null())
185 return; 232 return;
186 233
187 InfoBarService* service = InfoBarService::FromWebContents(web_contents()); 234 InfoBarService* service = InfoBarService::FromWebContents(web_contents());
188 235
189 AppBannerInfoBar* weak_infobar_ptr = nullptr; 236 AppBannerInfoBar* weak_infobar_ptr = nullptr;
190 if (!native_app_data_.is_null()) { 237 if (!native_app_data_.is_null()) {
191 RecordCouldShowBanner(native_app_package_); 238 RecordCouldShowBanner(native_app_package_);
192 if (!CheckIfShouldShow(native_app_package_)) 239 if (!CheckIfShouldShow(native_app_package_))
193 return; 240 return;
194 241
195 weak_infobar_ptr = AppBannerInfoBarDelegate::CreateForNativeApp( 242 weak_infobar_ptr = AppBannerInfoBarDelegate::CreateForNativeApp(
196 service, 243 service,
197 app_title_, 244 app_title_,
198 new SkBitmap(*bitmap), 245 new SkBitmap(*icon),
199 native_app_data_, 246 native_app_data_,
200 native_app_package_); 247 native_app_package_);
201 } else if (!web_app_data_.IsEmpty()){ 248 } else if (!web_app_data_.IsEmpty()){
202 RecordCouldShowBanner(web_app_data_.start_url.spec()); 249 RecordCouldShowBanner(web_app_data_.start_url.spec());
203 if (!CheckIfShouldShow(web_app_data_.start_url.spec())) 250 if (!CheckIfShouldShow(web_app_data_.start_url.spec()))
204 return; 251 return;
205 252
206 weak_infobar_ptr = AppBannerInfoBarDelegate::CreateForWebApp( 253 weak_infobar_ptr = AppBannerInfoBarDelegate::CreateForWebApp(
207 service, 254 service,
208 app_title_, 255 app_title_,
209 new SkBitmap(*bitmap), 256 new SkBitmap(*icon),
210 web_app_data_); 257 web_app_data_);
211 } 258 }
212 259
213 if (weak_infobar_ptr != nullptr) 260 if (weak_infobar_ptr != nullptr)
214 banners::TrackDisplayEvent(DISPLAY_CREATED); 261 banners::TrackDisplayEvent(DISPLAY_CREATED);
215 } 262 }
216 263
217 void AppBannerManager::OnDidRetrieveMetaTagContent( 264 void AppBannerManager::OnDidRetrieveMetaTagContent(
218 bool success, 265 bool success,
219 const std::string& tag_name, 266 const std::string& tag_name,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 return false; 300 return false;
254 301
255 std::string image_url = ConvertJavaStringToUTF8(env, jicon_url); 302 std::string image_url = ConvertJavaStringToUTF8(env, jicon_url);
256 app_title_ = ConvertJavaStringToUTF16(env, japp_title); 303 app_title_ = ConvertJavaStringToUTF16(env, japp_title);
257 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package); 304 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
258 native_app_data_.Reset(env, japp_data); 305 native_app_data_.Reset(env, japp_data);
259 return FetchIcon(GURL(image_url)); 306 return FetchIcon(GURL(image_url));
260 } 307 }
261 308
262 int AppBannerManager::GetNumActiveFetchers(JNIEnv* env, jobject obj) { 309 int AppBannerManager::GetNumActiveFetchers(JNIEnv* env, jobject obj) {
263 return fetcher_.get() ? 1 : 0; 310 return active_fetchers_.size();
benwells 2015/02/16 01:58:43 As far as I can tell, this is the only reason to h
gone 2015/02/17 22:56:52 Started going the set route and realized that a we
264 } 311 }
265 312
266 bool AppBannerManager::FetchIcon(const GURL& image_url) { 313 bool AppBannerManager::FetchIcon(const GURL& image_url) {
267 if (!web_contents()) 314 if (!web_contents())
268 return false; 315 return false;
269 316
270 // Begin asynchronously fetching the app icon. 317 // Begin asynchronously fetching the app icon.
271 Profile* profile = 318 Profile* profile =
272 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 319 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
273 fetcher_.reset(new chrome::BitmapFetcher(image_url, this)); 320 BannerBitmapFetcher* fetcher = new BannerBitmapFetcher(image_url, this);
274 fetcher_.get()->Start( 321 active_fetchers_.push_back(fetcher);
322 fetcher->Start(
275 profile->GetRequestContext(), 323 profile->GetRequestContext(),
276 std::string(), 324 std::string(),
277 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, 325 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
278 net::LOAD_NORMAL); 326 net::LOAD_NORMAL);
279 app_icon_url_ = image_url; 327 app_icon_url_ = image_url;
280 return true; 328 return true;
281 } 329 }
282 330
283 int AppBannerManager::GetPreferredIconSize() { 331 int AppBannerManager::GetPreferredIconSize() {
284 JNIEnv* env = base::android::AttachCurrentThread(); 332 JNIEnv* env = base::android::AttachCurrentThread();
(...skipping 30 matching lines...) Expand all
315 void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) { 363 void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) {
316 gTimeDeltaForTesting = base::TimeDelta::FromDays(days); 364 gTimeDeltaForTesting = base::TimeDelta::FromDays(days);
317 } 365 }
318 366
319 // Register native methods 367 // Register native methods
320 bool RegisterAppBannerManager(JNIEnv* env) { 368 bool RegisterAppBannerManager(JNIEnv* env) {
321 return RegisterNativesImpl(env); 369 return RegisterNativesImpl(env);
322 } 370 }
323 371
324 } // namespace banners 372 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698