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
AppBannerManager(JNIEnv * env,jobject obj)34 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj)
35 : MetaTagObserver(kBannerTag),
36 weak_java_banner_view_manager_(env, obj) {}
37
~AppBannerManager()38 AppBannerManager::~AppBannerManager() {
39 }
40
Destroy(JNIEnv * env,jobject obj)41 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) {
42 delete this;
43 }
44
BlockBanner(JNIEnv * env,jobject obj,jstring jurl,jstring jpackage)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
ReplaceWebContents(JNIEnv * env,jobject obj,jobject jweb_contents)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
DidNavigateMainFrame(const content::LoadCommittedDetails & details,const content::FrameNavigateParams & params)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
OnFetchComplete(const GURL url,const SkBitmap * bitmap)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
HandleMetaTagContent(const std::string & tag_content,const GURL & expected_url)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
FetchIcon(JNIEnv * env,jobject obj,jstring jimage_url)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
RecordDismissEvent(JNIEnv * env,jclass clazz,jint metric)146 void RecordDismissEvent(JNIEnv* env, jclass clazz, jint metric) {
147 banners::TrackDismissEvent(metric);
148 }
149
RecordInstallEvent(JNIEnv * env,jclass clazz,jint metric)150 void RecordInstallEvent(JNIEnv* env, jclass clazz, jint metric) {
151 banners::TrackInstallEvent(metric);
152 }
153
Init(JNIEnv * env,jobject obj)154 jlong Init(JNIEnv* env, jobject obj) {
155 AppBannerManager* manager = new AppBannerManager(env, obj);
156 return reinterpret_cast<intptr_t>(manager);
157 }
158
IsEnabled(JNIEnv * env,jclass clazz)159 jboolean IsEnabled(JNIEnv* env, jclass clazz) {
160 return base::CommandLine::ForCurrentProcess()->HasSwitch(
161 switches::kEnableAppInstallAlerts);
162 }
163
164 // Register native methods
RegisterAppBannerManager(JNIEnv * env)165 bool RegisterAppBannerManager(JNIEnv* env) {
166 return RegisterNativesImpl(env);
167 }
168
169 } // namespace banners
170