Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc

Issue 2230773002: Migrate add to homescreen data fetcher to use InstallableManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/webapps/add_to_homescreen_data_fetcher.h" 5 #include "chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h"
6 6
7 #include <vector>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/callback.h" 10 #include "base/callback.h"
9 #include "base/location.h" 11 #include "base/location.h"
10 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
11 #include "base/task/cancelable_task_tracker.h"
12 #include "chrome/browser/android/offline_pages/offline_page_utils.h" 13 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
13 #include "chrome/browser/android/shortcut_helper.h" 14 #include "chrome/browser/android/shortcut_helper.h"
14 #include "chrome/browser/favicon/favicon_service_factory.h" 15 #include "chrome/browser/favicon/favicon_service_factory.h"
15 #include "chrome/browser/manifest/manifest_icon_downloader.h" 16 #include "chrome/browser/installable/installable_manager.h"
16 #include "chrome/browser/manifest/manifest_icon_selector.h" 17 #include "chrome/browser/manifest/manifest_icon_selector.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/chrome_constants.h" 19 #include "chrome/common/chrome_constants.h"
19 #include "chrome/common/render_messages.h" 20 #include "chrome/common/render_messages.h"
20 #include "chrome/common/web_application_info.h" 21 #include "chrome/common/web_application_info.h"
21 #include "components/dom_distiller/core/url_utils.h" 22 #include "components/dom_distiller/core/url_utils.h"
22 #include "components/favicon/core/favicon_service.h" 23 #include "components/favicon/core/favicon_service.h"
23 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/user_metrics.h" 25 #include "content/public/browser/user_metrics.h"
25 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_contents_observer.h" 27 #include "content/public/browser/web_contents_observer.h"
27 #include "content/public/common/frame_navigate_params.h"
28 #include "content/public/common/manifest.h" 28 #include "content/public/common/manifest.h"
29 #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScree nOrientationLockType.h" 29 #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScree nOrientationLockType.h"
30 #include "ui/display/display.h" 30 #include "ui/display/display.h"
31 #include "ui/display/screen.h" 31 #include "ui/display/screen.h"
32 #include "ui/gfx/codec/png_codec.h" 32 #include "ui/gfx/codec/png_codec.h"
33 #include "ui/gfx/favicon_size.h" 33 #include "ui/gfx/favicon_size.h"
34 #include "url/gurl.h" 34 #include "url/gurl.h"
35 35
36 using content::Manifest; 36 namespace {
37
38 InstallableParams ParamsToPerformInstallableCheck(int ideal_icon_size_in_dp,
39 int minimum_icon_size_in_dp) {
40 // TODO(hanxi): change check_installable to true for WebAPKs.
41 InstallableParams params;
42 params.ideal_icon_size_in_dp = ideal_icon_size_in_dp;
43 params.minimum_icon_size_in_dp = minimum_icon_size_in_dp;
44 params.check_installable = false;
45 params.fetch_valid_icon = true;
46 return params;
47 }
48
49 } // namespace
37 50
38 AddToHomescreenDataFetcher::AddToHomescreenDataFetcher( 51 AddToHomescreenDataFetcher::AddToHomescreenDataFetcher(
39 content::WebContents* web_contents, 52 content::WebContents* web_contents,
40 int ideal_icon_size_in_dp, 53 int ideal_icon_size_in_dp,
41 int minimum_icon_size_in_dp, 54 int minimum_icon_size_in_dp,
42 int ideal_splash_image_size_in_dp, 55 int ideal_splash_image_size_in_dp,
43 int minimum_splash_image_size_in_dp, 56 int minimum_splash_image_size_in_dp,
44 Observer* observer) 57 Observer* observer)
45 : WebContentsObserver(web_contents), 58 : WebContentsObserver(web_contents),
46 weak_observer_(observer), 59 weak_observer_(observer),
47 is_waiting_for_web_application_info_(false), 60 is_waiting_for_web_application_info_(false),
48 is_icon_saved_(false), 61 is_icon_saved_(false),
49 is_ready_(false), 62 is_ready_(false),
50 icon_timeout_timer_(false, false), 63 data_timeout_timer_(false, false),
51 shortcut_info_(GetShortcutUrl(web_contents->GetURL())), 64 shortcut_info_(GetShortcutUrl(web_contents->GetURL())),
52 ideal_icon_size_in_dp_(ideal_icon_size_in_dp), 65 ideal_icon_size_in_dp_(ideal_icon_size_in_dp),
53 minimum_icon_size_in_dp_(minimum_icon_size_in_dp), 66 minimum_icon_size_in_dp_(minimum_icon_size_in_dp),
54 ideal_splash_image_size_in_dp_(ideal_splash_image_size_in_dp), 67 ideal_splash_image_size_in_dp_(ideal_splash_image_size_in_dp),
55 minimum_splash_image_size_in_dp_(minimum_splash_image_size_in_dp) { 68 minimum_splash_image_size_in_dp_(minimum_splash_image_size_in_dp) {
56 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp); 69 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp);
57 DCHECK(minimum_splash_image_size_in_dp <= ideal_splash_image_size_in_dp); 70 DCHECK(minimum_splash_image_size_in_dp <= ideal_splash_image_size_in_dp);
58 71
59 // Send a message to the renderer to retrieve information about the page. 72 // Send a message to the renderer to retrieve information about the page.
60 is_waiting_for_web_application_info_ = true; 73 is_waiting_for_web_application_info_ = true;
61 Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id())); 74 Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id()));
62 } 75 }
63 76
64 void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo( 77 void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo(
65 const WebApplicationInfo& received_web_app_info) { 78 const WebApplicationInfo& received_web_app_info) {
66 is_waiting_for_web_application_info_ = false; 79 is_waiting_for_web_application_info_ = false;
67 if (!web_contents() || !weak_observer_) return; 80 if (!web_contents() || !weak_observer_)
81 return;
68 82
69 // Sanitize received_web_app_info. 83 // Sanitize received_web_app_info.
70 WebApplicationInfo web_app_info = received_web_app_info; 84 WebApplicationInfo web_app_info = received_web_app_info;
71 web_app_info.title = 85 web_app_info.title =
72 web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength); 86 web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength);
73 web_app_info.description = 87 web_app_info.description =
74 web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength); 88 web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength);
75 89
76 // Simply set the user-editable title to be the page's title 90 // Simply set the user-editable title to be the page's title
77 shortcut_info_.user_title = web_app_info.title.empty() 91 shortcut_info_.user_title = web_app_info.title.empty()
(...skipping 16 matching lines...) Expand all
94 case WebApplicationInfo::MOBILE_CAPABLE_APPLE: 108 case WebApplicationInfo::MOBILE_CAPABLE_APPLE:
95 content::RecordAction( 109 content::RecordAction(
96 base::UserMetricsAction("webapps.AddShortcut.AppShortcutApple")); 110 base::UserMetricsAction("webapps.AddShortcut.AppShortcutApple"));
97 break; 111 break;
98 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED: 112 case WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED:
99 content::RecordAction( 113 content::RecordAction(
100 base::UserMetricsAction("webapps.AddShortcut.Bookmark")); 114 base::UserMetricsAction("webapps.AddShortcut.Bookmark"));
101 break; 115 break;
102 } 116 }
103 117
104 web_contents()->GetManifest( 118 InstallableManager::CreateForWebContents(web_contents());
gone 2016/08/10 22:31:58 Is this a no-op if it's already happened once?
dominickn 2016/08/10 23:31:46 Yes, this does nothing if the manager has already
105 base::Bind(&AddToHomescreenDataFetcher::OnDidGetManifest, this)); 119 InstallableManager* manager =
120 InstallableManager::FromWebContents(web_contents());
121 DCHECK(manager);
122
123 // Kick off a timeout for downloading data. If we haven't finished within the
124 // timeout, fall back to using a dynamically-generated launcher icon.
125 data_timeout_timer_.Start(
126 FROM_HERE, base::TimeDelta::FromMilliseconds(4000),
127 base::Bind(&AddToHomescreenDataFetcher::OnFaviconFetched, this,
128 favicon_base::FaviconRawBitmapResult()));
129
130 manager->GetData(
131 ParamsToPerformInstallableCheck(ideal_icon_size_in_dp_,
132 minimum_icon_size_in_dp_),
133 base::Bind(&AddToHomescreenDataFetcher::OnDidPerformInstallableCheck,
134 this));
106 } 135 }
107 136
108 void AddToHomescreenDataFetcher::OnDidGetManifest( 137 void AddToHomescreenDataFetcher::OnDidPerformInstallableCheck(
109 const GURL& manifest_url, 138 const InstallableData& data) {
110 const content::Manifest& manifest) { 139 if (!web_contents() || !weak_observer_)
111 if (!web_contents() || !weak_observer_) return; 140 return;
112 141
113 if (!manifest.IsEmpty()) { 142 if (!data.manifest.IsEmpty()) {
114 content::RecordAction( 143 content::RecordAction(
115 base::UserMetricsAction("webapps.AddShortcut.Manifest")); 144 base::UserMetricsAction("webapps.AddShortcut.Manifest"));
116 shortcut_info_.UpdateFromManifest(manifest); 145 shortcut_info_.UpdateFromManifest(data.manifest);
117 shortcut_info_.manifest_url = manifest_url; 146 shortcut_info_.manifest_url = data.manifest_url;
118 }
119
120 GURL icon_src = ManifestIconSelector::FindBestMatchingIcon(
121 manifest.icons, ideal_icon_size_in_dp_, minimum_icon_size_in_dp_);
122
123 // If fetching the Manifest icon fails, fallback to the best favicon
124 // for the page.
125 if (!ManifestIconDownloader::Download(
126 web_contents(),
127 icon_src,
128 ideal_icon_size_in_dp_,
129 minimum_icon_size_in_dp_,
130 base::Bind(&AddToHomescreenDataFetcher::OnManifestIconFetched,
131 this, icon_src))) {
132 FetchFavicon();
133 } 147 }
134 148
135 // Save the splash screen URL for the later download. 149 // Save the splash screen URL for the later download.
136 splash_screen_url_ = ManifestIconSelector::FindBestMatchingIcon( 150 splash_screen_url_ = ManifestIconSelector::FindBestMatchingIcon(
137 manifest.icons, ideal_splash_image_size_in_dp_, 151 data.manifest.icons, ideal_splash_image_size_in_dp_,
138 minimum_splash_image_size_in_dp_); 152 minimum_splash_image_size_in_dp_);
139 153
140 weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title); 154 weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title);
141 155
142 // Kick off a timeout for downloading the icon. If an icon isn't set within 156 if (data.icon && !data.icon->drawsNothing()) {
143 // the timeout, fall back to using a dynamically-generated launcher icon. 157 // TODO(hanxi): implement WebAPK path if shortcut_info_.url has a secure
144 icon_timeout_timer_.Start(FROM_HERE, 158 // scheme and data.is_installable is true.
145 base::TimeDelta::FromMilliseconds(3000), 159 shortcut_info_.icon_url = data.icon_url;
146 base::Bind( 160 NotifyObserver(*(data.icon));
147 &AddToHomescreenDataFetcher::OnFaviconFetched, 161 return;
148 this, 162 }
149 favicon_base::FaviconRawBitmapResult())); 163
164 FetchFavicon();
150 } 165 }
151 166
152 bool AddToHomescreenDataFetcher::OnMessageReceived( 167 bool AddToHomescreenDataFetcher::OnMessageReceived(
153 const IPC::Message& message) { 168 const IPC::Message& message) {
154 if (!is_waiting_for_web_application_info_) return false; 169 if (!is_waiting_for_web_application_info_)
170 return false;
155 171
156 bool handled = true; 172 bool handled = true;
157 173
158 IPC_BEGIN_MESSAGE_MAP(AddToHomescreenDataFetcher, message) 174 IPC_BEGIN_MESSAGE_MAP(AddToHomescreenDataFetcher, message)
159 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo, 175 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo,
160 OnDidGetWebApplicationInfo) 176 OnDidGetWebApplicationInfo)
161 IPC_MESSAGE_UNHANDLED(handled = false) 177 IPC_MESSAGE_UNHANDLED(handled = false)
162 IPC_END_MESSAGE_MAP() 178 IPC_END_MESSAGE_MAP()
163 179
164 return handled; 180 return handled;
165 } 181 }
166 182
167 AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() { 183 AddToHomescreenDataFetcher::~AddToHomescreenDataFetcher() {
168 DCHECK(!weak_observer_); 184 DCHECK(!weak_observer_);
169 } 185 }
170 186
171 base::Closure AddToHomescreenDataFetcher::FetchSplashScreenImageCallback( 187 base::Closure AddToHomescreenDataFetcher::FetchSplashScreenImageCallback(
172 const std::string& webapp_id) { 188 const std::string& webapp_id) {
173 return base::Bind(&ShortcutHelper::FetchSplashScreenImage, web_contents(), 189 return base::Bind(&ShortcutHelper::FetchSplashScreenImage, web_contents(),
174 splash_screen_url_, ideal_splash_image_size_in_dp_, 190 splash_screen_url_, ideal_splash_image_size_in_dp_,
175 minimum_splash_image_size_in_dp_, webapp_id); 191 minimum_splash_image_size_in_dp_, webapp_id);
176 } 192 }
177 193
178 void AddToHomescreenDataFetcher::FetchFavicon() { 194 void AddToHomescreenDataFetcher::FetchFavicon() {
179 if (!web_contents() || !weak_observer_) return; 195 if (!web_contents() || !weak_observer_)
180 196 return;
181 Profile* profile =
182 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
183 197
184 // Grab the best, largest icon we can find to represent this bookmark. 198 // Grab the best, largest icon we can find to represent this bookmark.
185 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its 199 // TODO(dfalcantara): Try combining with the new BookmarksHandler once its
186 // rewrite is further along. 200 // rewrite is further along.
187 std::vector<int> icon_types; 201 std::vector<int> icon_types = {
188 icon_types.push_back(favicon_base::FAVICON); 202 favicon_base::FAVICON,
189 icon_types.push_back(favicon_base::TOUCH_PRECOMPOSED_ICON | 203 favicon_base::TOUCH_PRECOMPOSED_ICON | favicon_base::TOUCH_ICON};
gone 2016/08/10 22:31:58 Should }; go on the next line down? Honestly unsu
dominickn 2016/08/10 23:31:46 This is what clang-format gave me! Seems weird, bu
190 favicon_base::TOUCH_ICON);
191 favicon::FaviconService* favicon_service = 204 favicon::FaviconService* favicon_service =
192 FaviconServiceFactory::GetForProfile(profile, 205 FaviconServiceFactory::GetForProfile(
193 ServiceAccessType::EXPLICIT_ACCESS); 206 Profile::FromBrowserContext(web_contents()->GetBrowserContext()),
207 ServiceAccessType::EXPLICIT_ACCESS);
194 208
195 // Using favicon if its size is not smaller than platform required size, 209 // Using favicon if its size is not smaller than platform required size,
196 // otherwise using the largest icon among all avaliable icons. 210 // otherwise using the largest icon among all avaliable icons.
197 int ideal_icon_size_in_px = 211 int ideal_icon_size_in_px =
198 ideal_icon_size_in_dp_ * 212 ideal_icon_size_in_dp_ *
199 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); 213 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
200 int threshold_to_get_any_largest_icon = ideal_icon_size_in_px - 1; 214 int threshold_to_get_any_largest_icon = ideal_icon_size_in_px - 1;
201 favicon_service->GetLargestRawFaviconForPageURL( 215 favicon_service->GetLargestRawFaviconForPageURL(
202 shortcut_info_.url, 216 shortcut_info_.url,
203 icon_types, 217 icon_types,
(...skipping 10 matching lines...) Expand all
214 content::BrowserThread::PostTask( 228 content::BrowserThread::PostTask(
215 content::BrowserThread::IO, 229 content::BrowserThread::IO,
216 FROM_HERE, 230 FROM_HERE,
217 base::Bind(&AddToHomescreenDataFetcher::CreateLauncherIcon, 231 base::Bind(&AddToHomescreenDataFetcher::CreateLauncherIcon,
218 this, 232 this,
219 bitmap_result)); 233 bitmap_result));
220 } 234 }
221 235
222 void AddToHomescreenDataFetcher::CreateLauncherIcon( 236 void AddToHomescreenDataFetcher::CreateLauncherIcon(
223 const favicon_base::FaviconRawBitmapResult& bitmap_result) { 237 const favicon_base::FaviconRawBitmapResult& bitmap_result) {
224 if (!web_contents() || !weak_observer_) return; 238 if (!web_contents() || !weak_observer_)
239 return;
225 240
226 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 241 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
227 SkBitmap icon_bitmap; 242 SkBitmap icon_bitmap;
228 if (bitmap_result.is_valid()) { 243 if (bitmap_result.is_valid()) {
229 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), 244 gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(),
230 bitmap_result.bitmap_data->size(), 245 bitmap_result.bitmap_data->size(),
231 &icon_bitmap); 246 &icon_bitmap);
232 } 247 }
233 248
234 bool is_generated = false; 249 bool is_generated = false;
235 if (weak_observer_) { 250 if (weak_observer_) {
236 icon_bitmap = weak_observer_->FinalizeLauncherIcon(icon_bitmap, 251 icon_bitmap = weak_observer_->FinalizeLauncherIcon(icon_bitmap,
237 shortcut_info_.url, 252 shortcut_info_.url,
238 &is_generated); 253 &is_generated);
239 } 254 }
240 255
241 shortcut_info_.icon_url = is_generated ? GURL() : bitmap_result.icon_url; 256 shortcut_info_.icon_url = is_generated ? GURL() : bitmap_result.icon_url;
242 content::BrowserThread::PostTask( 257 content::BrowserThread::PostTask(
243 content::BrowserThread::UI, FROM_HERE, 258 content::BrowserThread::UI, FROM_HERE,
244 base::Bind(&AddToHomescreenDataFetcher::NotifyObserver, this, 259 base::Bind(&AddToHomescreenDataFetcher::NotifyObserver, this,
245 icon_bitmap)); 260 icon_bitmap));
246 } 261 }
247 262
248 void AddToHomescreenDataFetcher::OnManifestIconFetched(const GURL& icon_url,
249 const SkBitmap& icon) {
250 if (icon.drawsNothing()) {
251 FetchFavicon();
252 return;
253 }
254 shortcut_info_.icon_url = icon_url;
255 NotifyObserver(icon);
256 }
257
258 void AddToHomescreenDataFetcher::NotifyObserver(const SkBitmap& bitmap) { 263 void AddToHomescreenDataFetcher::NotifyObserver(const SkBitmap& bitmap) {
259 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 264 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
260 if (!web_contents() || !weak_observer_ || is_icon_saved_) 265 if (!web_contents() || !weak_observer_ || is_icon_saved_)
261 return; 266 return;
262 267
263 is_icon_saved_ = true; 268 is_icon_saved_ = true;
264 shortcut_icon_ = bitmap; 269 shortcut_icon_ = bitmap;
265 is_ready_ = true; 270 is_ready_ = true;
266 weak_observer_->OnDataAvailable(shortcut_info_, shortcut_icon_); 271 weak_observer_->OnDataAvailable(shortcut_info_, shortcut_icon_);
267 } 272 }
268 273
269 GURL AddToHomescreenDataFetcher::GetShortcutUrl(const GURL& actual_url) { 274 GURL AddToHomescreenDataFetcher::GetShortcutUrl(const GURL& actual_url) {
270 GURL original_url = 275 GURL original_url =
271 dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(actual_url); 276 dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(actual_url);
272 277
273 // If URL points to an offline content, get original URL. 278 // If URL points to an offline content, get original URL.
274 GURL online_url = 279 GURL online_url =
275 offline_pages::OfflinePageUtils::MaybeGetOnlineURLForOfflineURL( 280 offline_pages::OfflinePageUtils::MaybeGetOnlineURLForOfflineURL(
276 web_contents()->GetBrowserContext(), original_url); 281 web_contents()->GetBrowserContext(), original_url);
277 if (online_url.is_valid()) 282 if (online_url.is_valid())
278 return online_url; 283 return online_url;
279 284
280 return original_url; 285 return original_url;
281 } 286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698