1 // Copyright 2013 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.
5 #include "chrome/browser/android/shortcut_helper.h"
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/basictypes.h"
12 #include "base/location.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/banners/app_banner_settings_helper.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/manifest.h"
19 #include "jni/ShortcutHelper_jni.h"
20 #include "ui/gfx/android/java_bitmap.h"
21 #include "ui/gfx/color_analysis.h"
24 using content::Manifest
;
26 jlong
Initialize(JNIEnv
* env
, jobject obj
, jobject java_web_contents
) {
27 content::WebContents
* web_contents
=
28 content::WebContents::FromJavaWebContents(java_web_contents
);
29 ShortcutHelper
* shortcut_helper
= new ShortcutHelper(env
, obj
, web_contents
);
30 return reinterpret_cast<intptr_t>(shortcut_helper
);
33 ShortcutHelper::ShortcutHelper(JNIEnv
* env
,
35 content::WebContents
* web_contents
)
36 : add_shortcut_pending_(false),
37 data_fetcher_(new ShortcutDataFetcher(web_contents
, this)) {
38 java_ref_
.Reset(env
, obj
);
41 ShortcutHelper::~ShortcutHelper() {
42 data_fetcher_
->set_weak_observer(nullptr);
43 data_fetcher_
= nullptr;
46 void ShortcutHelper::OnUserTitleAvailable(const base::string16
& user_title
) {
47 JNIEnv
* env
= base::android::AttachCurrentThread();
48 ScopedJavaLocalRef
<jstring
> j_user_title
=
49 base::android::ConvertUTF16ToJavaString(env
, user_title
);
50 Java_ShortcutHelper_onUserTitleAvailable(env
,
55 void ShortcutHelper::OnDataAvailable(const ShortcutInfo
& info
,
56 const SkBitmap
& icon
) {
57 JNIEnv
* env
= base::android::AttachCurrentThread();
58 ScopedJavaLocalRef
<jobject
> java_bitmap
;
60 java_bitmap
= gfx::ConvertToJavaBitmap(&icon
);
62 Java_ShortcutHelper_onIconAvailable(env
,
66 if (add_shortcut_pending_
)
67 AddShortcut(info
, icon
);
70 void ShortcutHelper::Destroy(JNIEnv
* env
, jobject obj
) {
74 SkBitmap
ShortcutHelper::FinalizeLauncherIcon(const SkBitmap
& bitmap
,
76 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
78 // Determine a single color to use for the favicon if the favicon that is
79 // returned it is too low quality.
80 SkColor color
= color_utils::CalculateKMeanColorOfBitmap(bitmap
);
81 int dominant_red
= SkColorGetR(color
);
82 int dominant_green
= SkColorGetG(color
);
83 int dominant_blue
= SkColorGetB(color
);
85 // Make the icon acceptable for the Android launcher.
86 JNIEnv
* env
= base::android::AttachCurrentThread();
87 ScopedJavaLocalRef
<jstring
> java_url
=
88 base::android::ConvertUTF8ToJavaString(env
, url
.spec());
89 ScopedJavaLocalRef
<jobject
> java_bitmap
;
91 java_bitmap
= gfx::ConvertToJavaBitmap(&bitmap
);
93 base::android::ScopedJavaLocalRef
<jobject
> ref
=
94 Java_ShortcutHelper_finalizeLauncherIcon(env
,
100 return gfx::CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(ref
.obj()));
103 void ShortcutHelper::AddShortcut(JNIEnv
* env
,
105 jstring j_user_title
) {
106 add_shortcut_pending_
= true;
108 base::string16 user_title
=
109 base::android::ConvertJavaStringToUTF16(env
, j_user_title
);
110 if (!user_title
.empty())
111 data_fetcher_
->shortcut_info().user_title
= user_title
;
113 if (data_fetcher_
->is_ready()) {
114 // If the fetcher isn't ready yet, the shortcut will be added when it is
115 // via OnDataAvailable();
116 AddShortcut(data_fetcher_
->shortcut_info(), data_fetcher_
->shortcut_icon());
120 void ShortcutHelper::AddShortcut(const ShortcutInfo
& info
,
121 const SkBitmap
& icon
) {
122 DCHECK(add_shortcut_pending_
);
123 if (!add_shortcut_pending_
)
125 add_shortcut_pending_
= false;
127 RecordAddToHomescreen();
129 content::BrowserThread::PostTask(
130 content::BrowserThread::IO
,
132 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap
,
137 bool ShortcutHelper::RegisterShortcutHelper(JNIEnv
* env
) {
138 return RegisterNativesImpl(env
);
142 void ShortcutHelper::AddShortcutInBackgroundWithSkBitmap(
143 const ShortcutInfo
& info
,
144 const SkBitmap
& icon_bitmap
) {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
147 // Send the data to the Java side to create the shortcut.
148 JNIEnv
* env
= base::android::AttachCurrentThread();
149 ScopedJavaLocalRef
<jstring
> java_url
=
150 base::android::ConvertUTF8ToJavaString(env
, info
.url
.spec());
151 ScopedJavaLocalRef
<jstring
> java_user_title
=
152 base::android::ConvertUTF16ToJavaString(env
, info
.user_title
);
153 ScopedJavaLocalRef
<jstring
> java_name
=
154 base::android::ConvertUTF16ToJavaString(env
, info
.name
);
155 ScopedJavaLocalRef
<jstring
> java_short_name
=
156 base::android::ConvertUTF16ToJavaString(env
, info
.short_name
);
157 ScopedJavaLocalRef
<jobject
> java_bitmap
;
158 if (icon_bitmap
.getSize())
159 java_bitmap
= gfx::ConvertToJavaBitmap(&icon_bitmap
);
161 Java_ShortcutHelper_addShortcut(
163 base::android::GetApplicationContext(),
165 java_user_title
.obj(),
167 java_short_name
.obj(),
169 info
.display
== content::Manifest::DISPLAY_MODE_STANDALONE
,
174 void ShortcutHelper::RecordAddToHomescreen() {
175 // Record that the shortcut has been added, so no banners will be shown
177 content::WebContents
* web_contents
= data_fetcher_
->web_contents();
181 AppBannerSettingsHelper::RecordBannerEvent(
182 web_contents
, web_contents
->GetURL(),
183 data_fetcher_
->shortcut_info().url
.spec(),
184 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN
,