app_list_service_mac.mm revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1// Copyright 2013 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 "apps/app_shim/app_shim_handler_mac.h" 6#include "base/bind.h" 7#include "base/lazy_instance.h" 8#include "base/memory/scoped_nsobject.h" 9#include "base/memory/singleton.h" 10#include "base/message_loop.h" 11#include "base/observer_list.h" 12#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" 13#include "chrome/browser/ui/app_list/app_list_service.h" 14#include "chrome/browser/ui/app_list/app_list_service_impl.h" 15#include "chrome/browser/ui/app_list/app_list_view_delegate.h" 16#include "chrome/browser/ui/extensions/application_launch.h" 17#include "chrome/common/mac/app_mode_common.h" 18#import "ui/app_list/cocoa/app_list_view_controller.h" 19#import "ui/app_list/cocoa/app_list_window_controller.h" 20 21namespace gfx { 22class ImageSkia; 23} 24 25namespace { 26 27// AppListServiceMac manages global resources needed for the app list to 28// operate, and controls when the app list is opened and closed. 29class AppListServiceMac : public AppListServiceImpl, 30 public apps::AppShimHandler { 31 public: 32 virtual ~AppListServiceMac() {} 33 34 static AppListServiceMac* GetInstance() { 35 return Singleton<AppListServiceMac, 36 LeakySingletonTraits<AppListServiceMac> >::get(); 37 } 38 39 void CreateAppList(Profile* profile); 40 NSWindow* GetNativeWindow(); 41 42 // AppListService overrides: 43 virtual void Init(Profile* initial_profile) OVERRIDE; 44 virtual void ShowAppList(Profile* requested_profile) OVERRIDE; 45 virtual void DismissAppList() OVERRIDE; 46 virtual bool IsAppListVisible() const OVERRIDE; 47 virtual void EnableAppList() OVERRIDE; 48 49 // AppShimHandler overrides: 50 virtual bool OnShimLaunch(apps::AppShimHandler::Host* host) OVERRIDE; 51 virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE; 52 virtual void OnShimFocus(apps::AppShimHandler::Host* host) OVERRIDE; 53 54 private: 55 friend struct DefaultSingletonTraits<AppListServiceMac>; 56 57 AppListServiceMac() {} 58 59 scoped_nsobject<AppListWindowController> window_controller_; 60 61 // App shim hosts observing when the app list is dismissed. In normal user 62 // usage there should only be one. However, it can't be guaranteed, so use 63 // an ObserverList rather than handling corner cases. 64 ObserverList<apps::AppShimHandler::Host> observers_; 65 66 DISALLOW_COPY_AND_ASSIGN(AppListServiceMac); 67}; 68 69class AppListControllerDelegateCocoa : public AppListControllerDelegate { 70 public: 71 AppListControllerDelegateCocoa(); 72 virtual ~AppListControllerDelegateCocoa(); 73 74 private: 75 // AppListControllerDelegate overrides: 76 virtual void DismissView() OVERRIDE; 77 virtual gfx::NativeWindow GetAppListWindow() OVERRIDE; 78 virtual bool CanPin() OVERRIDE; 79 virtual bool CanShowCreateShortcutsDialog() OVERRIDE; 80 virtual void ActivateApp(Profile* profile, 81 const extensions::Extension* extension, 82 int event_flags) OVERRIDE; 83 virtual void LaunchApp(Profile* profile, 84 const extensions::Extension* extension, 85 int event_flags) OVERRIDE; 86 87 DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateCocoa); 88}; 89 90AppListControllerDelegateCocoa::AppListControllerDelegateCocoa() {} 91 92AppListControllerDelegateCocoa::~AppListControllerDelegateCocoa() {} 93 94void AppListControllerDelegateCocoa::DismissView() { 95 AppListServiceMac::GetInstance()->DismissAppList(); 96} 97 98gfx::NativeWindow AppListControllerDelegateCocoa::GetAppListWindow() { 99 return AppListServiceMac::GetInstance()->GetNativeWindow(); 100} 101 102bool AppListControllerDelegateCocoa::CanPin() { 103 return false; 104} 105 106bool AppListControllerDelegateCocoa::CanShowCreateShortcutsDialog() { 107 // TODO(tapted): Return true when create shortcuts menu is tested on mac. 108 return false; 109} 110 111void AppListControllerDelegateCocoa::ActivateApp( 112 Profile* profile, const extensions::Extension* extension, int event_flags) { 113 LaunchApp(profile, extension, event_flags); 114} 115 116void AppListControllerDelegateCocoa::LaunchApp( 117 Profile* profile, const extensions::Extension* extension, int event_flags) { 118 chrome::OpenApplication(chrome::AppLaunchParams( 119 profile, extension, NEW_FOREGROUND_TAB)); 120} 121 122void AppListServiceMac::CreateAppList(Profile* requested_profile) { 123 if (profile() == requested_profile) 124 return; 125 126 // The Objective C objects might be released at some unknown point in the 127 // future, so explicitly clear references to C++ objects. 128 [[window_controller_ appListViewController] 129 setDelegate:scoped_ptr<app_list::AppListViewDelegate>(NULL)]; 130 131 SetProfile(requested_profile); 132 scoped_ptr<app_list::AppListViewDelegate> delegate( 133 new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile())); 134 window_controller_.reset([[AppListWindowController alloc] init]); 135 [[window_controller_ appListViewController] setDelegate:delegate.Pass()]; 136} 137 138void AppListServiceMac::Init(Profile* initial_profile) { 139 static bool init_called = false; 140 if (init_called) 141 return; 142 143 init_called = true; 144 apps::AppShimHandler::RegisterHandler(app_mode::kAppListModeId, 145 AppListServiceMac::GetInstance()); 146} 147 148void AppListServiceMac::ShowAppList(Profile* requested_profile) { 149 InvalidatePendingProfileLoads(); 150 151 if (IsAppListVisible() && (requested_profile == profile())) { 152 DCHECK(window_controller_); 153 [[window_controller_ window] makeKeyAndOrderFront:nil]; 154 [NSApp activateIgnoringOtherApps:YES]; 155 return; 156 } 157 158 SaveProfilePathToLocalState(requested_profile->GetPath()); 159 160 DismissAppList(); 161 CreateAppList(requested_profile); 162 163 DCHECK(window_controller_); 164 [[window_controller_ window] makeKeyAndOrderFront:nil]; 165 [NSApp activateIgnoringOtherApps:YES]; 166} 167 168void AppListServiceMac::DismissAppList() { 169 if (!IsAppListVisible()) 170 return; 171 172 [[window_controller_ window] close]; 173 174 FOR_EACH_OBSERVER(apps::AppShimHandler::Host, 175 observers_, 176 OnAppClosed()); 177} 178 179bool AppListServiceMac::IsAppListVisible() const { 180 return [[window_controller_ window] isVisible]; 181} 182 183void AppListServiceMac::EnableAppList() { 184 // TODO(tapted): Implement enable logic here for OSX. 185} 186 187NSWindow* AppListServiceMac::GetNativeWindow() { 188 return [window_controller_ window]; 189} 190 191bool AppListServiceMac::OnShimLaunch(apps::AppShimHandler::Host* host) { 192 ShowForSavedProfile(); 193 observers_.AddObserver(host); 194 return true; 195} 196 197void AppListServiceMac::OnShimClose(apps::AppShimHandler::Host* host) { 198 observers_.RemoveObserver(host); 199 DismissAppList(); 200} 201 202void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host) { 203 DismissAppList(); 204} 205 206} // namespace 207 208// static 209AppListService* AppListService::Get() { 210 return AppListServiceMac::GetInstance(); 211} 212 213// static 214void AppListService::InitAll(Profile* initial_profile) { 215 Get()->Init(initial_profile); 216} 217