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.
5 #include "chrome/browser/ui/cocoa/profiles/user_manager_mac.h"
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"
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.
27 UserManagerMac* instance_ = NULL; // Weak.
29 // Custom WebContentsDelegate that allows handling of hotkeys.
30 class UserManagerWebContentsDelegate : public content::WebContentsDelegate {
32 UserManagerWebContentsDelegate() {}
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])
42 // -getCommandId returns -1 if the event isn't a chrome accelerator.
43 int chromeCommandId = [BrowserWindowUtils getCommandId:event];
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);
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];
59 // Window controller for the User Manager view.
60 @interface UserManagerWindowController : NSWindowController <NSWindowDelegate> {
62 scoped_ptr<content::WebContents> webContents_;
63 scoped_ptr<UserManagerWebContentsDelegate> webContentsDelegate_;
64 UserManagerMac* userManagerObserver_; // Weak.
66 - (void)windowWillClose:(NSNotification*)notification;
68 - (id)initWithProfile:(Profile*)profile
69 withObserver:(UserManagerMac*)userManagerObserver;
70 - (void)showURL:(const GURL&)url;
76 @implementation UserManagerWindowController
78 - (id)initWithProfile:(Profile*)profile
79 withObserver:(UserManagerMac*)userManagerObserver {
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;
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 |
95 backing:NSBackingStoreBuffered
98 [window setTitle:l10n_util::GetNSString(IDS_PRODUCT_NAME)];
99 [window setMinSize:NSMakeSize(UserManager::kWindowWidth,
100 UserManager::kWindowHeight)];
102 if ((self = [super initWithWindow:window])) {
103 userManagerObserver_ = userManagerObserver;
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);
113 [[NSNotificationCenter defaultCenter]
115 selector:@selector(windowWillClose:)
116 name:NSWindowWillCloseNotification
123 [[NSNotificationCenter defaultCenter] removeObserver:self];
127 - (void)showURL:(const GURL&)url {
128 webContents_->GetController().LoadURL(url, content::Referrer(),
129 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
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];
145 [[self window] makeKeyAndOrderFront:self];
149 [[self window] close];
153 return [[self window] isVisible];
156 - (void)windowWillClose:(NSNotification*)notification {
157 [[NSNotificationCenter defaultCenter] removeObserver:self];
158 DCHECK(userManagerObserver_);
159 userManagerObserver_->WindowWasClosed();
165 void 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);
171 // If there's a user manager window open already, just activate it.
172 [instance_->window_controller() show];
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,
182 base::Bind(&UserManagerMac::OnGuestProfileCreated));
185 void UserManager::Hide() {
187 [instance_->window_controller() close];
190 bool UserManager::IsShowing() {
191 return instance_ ? [instance_->window_controller() isVisible]: false;
194 UserManagerMac::UserManagerMac(Profile* profile) {
195 window_controller_.reset([[UserManagerWindowController alloc]
196 initWithProfile:profile withObserver:this]);
199 UserManagerMac::~UserManagerMac() {
203 void UserManagerMac::OnGuestProfileCreated(Profile* guest_profile,
204 const std::string& url) {
206 instance_ = new UserManagerMac(guest_profile);
207 [instance_->window_controller() showURL:GURL(url)];
210 void UserManagerMac::WindowWasClosed() {