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 <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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |