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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/android/banners/app_banner_manager.h" 6 7 #include "base/android/jni_android.h" 8 #include "base/android/jni_string.h" 9 #include "base/command_line.h" 10 #include "base/metrics/histogram.h" 11 #include "chrome/browser/android/banners/app_banner_metrics_ids.h" 12 #include "chrome/browser/android/banners/app_banner_settings_helper.h" 13 #include "chrome/browser/android/banners/app_banner_utilities.h" 14 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/common/chrome_switches.h" 17 #include "content/public/browser/android/content_view_core.h" 18 #include "content/public/browser/navigation_details.h" 19 #include "content/public/browser/web_contents.h" 20 #include "content/public/common/frame_navigate_params.h" 21 #include "jni/AppBannerManager_jni.h" 22 #include "net/base/load_flags.h" 23 #include "ui/gfx/android/java_bitmap.h" 24 25 using base::android::ConvertJavaStringToUTF8; 26 using base::android::ConvertUTF8ToJavaString; 27 28 namespace { 29 const char kBannerTag[] = "google-play-id"; 30 } 31 32 namespace banners { 33 34 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) 35 : MetaTagObserver(kBannerTag), 36 weak_java_banner_view_manager_(env, obj) {} 37 38 AppBannerManager::~AppBannerManager() { 39 } 40 41 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) { 42 delete this; 43 } 44 45 void AppBannerManager::BlockBanner(JNIEnv* env, 46 jobject obj, 47 jstring jurl, 48 jstring jpackage) { 49 if (!web_contents()) 50 return; 51 52 GURL url(ConvertJavaStringToUTF8(env, jurl)); 53 std::string package_name = ConvertJavaStringToUTF8(env, jpackage); 54 AppBannerSettingsHelper::Block(web_contents(), url, package_name); 55 } 56 57 void AppBannerManager::ReplaceWebContents(JNIEnv* env, 58 jobject obj, 59 jobject jweb_contents) { 60 content::WebContents* web_contents = 61 content::WebContents::FromJavaWebContents(jweb_contents); 62 Observe(web_contents); 63 } 64 65 void AppBannerManager::DidNavigateMainFrame( 66 const content::LoadCommittedDetails& details, 67 const content::FrameNavigateParams& params) { 68 // Get rid of the current banner. 69 JNIEnv* env = base::android::AttachCurrentThread(); 70 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); 71 if (jobj.is_null()) 72 return; 73 Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj(), DISMISS_NAVIGATE); 74 } 75 76 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { 77 if (bitmap) { 78 JNIEnv* env = base::android::AttachCurrentThread(); 79 80 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); 81 if (jobj.is_null()) 82 return; 83 84 ScopedJavaLocalRef<jstring> jimage_url( 85 ConvertUTF8ToJavaString(env, url.spec())); 86 ScopedJavaLocalRef<jobject> jimage = gfx::ConvertToJavaBitmap(bitmap); 87 bool displayed = Java_AppBannerManager_createBanner(env, 88 jobj.obj(), 89 jimage_url.obj(), 90 jimage.obj()); 91 if (displayed) 92 banners::TrackDisplayEvent(DISPLAY_CREATED); 93 } else { 94 DVLOG(1) << "Failed to retrieve image: " << url; 95 } 96 97 fetcher_.reset(); 98 } 99 100 void AppBannerManager::HandleMetaTagContent(const std::string& tag_content, 101 const GURL& expected_url) { 102 DCHECK(web_contents()); 103 banners::TrackDisplayEvent(DISPLAY_BANNER_REQUESTED); 104 105 if (!AppBannerSettingsHelper::IsAllowed(web_contents(), 106 expected_url, 107 tag_content)) { 108 return; 109 } 110 111 // Send the info to the Java side to get info about the app. 112 JNIEnv* env = base::android::AttachCurrentThread(); 113 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); 114 if (jobj.is_null()) 115 return; 116 117 ScopedJavaLocalRef<jstring> jurl( 118 ConvertUTF8ToJavaString(env, expected_url.spec())); 119 ScopedJavaLocalRef<jstring> jpackage( 120 ConvertUTF8ToJavaString(env, tag_content)); 121 Java_AppBannerManager_prepareBanner(env, 122 jobj.obj(), 123 jurl.obj(), 124 jpackage.obj()); 125 } 126 127 bool AppBannerManager::FetchIcon(JNIEnv* env, 128 jobject obj, 129 jstring jimage_url) { 130 std::string image_url = ConvertJavaStringToUTF8(env, jimage_url); 131 if (!web_contents()) 132 return false; 133 134 // Begin asynchronously fetching the app icon. 135 Profile* profile = 136 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 137 fetcher_.reset(new chrome::BitmapFetcher(GURL(image_url), this)); 138 fetcher_.get()->Start( 139 profile->GetRequestContext(), 140 std::string(), 141 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, 142 net::LOAD_NORMAL); 143 return true; 144 } 145 146 void RecordDismissEvent(JNIEnv* env, jclass clazz, jint metric) { 147 banners::TrackDismissEvent(metric); 148 } 149 150 void RecordInstallEvent(JNIEnv* env, jclass clazz, jint metric) { 151 banners::TrackInstallEvent(metric); 152 } 153 154 jlong Init(JNIEnv* env, jobject obj) { 155 AppBannerManager* manager = new AppBannerManager(env, obj); 156 return reinterpret_cast<intptr_t>(manager); 157 } 158 159 jboolean IsEnabled(JNIEnv* env, jclass clazz) { 160 return base::CommandLine::ForCurrentProcess()->HasSwitch( 161 switches::kEnableAppInstallAlerts); 162 } 163 164 // Register native methods 165 bool RegisterAppBannerManager(JNIEnv* env) { 166 return RegisterNativesImpl(env); 167 } 168 169 } // namespace banners 170