OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/jumplist_win.h" | 5 #include "chrome/browser/jumplist_win.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
12 #include "base/prefs/pref_change_registrar.h" | |
12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
14 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
15 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
16 #include "chrome/browser/favicon/favicon_service.h" | 17 #include "chrome/browser/favicon/favicon_service.h" |
17 #include "chrome/browser/favicon/favicon_service_factory.h" | 18 #include "chrome/browser/favicon/favicon_service_factory.h" |
18 #include "chrome/browser/history/history_service.h" | 19 #include "chrome/browser/history/history_service.h" |
19 #include "chrome/browser/history/top_sites.h" | 20 #include "chrome/browser/history/top_sites.h" |
20 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
21 #include "chrome/browser/sessions/session_types.h" | 22 #include "chrome/browser/sessions/session_types.h" |
22 #include "chrome/browser/sessions/tab_restore_service.h" | 23 #include "chrome/browser/sessions/tab_restore_service.h" |
23 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 24 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
24 #include "chrome/browser/shell_integration.h" | 25 #include "chrome/browser/shell_integration.h" |
25 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
26 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
28 #include "chrome/common/pref_names.h" | |
27 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
28 #include "chrome/grit/generated_resources.h" | 30 #include "chrome/grit/generated_resources.h" |
29 #include "components/favicon_base/favicon_types.h" | 31 #include "components/favicon_base/favicon_types.h" |
30 #include "components/history/core/browser/page_usage_data.h" | 32 #include "components/history/core/browser/page_usage_data.h" |
31 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
32 #include "content/public/browser/notification_source.h" | 34 #include "content/public/browser/notification_source.h" |
33 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
34 #include "ui/gfx/codec/png_codec.h" | 36 #include "ui/gfx/codec/png_codec.h" |
35 #include "ui/gfx/favicon_size.h" | 37 #include "ui/gfx/favicon_size.h" |
36 #include "ui/gfx/icon_util.h" | 38 #include "ui/gfx/icon_util.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 if (!IconUtil::CreateIconFileFromImageFamily(image_family, path)) | 77 if (!IconUtil::CreateIconFileFromImageFamily(image_family, path)) |
76 return false; | 78 return false; |
77 | 79 |
78 // Add this icon file to the list and return its absolute path. | 80 // Add this icon file to the list and return its absolute path. |
79 // The IShellLink::SetIcon() function needs the absolute path to an icon. | 81 // The IShellLink::SetIcon() function needs the absolute path to an icon. |
80 *icon_path = path; | 82 *icon_path = path; |
81 return true; | 83 return true; |
82 } | 84 } |
83 | 85 |
84 // Updates the "Tasks" category of the JumpList. | 86 // Updates the "Tasks" category of the JumpList. |
85 bool UpdateTaskCategory(JumpListUpdater* jumplist_updater) { | 87 bool UpdateTaskCategory( |
88 JumpListUpdater* jumplist_updater, | |
89 IncognitoModePrefs::Availability incognito_availability) { | |
86 base::FilePath chrome_path; | 90 base::FilePath chrome_path; |
87 if (!PathService::Get(base::FILE_EXE, &chrome_path)) | 91 if (!PathService::Get(base::FILE_EXE, &chrome_path)) |
88 return false; | 92 return false; |
89 | 93 |
90 ShellLinkItemList items; | 94 ShellLinkItemList items; |
91 | 95 |
92 // Create an IShellLink object which launches Chrome, and add it to the | 96 // Create an IShellLink object which launches Chrome, and add it to the |
93 // collection. We use our application icon as the icon for this item. | 97 // collection. We use our application icon as the icon for this item. |
94 // We remove '&' characters from this string so we can share it with our | 98 // We remove '&' characters from this string so we can share it with our |
95 // system menu. | 99 // system menu. |
96 scoped_refptr<ShellLinkItem> chrome = CreateShellLink(); | 100 if (incognito_availability != IncognitoModePrefs::FORCED) { |
97 base::string16 chrome_title = l10n_util::GetStringUTF16(IDS_NEW_WINDOW); | 101 scoped_refptr<ShellLinkItem> chrome = CreateShellLink(); |
98 ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); | 102 base::string16 chrome_title = l10n_util::GetStringUTF16(IDS_NEW_WINDOW); |
99 chrome->set_title(chrome_title); | 103 ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); |
100 chrome->set_icon(chrome_path.value(), 0); | 104 chrome->set_title(chrome_title); |
101 items.push_back(chrome); | 105 chrome->set_icon(chrome_path.value(), 0); |
106 items.push_back(chrome); | |
107 } | |
102 | 108 |
103 // Create an IShellLink object which launches Chrome in incognito mode, and | 109 // Create an IShellLink object which launches Chrome in incognito mode, and |
104 // add it to the collection. We use our application icon as the icon for | 110 // add it to the collection. We use our application icon as the icon for |
105 // this item. | 111 // this item. |
106 scoped_refptr<ShellLinkItem> incognito = CreateShellLink(); | 112 if (incognito_availability != IncognitoModePrefs::DISABLED) { |
107 incognito->GetCommandLine()->AppendSwitch(switches::kIncognito); | 113 scoped_refptr<ShellLinkItem> incognito = CreateShellLink(); |
108 base::string16 incognito_title = | 114 incognito->GetCommandLine()->AppendSwitch(switches::kIncognito); |
109 l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW); | 115 base::string16 incognito_title = |
110 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); | 116 l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW); |
111 incognito->set_title(incognito_title); | 117 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); |
112 incognito->set_icon(chrome_path.value(), 0); | 118 incognito->set_title(incognito_title); |
113 items.push_back(incognito); | 119 incognito->set_icon(chrome_path.value(), 0); |
120 items.push_back(incognito); | |
121 } | |
114 | 122 |
115 return jumplist_updater->AddTasks(items); | 123 return jumplist_updater->AddTasks(items); |
116 } | 124 } |
117 | 125 |
118 // Updates the application JumpList. | 126 // Updates the application JumpList. |
119 bool UpdateJumpList(const wchar_t* app_id, | 127 bool UpdateJumpList(const wchar_t* app_id, |
120 const ShellLinkItemList& most_visited_pages, | 128 const ShellLinkItemList& most_visited_pages, |
121 const ShellLinkItemList& recently_closed_pages) { | 129 const ShellLinkItemList& recently_closed_pages, |
130 IncognitoModePrefs::Availability incognito_availability) { | |
122 // JumpList is implemented only on Windows 7 or later. | 131 // JumpList is implemented only on Windows 7 or later. |
123 // So, we should return now when this function is called on earlier versions | 132 // So, we should return now when this function is called on earlier versions |
124 // of Windows. | 133 // of Windows. |
125 if (!JumpListUpdater::IsEnabled()) | 134 if (!JumpListUpdater::IsEnabled()) |
126 return true; | 135 return true; |
127 | 136 |
128 JumpListUpdater jumplist_updater(app_id); | 137 JumpListUpdater jumplist_updater(app_id); |
129 if (!jumplist_updater.BeginUpdate()) | 138 if (!jumplist_updater.BeginUpdate()) |
130 return false; | 139 return false; |
131 | 140 |
(...skipping 25 matching lines...) Expand all Loading... | |
157 | 166 |
158 // Update the "Recently Closed" category of the JumpList. | 167 // Update the "Recently Closed" category of the JumpList. |
159 if (!jumplist_updater.AddCustomCategory( | 168 if (!jumplist_updater.AddCustomCategory( |
160 base::UTF16ToWide( | 169 base::UTF16ToWide( |
161 l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED)), | 170 l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED)), |
162 recently_closed_pages, recently_closed_items)) { | 171 recently_closed_pages, recently_closed_items)) { |
163 return false; | 172 return false; |
164 } | 173 } |
165 | 174 |
166 // Update the "Tasks" category of the JumpList. | 175 // Update the "Tasks" category of the JumpList. |
167 if (!UpdateTaskCategory(&jumplist_updater)) | 176 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) |
168 return false; | 177 return false; |
169 | 178 |
170 // Commit this transaction and send the updated JumpList to Windows. | 179 // Commit this transaction and send the updated JumpList to Windows. |
171 if (!jumplist_updater.CommitUpdate()) | 180 if (!jumplist_updater.CommitUpdate()) |
172 return false; | 181 return false; |
173 | 182 |
174 return true; | 183 return true; |
175 } | 184 } |
176 | 185 |
177 } // namespace | 186 } // namespace |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 // Register for notification when TopSites changes so that we can update | 226 // Register for notification when TopSites changes so that we can update |
218 // ourself. | 227 // ourself. |
219 registrar_->Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, | 228 registrar_->Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, |
220 content::Source<history::TopSites>(top_sites)); | 229 content::Source<history::TopSites>(top_sites)); |
221 // Register for notification when profile is destroyed to ensure that all | 230 // Register for notification when profile is destroyed to ensure that all |
222 // observers are detatched at that time. | 231 // observers are detatched at that time. |
223 registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 232 registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
224 content::Source<Profile>(profile_)); | 233 content::Source<Profile>(profile_)); |
225 } | 234 } |
226 tab_restore_service->AddObserver(this); | 235 tab_restore_service->AddObserver(this); |
236 pref_change_registrar_.reset(new PrefChangeRegistrar); | |
237 pref_change_registrar_->Init(profile_->GetPrefs()); | |
238 pref_change_registrar_->Add( | |
239 prefs::kIncognitoModeAvailability, | |
240 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this)); | |
227 return true; | 241 return true; |
228 } | 242 } |
229 | 243 |
230 void JumpList::Observe(int type, | 244 void JumpList::Observe(int type, |
231 const content::NotificationSource& source, | 245 const content::NotificationSource& source, |
232 const content::NotificationDetails& details) { | 246 const content::NotificationDetails& details) { |
233 switch (type) { | 247 switch (type) { |
234 case chrome::NOTIFICATION_TOP_SITES_CHANGED: { | 248 case chrome::NOTIFICATION_TOP_SITES_CHANGED: { |
235 // Most visited urls changed, query again. | 249 // Most visited urls changed, query again. |
236 history::TopSites* top_sites = profile_->GetTopSites(); | 250 history::TopSites* top_sites = profile_->GetTopSites(); |
(...skipping 14 matching lines...) Expand all Loading... | |
251 } | 265 } |
252 } | 266 } |
253 | 267 |
254 void JumpList::RemoveObserver() { | 268 void JumpList::RemoveObserver() { |
255 if (profile_) { | 269 if (profile_) { |
256 TabRestoreService* tab_restore_service = | 270 TabRestoreService* tab_restore_service = |
257 TabRestoreServiceFactory::GetForProfile(profile_); | 271 TabRestoreServiceFactory::GetForProfile(profile_); |
258 if (tab_restore_service) | 272 if (tab_restore_service) |
259 tab_restore_service->RemoveObserver(this); | 273 tab_restore_service->RemoveObserver(this); |
260 registrar_.reset(); | 274 registrar_.reset(); |
275 pref_change_registrar_.reset(); | |
261 } | 276 } |
262 profile_ = NULL; | 277 profile_ = NULL; |
263 } | 278 } |
264 | 279 |
265 void JumpList::CancelPendingUpdate() { | 280 void JumpList::CancelPendingUpdate() { |
266 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { | 281 if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { |
267 cancelable_task_tracker_.TryCancel(task_id_); | 282 cancelable_task_tracker_.TryCancel(task_id_); |
268 task_id_ = base::CancelableTaskTracker::kBadTaskId; | 283 task_id_ = base::CancelableTaskTracker::kBadTaskId; |
269 } | 284 } |
270 } | 285 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 } | 392 } |
378 } | 393 } |
379 | 394 |
380 void JumpList::StartLoadingFavicon() { | 395 void JumpList::StartLoadingFavicon() { |
381 GURL url; | 396 GURL url; |
382 { | 397 { |
383 base::AutoLock auto_lock(list_lock_); | 398 base::AutoLock auto_lock(list_lock_); |
384 if (icon_urls_.empty()) { | 399 if (icon_urls_.empty()) { |
385 // No more favicons are needed by the application JumpList. Schedule a | 400 // No more favicons are needed by the application JumpList. Schedule a |
386 // RunUpdate call. | 401 // RunUpdate call. |
387 BrowserThread::PostTask( | 402 PostRunUpdate(); |
sky
2014/09/08 16:15:17
Is it possible to not callout like this while hold
Joao da Silva
2014/09/08 16:44:10
Done.
| |
388 BrowserThread::FILE, FROM_HERE, | |
389 base::Bind(&JumpList::RunUpdate, this)); | |
390 return; | 403 return; |
391 } | 404 } |
392 // Ask FaviconService if it has a favicon of a URL. | 405 // Ask FaviconService if it has a favicon of a URL. |
393 // When FaviconService has one, it will call OnFaviconDataAvailable(). | 406 // When FaviconService has one, it will call OnFaviconDataAvailable(). |
394 url = GURL(icon_urls_.front().first); | 407 url = GURL(icon_urls_.front().first); |
395 } | 408 } |
396 FaviconService* favicon_service = | 409 FaviconService* favicon_service = |
397 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); | 410 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
398 task_id_ = favicon_service->GetFaviconImageForPageURL( | 411 task_id_ = favicon_service->GetFaviconImageForPageURL( |
399 url, | 412 url, |
(...skipping 16 matching lines...) Expand all Loading... | |
416 icon_urls_.front().second->set_icon_data(image_result.image.AsBitmap()); | 429 icon_urls_.front().second->set_icon_data(image_result.image.AsBitmap()); |
417 } | 430 } |
418 | 431 |
419 if (!icon_urls_.empty()) | 432 if (!icon_urls_.empty()) |
420 icon_urls_.pop_front(); | 433 icon_urls_.pop_front(); |
421 } | 434 } |
422 // Check whether we need to load more favicons. | 435 // Check whether we need to load more favicons. |
423 StartLoadingFavicon(); | 436 StartLoadingFavicon(); |
424 } | 437 } |
425 | 438 |
426 void JumpList::RunUpdate() { | 439 void JumpList::OnIncognitoAvailabilityChanged() { |
440 base::AutoLock auto_lock(list_lock_); | |
sky
2014/09/08 16:15:17
Do you really need to hold the lock here?
Joao da Silva
2014/09/08 16:44:10
The header documents that |icon_urls_| is protecte
| |
441 if (icon_urls_.empty()) | |
442 PostRunUpdate(); | |
443 // If |icon_urls_| isn't empty then OnFaviconDataAvailable will eventually | |
444 // call PostRunUpdate(). | |
445 } | |
446 | |
447 void JumpList::PostRunUpdate() { | |
448 // Check if incognito windows (or normal windows) are disabled by policy. | |
449 IncognitoModePrefs::Availability incognito_availability = | |
450 profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) | |
451 : IncognitoModePrefs::ENABLED; | |
452 | |
453 BrowserThread::PostTask( | |
454 BrowserThread::FILE, FROM_HERE, | |
455 base::Bind(&JumpList::RunUpdate, this, incognito_availability)); | |
456 } | |
457 | |
458 void JumpList::RunUpdate( | |
459 IncognitoModePrefs::Availability incognito_availability) { | |
427 ShellLinkItemList local_most_visited_pages; | 460 ShellLinkItemList local_most_visited_pages; |
428 ShellLinkItemList local_recently_closed_pages; | 461 ShellLinkItemList local_recently_closed_pages; |
429 | 462 |
430 { | 463 { |
431 base::AutoLock auto_lock(list_lock_); | 464 base::AutoLock auto_lock(list_lock_); |
432 // Make sure we are not out of date: if icon_urls_ is not empty, then | 465 // Make sure we are not out of date: if icon_urls_ is not empty, then |
433 // another notification has been received since we processed this one | 466 // another notification has been received since we processed this one |
434 if (!icon_urls_.empty()) | 467 if (!icon_urls_.empty()) |
435 return; | 468 return; |
436 | 469 |
(...skipping 11 matching lines...) Expand all Loading... | |
448 base::Move(icon_dir_, icon_dir_old); | 481 base::Move(icon_dir_, icon_dir_old); |
449 base::CreateDirectory(icon_dir_); | 482 base::CreateDirectory(icon_dir_); |
450 | 483 |
451 // Create temporary icon files for shortcuts in the "Most Visited" category. | 484 // Create temporary icon files for shortcuts in the "Most Visited" category. |
452 CreateIconFiles(local_most_visited_pages); | 485 CreateIconFiles(local_most_visited_pages); |
453 | 486 |
454 // Create temporary icon files for shortcuts in the "Recently Closed" | 487 // Create temporary icon files for shortcuts in the "Recently Closed" |
455 // category. | 488 // category. |
456 CreateIconFiles(local_recently_closed_pages); | 489 CreateIconFiles(local_recently_closed_pages); |
457 | 490 |
458 // We finished collecting all resources needed for updating an appliation | 491 // We finished collecting all resources needed for updating an application |
459 // JumpList. So, create a new JumpList and replace the current JumpList | 492 // JumpList. So, create a new JumpList and replace the current JumpList |
460 // with it. | 493 // with it. |
461 UpdateJumpList(app_id_.c_str(), local_most_visited_pages, | 494 UpdateJumpList(app_id_.c_str(), local_most_visited_pages, |
462 local_recently_closed_pages); | 495 local_recently_closed_pages, incognito_availability); |
463 } | 496 } |
464 | 497 |
465 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { | 498 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { |
466 for (ShellLinkItemList::const_iterator item = item_list.begin(); | 499 for (ShellLinkItemList::const_iterator item = item_list.begin(); |
467 item != item_list.end(); ++item) { | 500 item != item_list.end(); ++item) { |
468 base::FilePath icon_path; | 501 base::FilePath icon_path; |
469 if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) | 502 if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) |
470 (*item)->set_icon(icon_path.value(), 0); | 503 (*item)->set_icon(icon_path.value(), 0); |
471 } | 504 } |
472 } | 505 } |
OLD | NEW |