OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/shortcut_helper.h" | 5 #include "chrome/browser/android/shortcut_helper.h" |
6 | 6 |
7 #include <jni.h> | 7 #include <jni.h> |
8 #include <limits> | |
8 | 9 |
9 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 11 #include "base/android/jni_string.h" |
11 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
12 #include "base/location.h" | 13 #include "base/location.h" |
13 #include "base/strings/string16.h" | 14 #include "base/strings/string16.h" |
15 #include "base/strings/utf_string_conversions.h" | |
14 #include "base/task/cancelable_task_tracker.h" | 16 #include "base/task/cancelable_task_tracker.h" |
15 #include "base/threading/worker_pool.h" | 17 #include "base/threading/worker_pool.h" |
16 #include "chrome/browser/android/tab_android.h" | 18 #include "chrome/browser/android/tab_android.h" |
17 #include "chrome/browser/favicon/favicon_service.h" | 19 #include "chrome/browser/favicon/favicon_service.h" |
18 #include "chrome/browser/favicon/favicon_service_factory.h" | 20 #include "chrome/browser/favicon/favicon_service_factory.h" |
19 #include "chrome/common/chrome_constants.h" | 21 #include "chrome/common/chrome_constants.h" |
20 #include "chrome/common/render_messages.h" | 22 #include "chrome/common/render_messages.h" |
21 #include "chrome/common/web_application_info.h" | 23 #include "chrome/common/web_application_info.h" |
22 #include "content/public/browser/user_metrics.h" | 24 #include "content/public/browser/user_metrics.h" |
23 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
24 #include "content/public/browser/web_contents_observer.h" | 26 #include "content/public/browser/web_contents_observer.h" |
25 #include "content/public/common/frame_navigate_params.h" | 27 #include "content/public/common/frame_navigate_params.h" |
26 #include "content/public/common/manifest.h" | 28 #include "content/public/common/manifest.h" |
27 #include "jni/ShortcutHelper_jni.h" | 29 #include "jni/ShortcutHelper_jni.h" |
30 #include "net/base/mime_util.h" | |
28 #include "ui/gfx/android/java_bitmap.h" | 31 #include "ui/gfx/android/java_bitmap.h" |
29 #include "ui/gfx/codec/png_codec.h" | 32 #include "ui/gfx/codec/png_codec.h" |
30 #include "ui/gfx/color_analysis.h" | 33 #include "ui/gfx/color_analysis.h" |
31 #include "ui/gfx/favicon_size.h" | 34 #include "ui/gfx/favicon_size.h" |
35 #include "ui/gfx/screen.h" | |
32 #include "url/gurl.h" | 36 #include "url/gurl.h" |
33 | 37 |
38 using content::Manifest; | |
39 | |
40 // Android's preferred icon size in DP is 48, as defined in | |
41 // http://developer.android.com/design/style/iconography.html | |
42 const int ShortcutHelper::kPreferredIconSizeInDp = 48; | |
43 | |
34 jlong Initialize(JNIEnv* env, jobject obj, jlong tab_android_ptr) { | 44 jlong Initialize(JNIEnv* env, jobject obj, jlong tab_android_ptr) { |
35 TabAndroid* tab = reinterpret_cast<TabAndroid*>(tab_android_ptr); | 45 TabAndroid* tab = reinterpret_cast<TabAndroid*>(tab_android_ptr); |
36 | 46 |
37 ShortcutHelper* shortcut_helper = | 47 ShortcutHelper* shortcut_helper = |
38 new ShortcutHelper(env, obj, tab->web_contents()); | 48 new ShortcutHelper(env, obj, tab->web_contents()); |
39 shortcut_helper->Initialize(); | 49 shortcut_helper->Initialize(); |
40 | 50 |
41 return reinterpret_cast<intptr_t>(shortcut_helper); | 51 return reinterpret_cast<intptr_t>(shortcut_helper); |
42 } | 52 } |
43 | 53 |
44 ShortcutHelper::ShortcutHelper(JNIEnv* env, | 54 ShortcutHelper::ShortcutHelper(JNIEnv* env, |
45 jobject obj, | 55 jobject obj, |
46 content::WebContents* web_contents) | 56 content::WebContents* web_contents) |
47 : WebContentsObserver(web_contents), | 57 : WebContentsObserver(web_contents), |
48 java_ref_(env, obj), | 58 java_ref_(env, obj), |
49 url_(web_contents->GetURL()), | 59 url_(web_contents->GetURL()), |
50 display_(content::Manifest::DISPLAY_MODE_BROWSER), | 60 display_(content::Manifest::DISPLAY_MODE_BROWSER), |
51 orientation_(blink::WebScreenOrientationLockDefault), | 61 orientation_(blink::WebScreenOrientationLockDefault), |
62 add_shortcut_requested_(false), | |
63 manifest_icon_status_(MANIFEST_ICON_STATUS_NONE), | |
64 preferred_icon_size_in_px_(kPreferredIconSizeInDp * | |
gone
2014/09/24 18:17:24
does this calculation _have_ to go here? makes th
mlamouri (slow - plz ping)
2014/09/24 18:36:49
I possibly moved it there because of the value bei
| |
65 gfx::Screen::GetScreenFor(web_contents->GetNativeView())-> | |
66 GetPrimaryDisplay().device_scale_factor()), | |
52 weak_ptr_factory_(this) { | 67 weak_ptr_factory_(this) { |
53 } | 68 } |
54 | 69 |
55 void ShortcutHelper::Initialize() { | 70 void ShortcutHelper::Initialize() { |
56 // Send a message to the renderer to retrieve information about the page. | 71 // Send a message to the renderer to retrieve information about the page. |
57 Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id())); | 72 Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id())); |
58 } | 73 } |
59 | 74 |
60 ShortcutHelper::~ShortcutHelper() { | 75 ShortcutHelper::~ShortcutHelper() { |
61 } | 76 } |
(...skipping 28 matching lines...) Expand all Loading... | |
90 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: | 105 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: |
91 content::RecordAction( | 106 content::RecordAction( |
92 base::UserMetricsAction("webapps.AddShortcut.Bookmark")); | 107 base::UserMetricsAction("webapps.AddShortcut.Bookmark")); |
93 break; | 108 break; |
94 } | 109 } |
95 | 110 |
96 web_contents()->GetManifest(base::Bind(&ShortcutHelper::OnDidGetManifest, | 111 web_contents()->GetManifest(base::Bind(&ShortcutHelper::OnDidGetManifest, |
97 weak_ptr_factory_.GetWeakPtr())); | 112 weak_ptr_factory_.GetWeakPtr())); |
98 } | 113 } |
99 | 114 |
115 bool ShortcutHelper::IconSizesContainsPreferredSize( | |
116 const std::vector<gfx::Size>& sizes) const { | |
117 for (size_t i = 0; i < sizes.size(); ++i) { | |
118 if (sizes[i].height() != sizes[i].width()) | |
119 continue; | |
120 if (sizes[i].width() == preferred_icon_size_in_px_) | |
121 return true; | |
122 } | |
123 | |
124 return false; | |
125 } | |
126 | |
127 GURL ShortcutHelper::FindBestMatchingIcon( | |
128 const std::vector<Manifest::Icon>& icons, float density) const { | |
129 GURL url; | |
130 int delta = std::numeric_limits<int>::min(); | |
131 | |
132 for (size_t i = 0; i < icons.size(); ++i) { | |
133 if (icons[i].density != density) | |
134 continue; | |
135 | |
136 const std::vector<gfx::Size>& sizes = icons[i].sizes; | |
137 for (size_t j = 0; j < sizes.size(); ++j) { | |
138 if (sizes[j].height() != sizes[j].width()) | |
139 continue; | |
140 int d = sizes[j].width() - preferred_icon_size_in_px_; | |
141 if (d == 0) | |
142 return icons[i].src; | |
143 if (delta > 0 && d < 0) | |
144 continue; | |
145 if ((delta > 0 && d < delta) || (delta < 0 && d > delta)) { | |
146 url = icons[i].src; | |
147 delta = d; | |
148 } | |
149 } | |
150 } | |
151 | |
152 return url; | |
153 } | |
154 | |
155 // static | |
156 std::vector<Manifest::Icon> ShortcutHelper::FilterIconsByType( | |
157 const std::vector<Manifest::Icon>& icons) { | |
158 std::vector<Manifest::Icon> result; | |
159 | |
160 for (size_t i = 0; i < icons.size(); ++i) { | |
161 if (icons[i].type.is_null() || | |
gone
2014/09/24 18:17:24
any reason why you keep the icon if the type is nu
mlamouri (slow - plz ping)
2014/09/24 18:36:49
If the type is not specified but sizes are, I woul
| |
162 net::IsSupportedImageMimeType( | |
163 base::UTF16ToUTF8(icons[i].type.string()))) { | |
164 result.push_back(icons[i]); | |
165 } | |
166 } | |
167 | |
168 return result; | |
169 } | |
170 | |
171 GURL ShortcutHelper::FindBestMatchingIcon( | |
172 const std::vector<Manifest::Icon>& unfiltered_icons) const { | |
173 const float device_scale_factor = | |
174 gfx::Screen::GetScreenFor(web_contents()->GetNativeView())-> | |
175 GetPrimaryDisplay().device_scale_factor(); | |
176 | |
177 GURL url; | |
178 std::vector<Manifest::Icon> icons = FilterIconsByType(unfiltered_icons); | |
179 | |
180 // The first pass is to find the ideal icon. That icon is of the right size | |
181 // with the default density or the device's density. | |
182 for (size_t i = 0; i < icons.size(); ++i) { | |
183 if (icons[i].density == device_scale_factor && | |
184 IconSizesContainsPreferredSize(icons[i].sizes)) { | |
185 return icons[i].src; | |
186 } | |
187 | |
188 // If there is an icon with the right size but not the right density, keep | |
189 // it on the side and only use it if nothing better is found. | |
190 if (icons[i].density == Manifest::Icon::kDefaultDensity && | |
191 IconSizesContainsPreferredSize(icons[i].sizes)) { | |
192 url = icons[i].src; | |
193 } | |
194 } | |
195 | |
196 // Second pass will try to find the best suitable icon for the device's scale | |
197 // factor. If none, another pass will be run using kDefaultDensity. | |
198 if (!url.is_valid()) { | |
199 url = FindBestMatchingIcon(icons, device_scale_factor); | |
200 if (!url.is_valid()) | |
gone
2014/09/24 18:17:24
may as well move this if outside of the other if s
mlamouri (slow - plz ping)
2014/09/24 18:36:49
Done.
| |
201 url = FindBestMatchingIcon(icons, Manifest::Icon::kDefaultDensity); | |
202 } | |
203 | |
204 return url; | |
205 } | |
206 | |
100 void ShortcutHelper::OnDidGetManifest(const content::Manifest& manifest) { | 207 void ShortcutHelper::OnDidGetManifest(const content::Manifest& manifest) { |
101 // Set the title based on the manifest value, if any. | 208 // Set the title based on the manifest value, if any. |
102 if (!manifest.short_name.is_null()) | 209 if (!manifest.short_name.is_null()) |
103 title_ = manifest.short_name.string(); | 210 title_ = manifest.short_name.string(); |
104 else if (!manifest.name.is_null()) | 211 else if (!manifest.name.is_null()) |
105 title_ = manifest.name.string(); | 212 title_ = manifest.name.string(); |
106 | 213 |
107 // Set the url based on the manifest value, if any. | 214 // Set the url based on the manifest value, if any. |
108 if (manifest.start_url.is_valid()) | 215 if (manifest.start_url.is_valid()) |
109 url_ = manifest.start_url; | 216 url_ = manifest.start_url; |
(...skipping 11 matching lines...) Expand all Loading... | |
121 | 228 |
122 // Set the orientation based on the manifest value, if any. | 229 // Set the orientation based on the manifest value, if any. |
123 if (manifest.orientation != blink::WebScreenOrientationLockDefault) { | 230 if (manifest.orientation != blink::WebScreenOrientationLockDefault) { |
124 // Ignore the orientation if the display mode is different from | 231 // Ignore the orientation if the display mode is different from |
125 // 'standalone'. | 232 // 'standalone'. |
126 // TODO(mlamouri): send a message to the developer console about this. | 233 // TODO(mlamouri): send a message to the developer console about this. |
127 if (display_ == content::Manifest::DISPLAY_MODE_STANDALONE) | 234 if (display_ == content::Manifest::DISPLAY_MODE_STANDALONE) |
128 orientation_ = manifest.orientation; | 235 orientation_ = manifest.orientation; |
129 } | 236 } |
130 | 237 |
238 GURL icon_src = FindBestMatchingIcon(manifest.icons); | |
239 if (icon_src.is_valid()) { | |
240 web_contents()->DownloadImage(icon_src, | |
241 false, | |
242 preferred_icon_size_in_px_, | |
243 base::Bind(&ShortcutHelper::OnDidDownloadIcon, | |
244 weak_ptr_factory_.GetWeakPtr())); | |
245 manifest_icon_status_ = MANIFEST_ICON_STATUS_FETCHING; | |
246 } | |
247 | |
131 // The ShortcutHelper is now able to notify its Java counterpart that it is | 248 // The ShortcutHelper is now able to notify its Java counterpart that it is |
132 // initialized. OnInitialized method is not conceptually part of getting the | 249 // initialized. OnInitialized method is not conceptually part of getting the |
133 // manifest data but it happens that the initialization is finalized when | 250 // manifest data but it happens that the initialization is finalized when |
134 // these data are available. | 251 // these data are available. |
135 JNIEnv* env = base::android::AttachCurrentThread(); | 252 JNIEnv* env = base::android::AttachCurrentThread(); |
136 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); | 253 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |
137 ScopedJavaLocalRef<jstring> j_title = | 254 ScopedJavaLocalRef<jstring> j_title = |
138 base::android::ConvertUTF16ToJavaString(env, title_); | 255 base::android::ConvertUTF16ToJavaString(env, title_); |
139 | 256 |
140 Java_ShortcutHelper_onInitialized(env, j_obj.obj(), j_title.obj()); | 257 Java_ShortcutHelper_onInitialized(env, j_obj.obj(), j_title.obj()); |
141 } | 258 } |
142 | 259 |
260 void ShortcutHelper::OnDidDownloadIcon(int id, | |
261 int http_status_code, | |
262 const GURL& url, | |
263 const std::vector<SkBitmap>& bitmaps, | |
264 const std::vector<gfx::Size>& sizes) { | |
265 // If getting the candidate manifest icon failed, the ShortcutHelper should | |
266 // fallback to the favicon. | |
267 // If the user already requested to add the shortcut, it will do so but use | |
268 // the favicon instead. | |
269 // Otherwise, it sets the state as if there was no manifest icon pending. | |
270 if (bitmaps.empty()) { | |
271 if (add_shortcut_requested_) | |
272 AddShortcutUsingFavicon(); | |
273 else | |
274 manifest_icon_status_ = MANIFEST_ICON_STATUS_NONE; | |
275 return; | |
276 } | |
277 | |
278 // There might be multiple bitmaps returned. The one to pick is bigger or | |
279 // equal to the preferred size. |bitmaps| is ordered from bigger to smaller. | |
280 int preferred_bitmap_index = 0; | |
281 for (size_t i = 0; i < bitmaps.size(); ++i) { | |
282 if (bitmaps[i].height() < preferred_icon_size_in_px_) | |
283 break; | |
284 preferred_bitmap_index = i; | |
285 } | |
286 | |
287 manifest_icon_ = bitmaps[preferred_bitmap_index]; | |
288 manifest_icon_status_ = MANIFEST_ICON_STATUS_DONE; | |
289 | |
290 if (add_shortcut_requested_) | |
291 AddShortcutUsingManifestIcon(); | |
gone
2014/09/24 18:17:24
what happens if a shortcut wasn't requested? what
mlamouri (slow - plz ping)
2014/09/24 18:36:49
If the shortcut wasn't requested but is later requ
| |
292 } | |
293 | |
143 void ShortcutHelper::TearDown(JNIEnv*, jobject) { | 294 void ShortcutHelper::TearDown(JNIEnv*, jobject) { |
144 Destroy(); | 295 Destroy(); |
145 } | 296 } |
146 | 297 |
147 void ShortcutHelper::Destroy() { | 298 void ShortcutHelper::Destroy() { |
148 delete this; | 299 delete this; |
149 } | 300 } |
150 | 301 |
151 void ShortcutHelper::AddShortcut( | 302 void ShortcutHelper::AddShortcut( |
152 JNIEnv* env, | 303 JNIEnv* env, |
153 jobject obj, | 304 jobject obj, |
154 jstring jtitle, | 305 jstring jtitle, |
155 jint launcher_large_icon_size) { | 306 jint launcher_large_icon_size) { |
307 add_shortcut_requested_ = true; | |
308 | |
156 base::string16 title = base::android::ConvertJavaStringToUTF16(env, jtitle); | 309 base::string16 title = base::android::ConvertJavaStringToUTF16(env, jtitle); |
157 if (!title.empty()) | 310 if (!title.empty()) |
158 title_ = title; | 311 title_ = title; |
159 | 312 |
313 switch (manifest_icon_status_) { | |
gone
2014/09/24 18:17:24
indentation seems off here
mlamouri (slow - plz ping)
2014/09/24 18:36:49
How so?
gone
2014/09/24 18:39:21
http://google-styleguide.googlecode.com/svn/trunk/
mlamouri (slow - plz ping)
2014/09/24 19:41:38
I got hit again by Blink and Chromium having diffe
| |
314 case MANIFEST_ICON_STATUS_NONE: | |
315 AddShortcutUsingFavicon(); | |
316 break; | |
317 case MANIFEST_ICON_STATUS_FETCHING: | |
318 // ::OnDidDownloadIcon() will call AddShortcutUsingManifestIcon() when run. | |
319 break; | |
320 case MANIFEST_ICON_STATUS_DONE: | |
321 AddShortcutUsingManifestIcon(); | |
322 break; | |
323 } | |
324 } | |
325 | |
326 void ShortcutHelper::AddShortcutUsingManifestIcon() { | |
327 // Stop observing so we don't get destroyed while doing the last steps. | |
328 Observe(NULL); | |
329 | |
330 base::WorkerPool::PostTask( | |
331 FROM_HERE, | |
332 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap, | |
333 url_, | |
334 title_, | |
335 display_, | |
336 manifest_icon_, | |
337 orientation_), | |
338 true); | |
339 | |
340 Destroy(); | |
341 } | |
342 | |
343 void ShortcutHelper::AddShortcutUsingFavicon() { | |
160 Profile* profile = | 344 Profile* profile = |
161 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 345 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
162 | 346 |
163 // Grab the best, largest icon we can find to represent this bookmark. | 347 // Grab the best, largest icon we can find to represent this bookmark. |
164 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its | 348 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its |
165 // rewrite is further along. | 349 // rewrite is further along. |
166 std::vector<int> icon_types; | 350 std::vector<int> icon_types; |
167 icon_types.push_back(favicon_base::FAVICON); | 351 icon_types.push_back(favicon_base::FAVICON); |
168 icon_types.push_back(favicon_base::TOUCH_PRECOMPOSED_ICON | | 352 icon_types.push_back(favicon_base::TOUCH_PRECOMPOSED_ICON | |
169 favicon_base::TOUCH_ICON); | 353 favicon_base::TOUCH_ICON); |
170 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( | 354 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( |
171 profile, Profile::EXPLICIT_ACCESS); | 355 profile, Profile::EXPLICIT_ACCESS); |
172 | 356 |
173 // Using favicon if its size is not smaller than platform required size, | 357 // Using favicon if its size is not smaller than platform required size, |
174 // otherwise using the largest icon among all avaliable icons. | 358 // otherwise using the largest icon among all avaliable icons. |
175 int threshold_to_get_any_largest_icon = launcher_large_icon_size_ - 1; | 359 int threshold_to_get_any_largest_icon = preferred_icon_size_in_px_ - 1; |
176 favicon_service->GetLargestRawFaviconForPageURL(url_, icon_types, | 360 favicon_service->GetLargestRawFaviconForPageURL(url_, icon_types, |
177 threshold_to_get_any_largest_icon, | 361 threshold_to_get_any_largest_icon, |
178 base::Bind(&ShortcutHelper::FinishAddingShortcut, | 362 base::Bind(&ShortcutHelper::OnDidGetFavicon, |
179 base::Unretained(this)), | 363 base::Unretained(this)), |
180 &cancelable_task_tracker_); | 364 &cancelable_task_tracker_); |
181 } | 365 } |
182 | 366 |
183 void ShortcutHelper::FinishAddingShortcut( | 367 void ShortcutHelper::OnDidGetFavicon( |
184 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | 368 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
185 icon_ = bitmap_result; | |
186 | |
187 // Stop observing so we don't get destroyed while doing the last steps. | 369 // Stop observing so we don't get destroyed while doing the last steps. |
188 Observe(NULL); | 370 Observe(NULL); |
189 | 371 |
190 base::WorkerPool::PostTask( | 372 base::WorkerPool::PostTask( |
191 FROM_HERE, | 373 FROM_HERE, |
192 base::Bind(&ShortcutHelper::AddShortcutInBackground, | 374 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithRawBitmap, |
193 url_, | 375 url_, |
194 title_, | 376 title_, |
195 display_, | 377 display_, |
196 icon_, | 378 bitmap_result, |
197 orientation_), | 379 orientation_), |
198 true); | 380 true); |
199 | 381 |
200 Destroy(); | 382 Destroy(); |
201 } | 383 } |
202 | 384 |
203 bool ShortcutHelper::OnMessageReceived(const IPC::Message& message) { | 385 bool ShortcutHelper::OnMessageReceived(const IPC::Message& message) { |
204 bool handled = true; | 386 bool handled = true; |
205 | 387 |
206 IPC_BEGIN_MESSAGE_MAP(ShortcutHelper, message) | 388 IPC_BEGIN_MESSAGE_MAP(ShortcutHelper, message) |
207 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, | 389 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, |
208 OnDidGetWebApplicationInfo) | 390 OnDidGetWebApplicationInfo) |
209 IPC_MESSAGE_UNHANDLED(handled = false) | 391 IPC_MESSAGE_UNHANDLED(handled = false) |
210 IPC_END_MESSAGE_MAP() | 392 IPC_END_MESSAGE_MAP() |
211 | 393 |
212 return handled; | 394 return handled; |
213 } | 395 } |
214 | 396 |
215 void ShortcutHelper::WebContentsDestroyed() { | 397 void ShortcutHelper::WebContentsDestroyed() { |
216 Destroy(); | 398 Destroy(); |
217 } | 399 } |
218 | 400 |
219 bool ShortcutHelper::RegisterShortcutHelper(JNIEnv* env) { | 401 bool ShortcutHelper::RegisterShortcutHelper(JNIEnv* env) { |
220 return RegisterNativesImpl(env); | 402 return RegisterNativesImpl(env); |
221 } | 403 } |
222 | 404 |
223 void ShortcutHelper::AddShortcutInBackground( | 405 void ShortcutHelper::AddShortcutInBackgroundWithRawBitmap( |
224 const GURL& url, | 406 const GURL& url, |
225 const base::string16& title, | 407 const base::string16& title, |
226 content::Manifest::DisplayMode display, | 408 content::Manifest::DisplayMode display, |
227 const favicon_base::FaviconRawBitmapResult& bitmap_result, | 409 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
228 blink::WebScreenOrientationLockType orientation) { | 410 blink::WebScreenOrientationLockType orientation) { |
229 DCHECK(base::WorkerPool::RunsTasksOnCurrentThread()); | 411 DCHECK(base::WorkerPool::RunsTasksOnCurrentThread()); |
230 | 412 |
231 // Grab the average color from the bitmap. | 413 SkBitmap icon_bitmap; |
232 SkColor color = SK_ColorWHITE; | |
233 SkBitmap favicon_bitmap; | |
234 if (bitmap_result.is_valid()) { | 414 if (bitmap_result.is_valid()) { |
235 if (gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), | 415 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), |
236 bitmap_result.bitmap_data->size(), | 416 bitmap_result.bitmap_data->size(), |
237 &favicon_bitmap)) | 417 &icon_bitmap); |
238 color = color_utils::CalculateKMeanColorOfBitmap(favicon_bitmap); | |
239 } | 418 } |
240 | 419 |
420 AddShortcutInBackgroundWithSkBitmap( | |
421 url, title, display, icon_bitmap, orientation); | |
422 } | |
423 | |
424 void ShortcutHelper::AddShortcutInBackgroundWithSkBitmap( | |
425 const GURL& url, | |
426 const base::string16& title, | |
427 content::Manifest::DisplayMode display, | |
428 const SkBitmap& icon_bitmap, | |
429 blink::WebScreenOrientationLockType orientation) { | |
430 DCHECK(base::WorkerPool::RunsTasksOnCurrentThread()); | |
431 | |
432 SkColor color = color_utils::CalculateKMeanColorOfBitmap(icon_bitmap); | |
241 int r_value = SkColorGetR(color); | 433 int r_value = SkColorGetR(color); |
242 int g_value = SkColorGetG(color); | 434 int g_value = SkColorGetG(color); |
243 int b_value = SkColorGetB(color); | 435 int b_value = SkColorGetB(color); |
244 | 436 |
245 // Send the data to the Java side to create the shortcut. | 437 // Send the data to the Java side to create the shortcut. |
246 JNIEnv* env = base::android::AttachCurrentThread(); | 438 JNIEnv* env = base::android::AttachCurrentThread(); |
247 ScopedJavaLocalRef<jstring> java_url = | 439 ScopedJavaLocalRef<jstring> java_url = |
248 base::android::ConvertUTF8ToJavaString(env, url.spec()); | 440 base::android::ConvertUTF8ToJavaString(env, url.spec()); |
249 ScopedJavaLocalRef<jstring> java_title = | 441 ScopedJavaLocalRef<jstring> java_title = |
250 base::android::ConvertUTF16ToJavaString(env, title); | 442 base::android::ConvertUTF16ToJavaString(env, title); |
251 ScopedJavaLocalRef<jobject> java_bitmap; | 443 ScopedJavaLocalRef<jobject> java_bitmap; |
252 if (favicon_bitmap.getSize()) | 444 if (icon_bitmap.getSize()) |
253 java_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap); | 445 java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap); |
254 | 446 |
255 Java_ShortcutHelper_addShortcut( | 447 Java_ShortcutHelper_addShortcut( |
256 env, | 448 env, |
257 base::android::GetApplicationContext(), | 449 base::android::GetApplicationContext(), |
258 java_url.obj(), | 450 java_url.obj(), |
259 java_title.obj(), | 451 java_title.obj(), |
260 java_bitmap.obj(), | 452 java_bitmap.obj(), |
261 r_value, | 453 r_value, |
262 g_value, | 454 g_value, |
263 b_value, | 455 b_value, |
264 display == content::Manifest::DISPLAY_MODE_STANDALONE, | 456 display == content::Manifest::DISPLAY_MODE_STANDALONE, |
265 orientation); | 457 orientation); |
266 } | 458 } |
OLD | NEW |