user_manager_mac.mm revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2014 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/cocoa/profiles/user_manager_mac.h" 6 7#include "base/mac/foundation_util.h" 8#include "chrome/app/chrome_command_ids.h" 9#import "chrome/browser/app_controller_mac.h" 10#include "chrome/browser/browser_process.h" 11#include "chrome/browser/profiles/profile_manager.h" 12#include "chrome/browser/profiles/profiles_state.h" 13#include "chrome/browser/ui/browser_dialogs.h" 14#import "chrome/browser/ui/cocoa/browser_window_utils.h" 15#include "chrome/browser/ui/cocoa/chrome_event_processing_window.h" 16#include "chrome/browser/ui/user_manager.h" 17#include "chrome/grit/chromium_strings.h" 18#include "content/public/browser/native_web_keyboard_event.h" 19#include "content/public/browser/web_contents.h" 20#include "content/public/browser/web_contents_delegate.h" 21#include "ui/base/l10n/l10n_util_mac.h" 22#include "ui/events/keycodes/keyboard_codes.h" 23 24 25// An open User Manager window. There can only be one open at a time. This 26// is reset to NULL when the window is closed. 27UserManagerMac* instance_ = NULL; // Weak. 28 29// Custom WebContentsDelegate that allows handling of hotkeys. 30class UserManagerWebContentsDelegate : public content::WebContentsDelegate { 31 public: 32 UserManagerWebContentsDelegate() {} 33 34 // WebContentsDelegate implementation. Forwards all unhandled keyboard events 35 // to the current window. 36 virtual void HandleKeyboardEvent( 37 content::WebContents* source, 38 const content::NativeWebKeyboardEvent& event) OVERRIDE { 39 if (![BrowserWindowUtils shouldHandleKeyboardEvent:event]) 40 return; 41 42 // -getCommandId returns -1 if the event isn't a chrome accelerator. 43 int chromeCommandId = [BrowserWindowUtils getCommandId:event]; 44 45 // Check for Cmd+A and Cmd+V events that could come from a password field. 46 bool isTextEditingCommand = 47 (event.modifiers & blink::WebInputEvent::MetaKey) && 48 (event.windowsKeyCode == ui::VKEY_A || 49 event.windowsKeyCode == ui::VKEY_V); 50 51 // Only handle close window Chrome accelerators and text editing ones. 52 if (chromeCommandId == IDC_CLOSE_WINDOW || chromeCommandId == IDC_EXIT || 53 isTextEditingCommand) { 54 [[NSApp mainMenu] performKeyEquivalent:event.os_event]; 55 } 56 } 57}; 58 59// Window controller for the User Manager view. 60@interface UserManagerWindowController : NSWindowController <NSWindowDelegate> { 61 @private 62 scoped_ptr<content::WebContents> webContents_; 63 scoped_ptr<UserManagerWebContentsDelegate> webContentsDelegate_; 64 UserManagerMac* userManagerObserver_; // Weak. 65} 66- (void)windowWillClose:(NSNotification*)notification; 67- (void)dealloc; 68- (id)initWithProfile:(Profile*)profile 69 withObserver:(UserManagerMac*)userManagerObserver; 70- (void)showURL:(const GURL&)url; 71- (void)show; 72- (void)close; 73- (BOOL)isVisible; 74@end 75 76@implementation UserManagerWindowController 77 78- (id)initWithProfile:(Profile*)profile 79 withObserver:(UserManagerMac*)userManagerObserver { 80 81 // Center the window on the screen that currently has focus. 82 NSScreen* mainScreen = [NSScreen mainScreen]; 83 CGFloat screenHeight = [mainScreen frame].size.height; 84 CGFloat screenWidth = [mainScreen frame].size.width; 85 86 NSRect contentRect = 87 NSMakeRect((screenWidth - UserManager::kWindowWidth) / 2, 88 (screenHeight - UserManager::kWindowHeight) / 2, 89 UserManager::kWindowWidth, UserManager::kWindowHeight); 90 ChromeEventProcessingWindow* window = [[ChromeEventProcessingWindow alloc] 91 initWithContentRect:contentRect 92 styleMask:NSTitledWindowMask | 93 NSClosableWindowMask | 94 NSResizableWindowMask 95 backing:NSBackingStoreBuffered 96 defer:NO 97 screen:mainScreen]; 98 [window setTitle:l10n_util::GetNSString(IDS_PRODUCT_NAME)]; 99 [window setMinSize:NSMakeSize(UserManager::kWindowWidth, 100 UserManager::kWindowHeight)]; 101 102 if ((self = [super initWithWindow:window])) { 103 userManagerObserver_ = userManagerObserver; 104 105 // Initialize the web view. 106 webContents_.reset(content::WebContents::Create( 107 content::WebContents::CreateParams(profile))); 108 window.contentView = webContents_->GetNativeView(); 109 webContentsDelegate_.reset(new UserManagerWebContentsDelegate()); 110 webContents_->SetDelegate(webContentsDelegate_.get()); 111 DCHECK(window.contentView); 112 113 [[NSNotificationCenter defaultCenter] 114 addObserver:self 115 selector:@selector(windowWillClose:) 116 name:NSWindowWillCloseNotification 117 object:self.window]; 118 } 119 return self; 120} 121 122- (void)dealloc { 123 [[NSNotificationCenter defaultCenter] removeObserver:self]; 124 [super dealloc]; 125} 126 127- (void)showURL:(const GURL&)url { 128 webContents_->GetController().LoadURL(url, content::Referrer(), 129 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, 130 std::string()); 131 [self show]; 132} 133 134- (void)show { 135 // Because the User Manager isn't a BrowserWindowController, activating it 136 // will not trigger a -windowChangedToProfile and update the menu bar. 137 // This is only important if the active profile is Guest, which may have 138 // happened after locking a profile. 139 Profile* guestProfile = profiles::SetActiveProfileToGuestIfLocked(); 140 if (guestProfile && guestProfile->IsGuestSession()) { 141 AppController* controller = 142 base::mac::ObjCCast<AppController>([NSApp delegate]); 143 [controller windowChangedToProfile:guestProfile]; 144 } 145 [[self window] makeKeyAndOrderFront:self]; 146} 147 148- (void)close { 149 [[self window] close]; 150} 151 152-(BOOL)isVisible { 153 return [[self window] isVisible]; 154} 155 156- (void)windowWillClose:(NSNotification*)notification { 157 [[NSNotificationCenter defaultCenter] removeObserver:self]; 158 DCHECK(userManagerObserver_); 159 userManagerObserver_->WindowWasClosed(); 160} 161 162@end 163 164 165void UserManager::Show( 166 const base::FilePath& profile_path_to_focus, 167 profiles::UserManagerTutorialMode tutorial_mode, 168 profiles::UserManagerProfileSelected profile_open_action) { 169 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::OPEN_USER_MANAGER); 170 if (instance_) { 171 // If there's a user manager window open already, just activate it. 172 [instance_->window_controller() show]; 173 return; 174 } 175 176 // Create the guest profile, if necessary, and open the User Manager 177 // from the guest profile. 178 profiles::CreateGuestProfileForUserManager( 179 profile_path_to_focus, 180 tutorial_mode, 181 profile_open_action, 182 base::Bind(&UserManagerMac::OnGuestProfileCreated)); 183} 184 185void UserManager::Hide() { 186 if (instance_) 187 [instance_->window_controller() close]; 188} 189 190bool UserManager::IsShowing() { 191 return instance_ ? [instance_->window_controller() isVisible]: false; 192} 193 194UserManagerMac::UserManagerMac(Profile* profile) { 195 window_controller_.reset([[UserManagerWindowController alloc] 196 initWithProfile:profile withObserver:this]); 197} 198 199UserManagerMac::~UserManagerMac() { 200} 201 202// static 203void UserManagerMac::OnGuestProfileCreated(Profile* guest_profile, 204 const std::string& url) { 205 DCHECK(!instance_); 206 instance_ = new UserManagerMac(guest_profile); 207 [instance_->window_controller() showURL:GURL(url)]; 208} 209 210void UserManagerMac::WindowWasClosed() { 211 instance_ = NULL; 212 delete this; 213} 214