13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/android/shortcut_helper.h" 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <jni.h> 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <limits> 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/android/jni_android.h" 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/android/jni_string.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/basictypes.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/location.h" 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/strings/string16.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/strings/utf_string_conversions.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h" 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/worker_pool.h" 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/android/tab_android.h" 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/chrome_constants.h" 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/render_messages.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/web_application_info.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/web_contents.h" 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/common/frame_navigate_params.h" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/manifest.h" 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "jni/ShortcutHelper_jni.h" 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/mime_util.h" 313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/android/java_bitmap.h" 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/color_analysis.h" 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/screen.h" 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "url/gurl.h" 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing content::Manifest; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Android's preferred icon size in DP is 48, as defined in 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// http://developer.android.com/design/style/iconography.html 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int ShortcutHelper::kPreferredIconSizeInDp = 48; 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccijlong Initialize(JNIEnv* env, jobject obj, jlong tab_android_ptr) { 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TabAndroid* tab = reinterpret_cast<TabAndroid*>(tab_android_ptr); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShortcutHelper* shortcut_helper = 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new ShortcutHelper(env, obj, tab->web_contents()); 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci shortcut_helper->Initialize(); 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return reinterpret_cast<intptr_t>(shortcut_helper); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciShortcutHelper::ShortcutHelper(JNIEnv* env, 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci jobject obj, 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::WebContents* web_contents) 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : WebContentsObserver(web_contents), 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci java_ref_(env, obj), 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_(web_contents->GetURL()), 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_(content::Manifest::DISPLAY_MODE_BROWSER), 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci orientation_(blink::WebScreenOrientationLockDefault), 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci add_shortcut_requested_(false), 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_status_(MANIFEST_ICON_STATUS_NONE), 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci preferred_icon_size_in_px_(kPreferredIconSizeInDp * 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Screen::GetScreenFor(web_contents->GetNativeView())-> 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetPrimaryDisplay().device_scale_factor()), 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_(this) { 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::Initialize() { 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Send a message to the renderer to retrieve information about the page. 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id())); 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciShortcutHelper::~ShortcutHelper() { 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::OnDidGetWebApplicationInfo( 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const WebApplicationInfo& received_web_app_info) { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Sanitize received_web_app_info. 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WebApplicationInfo web_app_info = received_web_app_info; 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_app_info.title = 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_app_info.description = 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_ = web_app_info.title.empty() ? web_contents()->GetTitle() 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : web_app_info.title; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (web_app_info.mobile_capable == WebApplicationInfo::MOBILE_CAPABLE || 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_app_info.mobile_capable == WebApplicationInfo::MOBILE_CAPABLE_APPLE) { 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_ = content::Manifest::DISPLAY_MODE_STANDALONE; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Record what type of shortcut was added by the user. 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (web_app_info.mobile_capable) { 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case WebApplicationInfo::MOBILE_CAPABLE: 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction( 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::UserMetricsAction("webapps.AddShortcut.AppShortcut")); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case WebApplicationInfo::MOBILE_CAPABLE_APPLE: 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction( 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::UserMetricsAction("webapps.AddShortcut.AppShortcutApple")); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction( 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::UserMetricsAction("webapps.AddShortcut.Bookmark")); 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_contents()->GetManifest(base::Bind(&ShortcutHelper::OnDidGetManifest, 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr())); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ShortcutHelper::IconSizesContainsPreferredSize( 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<gfx::Size>& sizes) const { 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < sizes.size(); ++i) { 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sizes[i].height() != sizes[i].width()) 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sizes[i].width() == preferred_icon_size_in_px_) 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ShortcutHelper::IconSizesContainsAny( 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<gfx::Size>& sizes) const { 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < sizes.size(); ++i) { 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sizes[i].IsEmpty()) 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGURL ShortcutHelper::FindBestMatchingIcon( 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<Manifest::Icon>& icons, float density) const { 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL url; 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int best_delta = std::numeric_limits<int>::min(); 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < icons.size(); ++i) { 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].density != density) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<gfx::Size>& sizes = icons[i].sizes; 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t j = 0; j < sizes.size(); ++j) { 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sizes[j].height() != sizes[j].width()) 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int delta = sizes[j].width() - preferred_icon_size_in_px_; 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (delta == 0) 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return icons[i].src; 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (best_delta > 0 && delta < 0) 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((best_delta > 0 && delta < best_delta) || 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (best_delta < 0 && delta > best_delta)) { 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = icons[i].src; 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci best_delta = delta; 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return url; 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::vector<Manifest::Icon> ShortcutHelper::FilterIconsByType( 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<Manifest::Icon>& icons) { 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<Manifest::Icon> result; 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < icons.size(); ++i) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].type.is_null() || 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::IsSupportedImageMimeType( 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::UTF16ToUTF8(icons[i].type.string()))) { 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result.push_back(icons[i]); 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGURL ShortcutHelper::FindBestMatchingIcon( 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<Manifest::Icon>& unfiltered_icons) const { 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const float device_scale_factor = 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Screen::GetScreenFor(web_contents()->GetNativeView())-> 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetPrimaryDisplay().device_scale_factor(); 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL url; 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<Manifest::Icon> icons = FilterIconsByType(unfiltered_icons); 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The first pass is to find the ideal icon. That icon is of the right size 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // with the default density or the device's density. 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < icons.size(); ++i) { 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].density == device_scale_factor && 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconSizesContainsPreferredSize(icons[i].sizes)) { 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return icons[i].src; 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there is an icon with the right size but not the right density, keep 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it on the side and only use it if nothing better is found. 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].density == Manifest::Icon::kDefaultDensity && 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconSizesContainsPreferredSize(icons[i].sizes)) { 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = icons[i].src; 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The second pass is to find an icon with 'any'. The current device scale 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // factor is preferred. Otherwise, the default scale factor is used. 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < icons.size(); ++i) { 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].density == device_scale_factor && 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconSizesContainsAny(icons[i].sizes)) { 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return icons[i].src; 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there is an icon with 'any' but not the right density, keep it on the 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // side and only use it if nothing better is found. 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icons[i].density == Manifest::Icon::kDefaultDensity && 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconSizesContainsAny(icons[i].sizes)) { 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = icons[i].src; 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The last pass will try to find the best suitable icon for the device's 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scale factor. If none, another pass will be run using kDefaultDensity. 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!url.is_valid()) 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = FindBestMatchingIcon(icons, device_scale_factor); 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!url.is_valid()) 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = FindBestMatchingIcon(icons, Manifest::Icon::kDefaultDensity); 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return url; 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::OnDidGetManifest(const content::Manifest& manifest) { 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set the title based on the manifest value, if any. 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!manifest.short_name.is_null()) 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_ = manifest.short_name.string(); 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else if (!manifest.name.is_null()) 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_ = manifest.name.string(); 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set the url based on the manifest value, if any. 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manifest.start_url.is_valid()) 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_ = manifest.start_url; 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set the display based on the manifest value, if any. 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manifest.display != content::Manifest::DISPLAY_MODE_UNSPECIFIED) 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_ = manifest.display; 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 'fullscreen' and 'minimal-ui' are not yet supported, fallback to the right 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // mode in those cases. 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manifest.display == content::Manifest::DISPLAY_MODE_FULLSCREEN) 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_ = content::Manifest::DISPLAY_MODE_STANDALONE; 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manifest.display == content::Manifest::DISPLAY_MODE_MINIMAL_UI) 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_ = content::Manifest::DISPLAY_MODE_BROWSER; 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set the orientation based on the manifest value, if any. 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manifest.orientation != blink::WebScreenOrientationLockDefault) { 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Ignore the orientation if the display mode is different from 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 'standalone'. 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mlamouri): send a message to the developer console about this. 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (display_ == content::Manifest::DISPLAY_MODE_STANDALONE) 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci orientation_ = manifest.orientation; 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL icon_src = FindBestMatchingIcon(manifest.icons); 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icon_src.is_valid()) { 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_contents()->DownloadImage(icon_src, 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci false, 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci preferred_icon_size_in_px_, 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ShortcutHelper::OnDidDownloadIcon, 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr())); 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_status_ = MANIFEST_ICON_STATUS_FETCHING; 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The ShortcutHelper is now able to notify its Java counterpart that it is 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // initialized. OnInitialized method is not conceptually part of getting the 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // manifest data but it happens that the initialization is finalized when 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // these data are available. 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci JNIEnv* env = base::android::AttachCurrentThread(); 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedJavaLocalRef<jstring> j_title = 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::android::ConvertUTF16ToJavaString(env, title_); 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Java_ShortcutHelper_onInitialized(env, j_obj.obj(), j_title.obj()); 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::OnDidDownloadIcon(int id, 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int http_status_code, 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url, 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<SkBitmap>& bitmaps, 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<gfx::Size>& sizes) { 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If getting the candidate manifest icon failed, the ShortcutHelper should 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // fallback to the favicon. 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the user already requested to add the shortcut, it will do so but use 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the favicon instead. 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Otherwise, it sets the state as if there was no manifest icon pending. 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (bitmaps.empty()) { 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (add_shortcut_requested_) 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddShortcutUsingFavicon(); 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_status_ = MANIFEST_ICON_STATUS_NONE; 3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // There might be multiple bitmaps returned. The one to pick is bigger or 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // equal to the preferred size. |bitmaps| is ordered from bigger to smaller. 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int preferred_bitmap_index = 0; 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < bitmaps.size(); ++i) { 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (bitmaps[i].height() < preferred_icon_size_in_px_) 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci preferred_bitmap_index = i; 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_ = bitmaps[preferred_bitmap_index]; 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_status_ = MANIFEST_ICON_STATUS_DONE; 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (add_shortcut_requested_) 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddShortcutUsingManifestIcon(); 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::TearDown(JNIEnv*, jobject) { 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Destroy(); 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::Destroy() { 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete this; 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::AddShortcut( 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci JNIEnv* env, 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci jobject obj, 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci jstring jtitle, 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci jint launcher_large_icon_size) { 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci add_shortcut_requested_ = true; 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::string16 title = base::android::ConvertJavaStringToUTF16(env, jtitle); 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!title.empty()) 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_ = title; 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (manifest_icon_status_) { 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case MANIFEST_ICON_STATUS_NONE: 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddShortcutUsingFavicon(); 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case MANIFEST_ICON_STATUS_FETCHING: 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ::OnDidDownloadIcon() will call AddShortcutUsingManifestIcon(). 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case MANIFEST_ICON_STATUS_DONE: 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddShortcutUsingManifestIcon(); 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::AddShortcutUsingManifestIcon() { 3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Stop observing so we don't get destroyed while doing the last steps. 3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Observe(NULL); 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WorkerPool::PostTask( 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap, 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_, 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_, 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_, 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest_icon_, 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci orientation_), 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true); 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Destroy(); 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::AddShortcutUsingFavicon() { 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Profile* profile = 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Grab the best, largest icon we can find to represent this bookmark. 3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(dfalcantara): Try combining with the new BookmarksHandler once its 3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // rewrite is further along. 3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<int> icon_types; 3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types.push_back(favicon_base::FAVICON); 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types.push_back(favicon_base::TOUCH_PRECOMPOSED_ICON | 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::TOUCH_ICON); 3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) profile, Profile::EXPLICIT_ACCESS); 3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Using favicon if its size is not smaller than platform required size, 3841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // otherwise using the largest icon among all avaliable icons. 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int threshold_to_get_any_largest_icon = preferred_icon_size_in_px_ - 1; 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch favicon_service->GetLargestRawFaviconForPageURL(url_, icon_types, 3871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) threshold_to_get_any_largest_icon, 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ShortcutHelper::OnDidGetFavicon, 389424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(this)), 3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &cancelable_task_tracker_); 3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::OnDidGetFavicon( 394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const favicon_base::FaviconRawBitmapResult& bitmap_result) { 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Stop observing so we don't get destroyed while doing the last steps. 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Observe(NULL); 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::WorkerPool::PostTask( 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FROM_HERE, 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithRawBitmap, 401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) url_, 402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) title_, 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display_, 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bitmap_result, 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci orientation_), 406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) true); 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Destroy(); 4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ShortcutHelper::OnMessageReceived(const IPC::Message& message) { 4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool handled = true; 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_BEGIN_MESSAGE_MAP(ShortcutHelper, message) 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnDidGetWebApplicationInfo) 4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) IPC_END_MESSAGE_MAP() 4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return handled; 4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::WebContentsDestroyed() { 424424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Destroy(); 425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ShortcutHelper::RegisterShortcutHelper(JNIEnv* env) { 4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return RegisterNativesImpl(env); 4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::AddShortcutInBackgroundWithRawBitmap( 4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GURL& url, 433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title, 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::Manifest::DisplayMode display, 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const favicon_base::FaviconRawBitmapResult& bitmap_result, 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebScreenOrientationLockType orientation) { 4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(base::WorkerPool::RunsTasksOnCurrentThread()); 4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SkBitmap icon_bitmap; 4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (bitmap_result.is_valid()) { 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bitmap_result.bitmap_data->size(), 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &icon_bitmap); 4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddShortcutInBackgroundWithSkBitmap( 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, title, display, icon_bitmap, orientation); 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ShortcutHelper::AddShortcutInBackgroundWithSkBitmap( 4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url, 4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::string16& title, 4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::Manifest::DisplayMode display, 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const SkBitmap& icon_bitmap, 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebScreenOrientationLockType orientation) { 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(base::WorkerPool::RunsTasksOnCurrentThread()); 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SkColor color = color_utils::CalculateKMeanColorOfBitmap(icon_bitmap); 4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int r_value = SkColorGetR(color); 4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int g_value = SkColorGetG(color); 4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int b_value = SkColorGetB(color); 4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Send the data to the Java side to create the shortcut. 4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ScopedJavaLocalRef<jstring> java_url = 4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::android::ConvertUTF8ToJavaString(env, url.spec()); 4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ScopedJavaLocalRef<jstring> java_title = 4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::android::ConvertUTF16ToJavaString(env, title); 4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ScopedJavaLocalRef<jobject> java_bitmap; 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icon_bitmap.getSize()) 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap); 4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Java_ShortcutHelper_addShortcut( 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci env, 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::android::GetApplicationContext(), 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci java_url.obj(), 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci java_title.obj(), 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci java_bitmap.obj(), 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci r_value, 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_value, 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci b_value, 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci display == content::Manifest::DISPLAY_MODE_STANDALONE, 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci orientation); 4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 485