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

Side by Side Diff: chrome/browser/ui/web_applications/web_app_ui.cc

Issue 213113005: Remove web_app_ui.[cc|h]. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 6 years, 8 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/web_applications/web_app_ui.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/file_util.h"
10 #include "base/path_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/extensions/tab_helper.h"
14 #include "chrome/browser/favicon/favicon_tab_helper.h"
15 #include "chrome/browser/history/select_favicon_frames.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/web_applications/web_app.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/notification_source.h"
22 #include "content/public/browser/web_contents.h"
23 #include "url/gurl.h"
24
25 #if defined(OS_POSIX) && !defined(OS_MACOSX)
26 #include "base/environment.h"
27 #endif
28
29 #if defined(OS_WIN)
30 #include "base/win/shortcut.h"
31 #include "base/win/windows_version.h"
32 #include "chrome/browser/web_applications/web_app_win.h"
33 #include "ui/gfx/icon_util.h"
34 #endif
35
36 using content::BrowserThread;
37 using content::NavigationController;
38 using content::WebContents;
39
40 namespace {
41
42 // TODO(jackhou): Move all win-specific code to web_app_win.
43 #if defined(OS_WIN)
44 // UpdateShortcutWorker holds all context data needed for update shortcut.
45 // It schedules a pre-update check to find all shortcuts that needs to be
46 // updated. If there are such shortcuts, it schedules icon download and
47 // update them when icons are downloaded. It observes TAB_CLOSING notification
48 // and cancels all the work when the underlying tab is closing.
49 class UpdateShortcutWorker : public content::NotificationObserver {
50 public:
51 explicit UpdateShortcutWorker(WebContents* web_contents);
52
53 void Run();
54
55 private:
56 // Overridden from content::NotificationObserver:
57 virtual void Observe(int type,
58 const content::NotificationSource& source,
59 const content::NotificationDetails& details);
60
61 // Downloads icon via the FaviconTabHelper.
62 void DownloadIcon();
63
64 // Favicon download callback.
65 void DidDownloadFavicon(
66 int requested_size,
67 int id,
68 int http_status_code,
69 const GURL& image_url,
70 const std::vector<SkBitmap>& bitmaps,
71 const std::vector<gfx::Size>& original_bitmap_sizes);
72
73 // Checks if shortcuts exists on desktop, start menu and quick launch.
74 void CheckExistingShortcuts();
75
76 // Update shortcut files and icons.
77 void UpdateShortcuts();
78 void UpdateShortcutsOnFileThread();
79
80 // Callback after shortcuts are updated.
81 void OnShortcutsUpdated(bool);
82
83 // Deletes the worker on UI thread where it gets created.
84 void DeleteMe();
85 void DeleteMeOnUIThread();
86
87 content::NotificationRegistrar registrar_;
88
89 // Underlying WebContents whose shortcuts will be updated.
90 WebContents* web_contents_;
91
92 // Icons info from web_contents_'s web app data.
93 web_app::IconInfoList unprocessed_icons_;
94
95 // Cached shortcut data from the web_contents_.
96 ShellIntegration::ShortcutInfo shortcut_info_;
97
98 // Our copy of profile path.
99 base::FilePath profile_path_;
100
101 // File name of shortcut/ico file based on app title.
102 base::FilePath file_name_;
103
104 // Existing shortcuts.
105 std::vector<base::FilePath> shortcut_files_;
106
107 DISALLOW_COPY_AND_ASSIGN(UpdateShortcutWorker);
108 };
109
110 UpdateShortcutWorker::UpdateShortcutWorker(WebContents* web_contents)
111 : web_contents_(web_contents),
112 profile_path_(Profile::FromBrowserContext(
113 web_contents->GetBrowserContext())->GetPath()) {
114 extensions::TabHelper* extensions_tab_helper =
115 extensions::TabHelper::FromWebContents(web_contents);
116 web_app::GetShortcutInfoForTab(web_contents_, &shortcut_info_);
117 web_app::GetIconsInfo(extensions_tab_helper->web_app_info(),
118 &unprocessed_icons_);
119 file_name_ = web_app::internals::GetSanitizedFileName(shortcut_info_.title);
120
121 registrar_.Add(
122 this,
123 chrome::NOTIFICATION_TAB_CLOSING,
124 content::Source<NavigationController>(&web_contents->GetController()));
125 }
126
127 void UpdateShortcutWorker::Run() {
128 // Starting by downloading app icon.
129 DownloadIcon();
130 }
131
132 void UpdateShortcutWorker::Observe(
133 int type,
134 const content::NotificationSource& source,
135 const content::NotificationDetails& details) {
136 if (type == chrome::NOTIFICATION_TAB_CLOSING &&
137 content::Source<NavigationController>(source).ptr() ==
138 &web_contents_->GetController()) {
139 // Underlying tab is closing.
140 web_contents_ = NULL;
141 }
142 }
143
144 void UpdateShortcutWorker::DownloadIcon() {
145 // FetchIcon must run on UI thread because it relies on WebContents
146 // to download the icon.
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
148
149 if (web_contents_ == NULL) {
150 DeleteMe(); // We are done if underlying WebContents is gone.
151 return;
152 }
153
154 if (unprocessed_icons_.empty()) {
155 // No app icon. Just use the favicon from WebContents.
156 UpdateShortcuts();
157 return;
158 }
159
160 int preferred_size = std::max(unprocessed_icons_.back().width,
161 unprocessed_icons_.back().height);
162 web_contents_->DownloadImage(
163 unprocessed_icons_.back().url,
164 true, // favicon
165 0, // no maximum size
166 base::Bind(&UpdateShortcutWorker::DidDownloadFavicon,
167 base::Unretained(this),
168 preferred_size));
169 unprocessed_icons_.pop_back();
170 }
171
172 void UpdateShortcutWorker::DidDownloadFavicon(
173 int requested_size,
174 int id,
175 int http_status_code,
176 const GURL& image_url,
177 const std::vector<SkBitmap>& bitmaps,
178 const std::vector<gfx::Size>& original_sizes) {
179 std::vector<ui::ScaleFactor> scale_factors;
180 scale_factors.push_back(ui::SCALE_FACTOR_100P);
181
182 std::vector<size_t> closest_indices;
183 SelectFaviconFrameIndices(original_sizes,
184 scale_factors,
185 requested_size,
186 &closest_indices,
187 NULL);
188 size_t closest_index = closest_indices[0];
189
190 if (!bitmaps.empty() && !bitmaps[closest_index].isNull()) {
191 // Update icon with download image and update shortcut.
192 shortcut_info_.favicon.Add(
193 gfx::Image::CreateFrom1xBitmap(bitmaps[closest_index]));
194 extensions::TabHelper* extensions_tab_helper =
195 extensions::TabHelper::FromWebContents(web_contents_);
196 extensions_tab_helper->SetAppIcon(bitmaps[closest_index]);
197 UpdateShortcuts();
198 } else {
199 // Try the next icon otherwise.
200 DownloadIcon();
201 }
202 }
203
204 void UpdateShortcutWorker::CheckExistingShortcuts() {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
206
207 // Locations to check to shortcut_paths.
208 struct {
209 int location_id;
210 const wchar_t* sub_dir;
211 } locations[] = {
212 {
213 base::DIR_USER_DESKTOP,
214 NULL
215 }, {
216 base::DIR_START_MENU,
217 NULL
218 }, {
219 // For Win7, create_in_quick_launch_bar means pinning to taskbar.
220 base::DIR_APP_DATA,
221 (base::win::GetVersion() >= base::win::VERSION_WIN7) ?
222 L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar" :
223 L"Microsoft\\Internet Explorer\\Quick Launch"
224 }
225 };
226
227 for (int i = 0; i < arraysize(locations); ++i) {
228 base::FilePath path;
229 if (!PathService::Get(locations[i].location_id, &path)) {
230 NOTREACHED();
231 continue;
232 }
233
234 if (locations[i].sub_dir != NULL)
235 path = path.Append(locations[i].sub_dir);
236
237 base::FilePath shortcut_file = path.Append(file_name_).
238 ReplaceExtension(FILE_PATH_LITERAL(".lnk"));
239 if (base::PathExists(shortcut_file)) {
240 shortcut_files_.push_back(shortcut_file);
241 }
242 }
243 }
244
245 void UpdateShortcutWorker::UpdateShortcuts() {
246 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
247 base::Bind(&UpdateShortcutWorker::UpdateShortcutsOnFileThread,
248 base::Unretained(this)));
249 }
250
251 void UpdateShortcutWorker::UpdateShortcutsOnFileThread() {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
253
254 base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
255 profile_path_, shortcut_info_.extension_id, shortcut_info_.url);
256
257 // Ensure web_app_path exists. web_app_path could be missing for a legacy
258 // shortcut created by Gears.
259 if (!base::PathExists(web_app_path) &&
260 !base::CreateDirectory(web_app_path)) {
261 NOTREACHED();
262 return;
263 }
264
265 base::FilePath icon_file =
266 web_app::internals::GetIconFilePath(web_app_path, shortcut_info_.title);
267 web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon);
268
269 // Update existing shortcuts' description, icon and app id.
270 CheckExistingShortcuts();
271 if (!shortcut_files_.empty()) {
272 // Generates app id from web app url and profile path.
273 base::string16 app_id = ShellIntegration::GetAppModelIdForProfile(
274 base::UTF8ToWide(
275 web_app::GenerateApplicationNameFromURL(shortcut_info_.url)),
276 profile_path_);
277
278 // Sanitize description
279 if (shortcut_info_.description.length() >= MAX_PATH)
280 shortcut_info_.description.resize(MAX_PATH - 1);
281
282 for (size_t i = 0; i < shortcut_files_.size(); ++i) {
283 base::win::ShortcutProperties shortcut_properties;
284 shortcut_properties.set_target(shortcut_files_[i]);
285 shortcut_properties.set_description(shortcut_info_.description);
286 shortcut_properties.set_icon(icon_file, 0);
287 shortcut_properties.set_app_id(app_id);
288 base::win::CreateOrUpdateShortcutLink(
289 shortcut_files_[i], shortcut_properties,
290 base::win::SHORTCUT_UPDATE_EXISTING);
291 }
292 }
293
294 OnShortcutsUpdated(true);
295 }
296
297 void UpdateShortcutWorker::OnShortcutsUpdated(bool) {
298 DeleteMe(); // We are done.
299 }
300
301 void UpdateShortcutWorker::DeleteMe() {
302 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
303 DeleteMeOnUIThread();
304 } else {
305 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
306 base::Bind(&UpdateShortcutWorker::DeleteMeOnUIThread,
307 base::Unretained(this)));
308 }
309 }
310
311 void UpdateShortcutWorker::DeleteMeOnUIThread() {
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313 delete this;
314 }
315 #endif // defined(OS_WIN)
316
317 } // namespace
318
319 namespace web_app {
320
321 void GetShortcutInfoForTab(WebContents* web_contents,
322 ShellIntegration::ShortcutInfo* info) {
323 DCHECK(info); // Must provide a valid info.
324
325 const FaviconTabHelper* favicon_tab_helper =
326 FaviconTabHelper::FromWebContents(web_contents);
327 const extensions::TabHelper* extensions_tab_helper =
328 extensions::TabHelper::FromWebContents(web_contents);
329 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info();
330
331 info->url = app_info.app_url.is_empty() ? web_contents->GetURL() :
332 app_info.app_url;
333 info->title = app_info.title.empty() ?
334 (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) :
335 web_contents->GetTitle()) :
336 app_info.title;
337 info->description = app_info.description;
338 info->favicon.Add(favicon_tab_helper->GetFavicon());
339
340 Profile* profile =
341 Profile::FromBrowserContext(web_contents->GetBrowserContext());
342 info->profile_path = profile->GetPath();
343 }
344
345 void UpdateShortcutForTabContents(WebContents* web_contents) {
346 #if defined(OS_WIN)
347 // UpdateShortcutWorker will delete itself when it's done.
348 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents);
349 worker->Run();
350 #endif // defined(OS_WIN)
351 }
352
353 } // namespace web_app
OLDNEW
« no previous file with comments | « chrome/browser/ui/web_applications/web_app_ui.h ('k') | chrome/browser/web_applications/update_shortcut_worker_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698