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

Side by Side Diff: chrome/browser/ui/views/app_list/app_list_controller_win.cc

Issue 11367002: Add a flag to control whether there is a shortcut for the app list / launcher in the Windows taskba… (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Feedback Created 8 years, 1 month 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 (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 <sstream> 5 #include <sstream>
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/file_util.h"
8 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
9 #include "base/path_service.h" 10 #include "base/path_service.h"
10 #include "base/time.h" 11 #include "base/time.h"
11 #include "base/timer.h" 12 #include "base/timer.h"
12 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "base/win/shortcut.h"
13 #include "chrome/app/chrome_dll_resource.h" 15 #include "chrome/app/chrome_dll_resource.h"
14 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/lifetime/application_lifetime.h" 18 #include "chrome/browser/lifetime/application_lifetime.h"
17 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_manager.h" 20 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/shell_integration.h" 21 #include "chrome/browser/shell_integration.h"
20 #include "chrome/browser/ui/app_list/app_list_controller.h" 22 #include "chrome/browser/ui/app_list/app_list_controller.h"
21 #include "chrome/browser/ui/app_list/app_list_view_delegate.h" 23 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
22 #include "chrome/browser/ui/extensions/application_launch.h" 24 #include "chrome/browser/ui/extensions/application_launch.h"
23 #include "chrome/browser/ui/views/browser_dialogs.h" 25 #include "chrome/browser/ui/views/browser_dialogs.h"
24 #include "chrome/common/chrome_constants.h" 26 #include "chrome/common/chrome_constants.h"
25 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "grit/chromium_strings.h"
26 #include "grit/generated_resources.h" 30 #include "grit/generated_resources.h"
31 #include "grit/google_chrome_strings.h"
27 #include "ui/app_list/app_list_view.h" 32 #include "ui/app_list/app_list_view.h"
28 #include "ui/app_list/pagination_model.h" 33 #include "ui/app_list/pagination_model.h"
29 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/win/shell.h" 35 #include "ui/base/win/shell.h"
31 #include "ui/gfx/display.h" 36 #include "ui/gfx/display.h"
32 #include "ui/gfx/screen.h" 37 #include "ui/gfx/screen.h"
33 #include "ui/views/bubble/bubble_border.h" 38 #include "ui/views/bubble/bubble_border.h"
34 #include "ui/views/widget/widget.h" 39 #include "ui/views/widget/widget.h"
35 40
36 namespace { 41 namespace {
37 42
38 // Offset from the cursor to the point of the bubble arrow. It looks weird 43 // Offset from the cursor to the point of the bubble arrow. It looks weird
39 // if the arrow comes up right on top of the cursor, so it is offset by this 44 // if the arrow comes up right on top of the cursor, so it is offset by this
40 // amount. 45 // amount.
41 static const int kAnchorOffset = 25; 46 static const int kAnchorOffset = 25;
42 47
48 CommandLine GetAppListCommandLine() {
49 CommandLine* current = CommandLine::ForCurrentProcess();
50 CommandLine command_line(current->GetProgram());
51
52 if (current->HasSwitch(switches::kUserDataDir)) {
grt (UTC plus 2) 2012/11/01 23:18:57 use command_line.CopySwitchesFrom(*current, ...) i
benwells 2012/11/02 01:33:55 Done.
53 FilePath user_data_dir = current->GetSwitchValuePath(
54 switches::kUserDataDir);
55 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
56 }
57
58 command_line.AppendSwitch(switches::kShowAppList);
59 return command_line;
60 }
61
62 string16 GetAppModelId() {
63 // The AppModelId should be the same for all profiles in a user data directory
64 // but different for different user data directories, so base it on the
65 // initial profile in the current user data directory.
66 FilePath initial_profile_path;
67 CommandLine* command_line = CommandLine::ForCurrentProcess();
68 if (command_line->HasSwitch(switches::kUserDataDir)) {
69 initial_profile_path =
70 command_line->GetSwitchValuePath(switches::kUserDataDir).AppendASCII(
71 chrome::kInitialProfile);
72 }
73 return ShellIntegration::GetAppListAppModelIdForProfile(initial_profile_path);
74 }
75
43 class AppListControllerDelegateWin : public AppListControllerDelegate { 76 class AppListControllerDelegateWin : public AppListControllerDelegate {
44 public: 77 public:
45 AppListControllerDelegateWin(); 78 AppListControllerDelegateWin();
46 virtual ~AppListControllerDelegateWin(); 79 virtual ~AppListControllerDelegateWin();
47 80
48 private: 81 private:
49 // AppListController overrides: 82 // AppListController overrides:
50 virtual void CloseView() OVERRIDE; 83 virtual void CloseView() OVERRIDE;
51 virtual void ViewClosing() OVERRIDE; 84 virtual void ViewClosing() OVERRIDE;
52 virtual void ViewActivationChanged(bool active) OVERRIDE; 85 virtual void ViewActivationChanged(bool active) OVERRIDE;
(...skipping 26 matching lines...) Expand all
79 112
80 private: 113 private:
81 // Utility methods for showing the app list. 114 // Utility methods for showing the app list.
82 void GetArrowLocationAndUpdateAnchor( 115 void GetArrowLocationAndUpdateAnchor(
83 const gfx::Rect& work_area, 116 const gfx::Rect& work_area,
84 int min_space_x, 117 int min_space_x,
85 int min_space_y, 118 int min_space_y,
86 views::BubbleBorder::ArrowLocation* arrow, 119 views::BubbleBorder::ArrowLocation* arrow,
87 gfx::Point* anchor); 120 gfx::Point* anchor);
88 void UpdateArrowPositionAndAnchorPoint(app_list::AppListView* view); 121 void UpdateArrowPositionAndAnchorPoint(app_list::AppListView* view);
89 CommandLine GetAppListCommandLine();
90 string16 GetAppListIconPath(); 122 string16 GetAppListIconPath();
91 string16 GetAppModelId();
92 123
93 // Check if the app list or the taskbar has focus. The app list is kept 124 // Check if the app list or the taskbar has focus. The app list is kept
94 // visible whenever either of these have focus, which allows it to be 125 // visible whenever either of these have focus, which allows it to be
95 // pinned but will hide it if it otherwise loses focus. This is checked 126 // pinned but will hide it if it otherwise loses focus. This is checked
96 // periodically whenever the app list does not have focus. 127 // periodically whenever the app list does not have focus.
97 void CheckTaskbarOrViewHasFocus(); 128 void CheckTaskbarOrViewHasFocus();
98 129
99 // Weak pointer. The view manages its own lifetime. 130 // Weak pointer. The view manages its own lifetime.
100 app_list::AppListView* current_view_; 131 app_list::AppListView* current_view_;
101 132
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 anchor->Offset(kAnchorOffset, 0); 288 anchor->Offset(kAnchorOffset, 0);
258 return; 289 return;
259 } 290 }
260 291
261 *arrow = views::BubbleBorder::RIGHT_TOP; 292 *arrow = views::BubbleBorder::RIGHT_TOP;
262 anchor->Offset(-kAnchorOffset, 0); 293 anchor->Offset(-kAnchorOffset, 0);
263 } 294 }
264 295
265 void AppListController::UpdateArrowPositionAndAnchorPoint( 296 void AppListController::UpdateArrowPositionAndAnchorPoint(
266 app_list::AppListView* view) { 297 app_list::AppListView* view) {
267 static const int kArrowSize = 10; 298 const int kArrowSize = 10;
grt (UTC plus 2) 2012/11/01 23:18:57 just curious: why these changes?
benwells 2012/11/02 01:33:55 I was asked in another change just to use const, n
grt (UTC plus 2) 2012/11/02 04:00:36 i think they're equivalent (the compiler should kn
268 static const int kPadding = 20; 299 const int kPadding = 20;
269 300
270 gfx::Size preferred = view->GetPreferredSize(); 301 gfx::Size preferred = view->GetPreferredSize();
271 // Add the size of the arrow to the space needed, as the preferred size is 302 // Add the size of the arrow to the space needed, as the preferred size is
272 // of the view excluding the arrow. 303 // of the view excluding the arrow.
273 int min_space_x = preferred.width() + kAnchorOffset + kPadding + kArrowSize; 304 int min_space_x = preferred.width() + kAnchorOffset + kPadding + kArrowSize;
274 int min_space_y = preferred.height() + kAnchorOffset + kPadding + kArrowSize; 305 int min_space_y = preferred.height() + kAnchorOffset + kPadding + kArrowSize;
275 306
276 gfx::Point anchor = view->anchor_point(); 307 gfx::Point anchor = view->anchor_point();
277 gfx::Display display = gfx::Screen::GetScreenFor( 308 gfx::Display display = gfx::Screen::GetScreenFor(
278 view->GetWidget()->GetNativeView())->GetDisplayNearestPoint(anchor); 309 view->GetWidget()->GetNativeView())->GetDisplayNearestPoint(anchor);
279 const gfx::Rect& display_rect = display.work_area(); 310 const gfx::Rect& display_rect = display.work_area();
280 views::BubbleBorder::ArrowLocation arrow; 311 views::BubbleBorder::ArrowLocation arrow;
281 GetArrowLocationAndUpdateAnchor(display.work_area(), 312 GetArrowLocationAndUpdateAnchor(display.work_area(),
282 min_space_x, 313 min_space_x,
283 min_space_y, 314 min_space_y,
284 &arrow, 315 &arrow,
285 &anchor); 316 &anchor);
286 view->SetBubbleArrowLocation(arrow); 317 view->SetBubbleArrowLocation(arrow);
287 view->SetAnchorPoint(anchor); 318 view->SetAnchorPoint(anchor);
288 } 319 }
289 320
290 CommandLine AppListController::GetAppListCommandLine() {
291 CommandLine* current = CommandLine::ForCurrentProcess();
292 CommandLine command_line(current->GetProgram());
293
294 if (current->HasSwitch(switches::kUserDataDir)) {
295 FilePath user_data_dir = current->GetSwitchValuePath(
296 switches::kUserDataDir);
297 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
298 }
299
300 command_line.AppendSwitch(switches::kShowAppList);
301 return command_line;
302 }
303
304 string16 AppListController::GetAppListIconPath() { 321 string16 AppListController::GetAppListIconPath() {
305 FilePath icon_path; 322 FilePath icon_path;
306 if (!PathService::Get(base::DIR_MODULE, &icon_path)) 323 if (!PathService::Get(base::DIR_MODULE, &icon_path))
307 return string16(); 324 return string16();
308 325
309 icon_path = icon_path.Append(chrome::kBrowserResourcesDll); 326 icon_path = icon_path.Append(chrome::kBrowserResourcesDll);
310 std::stringstream ss; 327 std::stringstream ss;
311 ss << ",-" << IDI_APP_LIST; 328 ss << ",-" << IDI_APP_LIST;
312 string16 result = icon_path.value(); 329 string16 result = icon_path.value();
313 result.append(UTF8ToUTF16(ss.str())); 330 result.append(UTF8ToUTF16(ss.str()));
314 return result; 331 return result;
315 } 332 }
316 333
317 string16 AppListController::GetAppModelId() {
318 static const wchar_t kAppListId[] = L"ChromeAppList";
319 // The AppModelId should be the same for all profiles in a user data directory
320 // but different for different user data directories, so base it on the
321 // initial profile in the current user data directory.
322 FilePath initial_profile_path =
323 g_browser_process->profile_manager()->GetInitialProfileDir();
324 return ShellIntegration::GetAppModelIdForProfile(kAppListId,
325 initial_profile_path);
326 }
327
328 void AppListController::CheckTaskbarOrViewHasFocus() { 334 void AppListController::CheckTaskbarOrViewHasFocus() {
329 #if !defined(USE_AURA) 335 #if !defined(USE_AURA)
330 // Don't bother checking if the view has been closed. 336 // Don't bother checking if the view has been closed.
331 if (!current_view_) 337 if (!current_view_)
332 return; 338 return;
333 339
334 // First get the taskbar and jump lists windows (the jump list is the 340 // First get the taskbar and jump lists windows (the jump list is the
335 // context menu which the taskbar uses). 341 // context menu which the taskbar uses).
336 HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL); 342 HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL);
337 HWND taskbar_hwnd = FindWindow(L"Shell_TrayWnd", NULL); 343 HWND taskbar_hwnd = FindWindow(L"Shell_TrayWnd", NULL);
(...skipping 12 matching lines...) Expand all
350 } 356 }
351 focused_hwnd = GetParent(focused_hwnd); 357 focused_hwnd = GetParent(focused_hwnd);
352 } 358 }
353 359
354 // If we get here, the focused window is not the taskbar, it's context menu, 360 // If we get here, the focused window is not the taskbar, it's context menu,
355 // or the app list, so close the app list. 361 // or the app list, so close the app list.
356 CloseAppList(); 362 CloseAppList();
357 #endif 363 #endif
358 } 364 }
359 365
366 // Check that a taskbar shortcut exists if it should, or does not exist if
367 // it should not. A taskbar shortcut should exist if the switch
368 // kShowAppListShortcut is set. The shortcut will be created or deleted in
369 // |user_data_dir| and will use a Windows Application Model Id of
370 // |app_model_id|.
371 void DoCheckAppListTaskbarShortcut(const FilePath user_data_dir,
grt (UTC plus 2) 2012/11/01 23:18:57 nit: i think there's a pseudo-convention of naming
benwells 2012/11/02 01:33:55 Done.
372 const string16& app_model_id) {
373 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
374
375 const string16 shortcut_name = l10n_util::GetStringUTF16(
376 IDS_APP_LIST_SHORTCUT_NAME);
377 const FilePath shortcut_path(user_data_dir.Append(shortcut_name).
378 AddExtension(L"lnk"));
379 const bool should_show = CommandLine::ForCurrentProcess()->HasSwitch(
380 switches::kShowAppListShortcut);
381
382 // This will not reshow a shortcut if it has been unpinned manually by the
383 // user, as that will not delete the shortcut file.
384 if (should_show && !file_util::PathExists(shortcut_path)) {
385 FilePath chrome_exe;
386 if (!PathService::Get(base::FILE_EXE, &chrome_exe))
387 return;
388
389 base::win::ShortcutProperties shortcut_properties;
390 shortcut_properties.set_target(chrome_exe);
391 shortcut_properties.set_working_dir(chrome_exe.DirName());
392
393 string16 wide_switches(GetAppListCommandLine().GetArgumentsString());
394 shortcut_properties.set_arguments(wide_switches);
395 shortcut_properties.set_description(shortcut_name);
396
397 FilePath icon_path;
398 if (!PathService::Get(base::DIR_MODULE, &icon_path))
grt (UTC plus 2) 2012/11/02 03:09:52 this is unsafe, see comment below.
399 return;
400
401 icon_path = icon_path.Append(chrome::kBrowserResourcesDll);
402
403 // Icons are added to the resources of the DLL using icon indexes. The
404 // icon index for the app list icon is in IDI_APP_LIST. Creating shortcuts
405 // needs to specify a resource index, which are different to icon indexes.
406 // They are 0 based and contiguous. As Google Chrome builds have an extra
407 // icon (SXS) the icon for Google Chrome builds need to be one higher.
408 #if defined(GOOGLE_CHROME_BUILD)
409 const int kIconIndex = 26;
grt (UTC plus 2) 2012/11/01 23:18:57 is there a constant in a generated .h file that ca
benwells 2012/11/02 01:33:55 Not that I could find. See chrome/installer/util/g
grt (UTC plus 2) 2012/11/02 03:09:52 Since the path to chrome.dll changes on each updat
410 #else
411 const int kIconIndex = 25;
412 #endif
413 shortcut_properties.set_icon(icon_path, kIconIndex);
414 shortcut_properties.set_app_id(app_model_id);
415 shortcut_properties.set_dual_mode(false);
416
417 base::win::CreateOrUpdateShortcutLink(shortcut_path, shortcut_properties,
418 base::win::SHORTCUT_CREATE_ALWAYS);
419 base::win::TaskbarPinShortcutLink(shortcut_path.value().c_str());
420 return;
421 }
422
423 if (!should_show && file_util::PathExists(shortcut_path)) {
424 base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str());
425 file_util::Delete(shortcut_path, false);
426 }
427 }
428
360 } // namespace 429 } // namespace
361 430
362 namespace app_list_controller { 431 namespace app_list_controller {
363 432
364 void ShowAppList() { 433 void ShowAppList() {
365 g_app_list_controller.Get().ShowAppList(); 434 g_app_list_controller.Get().ShowAppList();
366 } 435 }
367 436
437 void CheckAppListTaskbarShortcut() {
438 FilePath user_data_dir(g_browser_process->profile_manager()->user_data_dir());
439 string16 app_model_id = GetAppModelId();
440 content::BrowserThread::PostTask(
grt (UTC plus 2) 2012/11/01 23:18:57 i think the blocking pool is appropriate here (see
benwells 2012/11/02 01:33:55 Is that safe? chrome/browser/shell_integration_win
grt (UTC plus 2) 2012/11/02 03:09:52 I could be mistaken, but at a high level this oper
grt (UTC plus 2) 2012/11/02 04:00:36 After chatting, I now understand your concern. I
441 content::BrowserThread::FILE,
442 FROM_HERE,
grt (UTC plus 2) 2012/11/01 23:18:57 nit: move to previous line
benwells 2012/11/02 01:33:55 Done.
443 base::Bind(&DoCheckAppListTaskbarShortcut, user_data_dir, app_model_id));
444 }
445
368 } // namespace app_list_controller 446 } // namespace app_list_controller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698