| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/cocoa/profiles/user_manager_mac.h" |
| |
| #include "base/mac/foundation_util.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #import "chrome/browser/app_controller_mac.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/profiles/profiles_state.h" |
| #include "chrome/browser/ui/browser_dialogs.h" |
| #import "chrome/browser/ui/cocoa/browser_window_utils.h" |
| #include "chrome/browser/ui/cocoa/chrome_event_processing_window.h" |
| #include "chrome/browser/ui/user_manager.h" |
| #include "chrome/grit/chromium_strings.h" |
| #include "content/public/browser/native_web_keyboard_event.h" |
| #include "content/public/browser/render_widget_host_view.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "ui/base/l10n/l10n_util_mac.h" |
| #include "ui/events/keycodes/keyboard_codes.h" |
| |
| |
| // An open User Manager window. There can only be one open at a time. This |
| // is reset to NULL when the window is closed. |
| UserManagerMac* instance_ = NULL; // Weak. |
| |
| // Custom WebContentsDelegate that allows handling of hotkeys. |
| class UserManagerWebContentsDelegate : public content::WebContentsDelegate { |
| public: |
| UserManagerWebContentsDelegate() {} |
| |
| // WebContentsDelegate implementation. Forwards all unhandled keyboard events |
| // to the current window. |
| void HandleKeyboardEvent( |
| content::WebContents* source, |
| const content::NativeWebKeyboardEvent& event) override { |
| if (![BrowserWindowUtils shouldHandleKeyboardEvent:event]) |
| return; |
| |
| // -getCommandId returns -1 if the event isn't a chrome accelerator. |
| int chromeCommandId = [BrowserWindowUtils getCommandId:event]; |
| |
| // Check for Cmd+A and Cmd+V events that could come from a password field. |
| bool isTextEditingCommand = |
| (event.modifiers & blink::WebInputEvent::MetaKey) && |
| (event.windowsKeyCode == ui::VKEY_A || |
| event.windowsKeyCode == ui::VKEY_V); |
| |
| // Only handle close window Chrome accelerators and text editing ones. |
| if (chromeCommandId == IDC_CLOSE_WINDOW || chromeCommandId == IDC_EXIT || |
| isTextEditingCommand) { |
| [[NSApp mainMenu] performKeyEquivalent:event.os_event]; |
| } |
| } |
| }; |
| |
| // Window controller for the User Manager view. |
| @interface UserManagerWindowController : NSWindowController <NSWindowDelegate> { |
| @private |
| scoped_ptr<content::WebContents> webContents_; |
| scoped_ptr<UserManagerWebContentsDelegate> webContentsDelegate_; |
| UserManagerMac* userManagerObserver_; // Weak. |
| } |
| - (void)windowWillClose:(NSNotification*)notification; |
| - (void)dealloc; |
| - (id)initWithProfile:(Profile*)profile |
| withObserver:(UserManagerMac*)userManagerObserver; |
| - (void)showURL:(const GURL&)url; |
| - (void)show; |
| - (void)close; |
| - (BOOL)isVisible; |
| @end |
| |
| @implementation UserManagerWindowController |
| |
| - (id)initWithProfile:(Profile*)profile |
| withObserver:(UserManagerMac*)userManagerObserver { |
| |
| // Center the window on the screen that currently has focus. |
| NSScreen* mainScreen = [NSScreen mainScreen]; |
| CGFloat screenHeight = [mainScreen frame].size.height; |
| CGFloat screenWidth = [mainScreen frame].size.width; |
| |
| NSRect contentRect = |
| NSMakeRect((screenWidth - UserManager::kWindowWidth) / 2, |
| (screenHeight - UserManager::kWindowHeight) / 2, |
| UserManager::kWindowWidth, UserManager::kWindowHeight); |
| ChromeEventProcessingWindow* window = [[ChromeEventProcessingWindow alloc] |
| initWithContentRect:contentRect |
| styleMask:NSTitledWindowMask | |
| NSClosableWindowMask | |
| NSResizableWindowMask |
| backing:NSBackingStoreBuffered |
| defer:NO |
| screen:mainScreen]; |
| [window setTitle:l10n_util::GetNSString(IDS_PRODUCT_NAME)]; |
| [window setMinSize:NSMakeSize(UserManager::kWindowWidth, |
| UserManager::kWindowHeight)]; |
| |
| if ((self = [super initWithWindow:window])) { |
| userManagerObserver_ = userManagerObserver; |
| |
| // Initialize the web view. |
| webContents_.reset(content::WebContents::Create( |
| content::WebContents::CreateParams(profile))); |
| window.contentView = webContents_->GetNativeView(); |
| webContentsDelegate_.reset(new UserManagerWebContentsDelegate()); |
| webContents_->SetDelegate(webContentsDelegate_.get()); |
| DCHECK(window.contentView); |
| |
| [[NSNotificationCenter defaultCenter] |
| addObserver:self |
| selector:@selector(windowWillClose:) |
| name:NSWindowWillCloseNotification |
| object:self.window]; |
| } |
| return self; |
| } |
| |
| - (void)dealloc { |
| [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| [super dealloc]; |
| } |
| |
| - (void)showURL:(const GURL&)url { |
| webContents_->GetController().LoadURL(url, content::Referrer(), |
| ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| std::string()); |
| content::RenderWidgetHostView* rwhv = webContents_->GetRenderWidgetHostView(); |
| if (rwhv) |
| rwhv->SetBackgroundColor(profiles::kUserManagerBackgroundColor); |
| [self show]; |
| } |
| |
| - (void)show { |
| // Because the User Manager isn't a BrowserWindowController, activating it |
| // will not trigger a -windowChangedToProfile and update the menu bar. |
| // This is only important if the active profile is Guest, which may have |
| // happened after locking a profile. |
| Profile* guestProfile = profiles::SetActiveProfileToGuestIfLocked(); |
| if (guestProfile && guestProfile->IsGuestSession()) { |
| AppController* controller = |
| base::mac::ObjCCast<AppController>([NSApp delegate]); |
| [controller windowChangedToProfile:guestProfile]; |
| } |
| [[self window] makeKeyAndOrderFront:self]; |
| } |
| |
| - (void)close { |
| [[self window] close]; |
| } |
| |
| -(BOOL)isVisible { |
| return [[self window] isVisible]; |
| } |
| |
| - (void)windowWillClose:(NSNotification*)notification { |
| [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| DCHECK(userManagerObserver_); |
| userManagerObserver_->WindowWasClosed(); |
| } |
| |
| @end |
| |
| |
| void UserManager::Show( |
| const base::FilePath& profile_path_to_focus, |
| profiles::UserManagerTutorialMode tutorial_mode, |
| profiles::UserManagerProfileSelected profile_open_action) { |
| DCHECK(profile_path_to_focus != ProfileManager::GetGuestProfilePath()); |
| |
| ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::OPEN_USER_MANAGER); |
| if (instance_) { |
| // If there's a user manager window open already, just activate it. |
| [instance_->window_controller() show]; |
| return; |
| } |
| |
| // Create the guest profile, if necessary, and open the User Manager |
| // from the guest profile. |
| profiles::CreateGuestProfileForUserManager( |
| profile_path_to_focus, |
| tutorial_mode, |
| profile_open_action, |
| base::Bind(&UserManagerMac::OnGuestProfileCreated)); |
| } |
| |
| void UserManager::Hide() { |
| if (instance_) |
| [instance_->window_controller() close]; |
| } |
| |
| bool UserManager::IsShowing() { |
| return instance_ ? [instance_->window_controller() isVisible]: false; |
| } |
| |
| UserManagerMac::UserManagerMac(Profile* profile) { |
| window_controller_.reset([[UserManagerWindowController alloc] |
| initWithProfile:profile withObserver:this]); |
| } |
| |
| UserManagerMac::~UserManagerMac() { |
| } |
| |
| // static |
| void UserManagerMac::OnGuestProfileCreated(Profile* guest_profile, |
| const std::string& url) { |
| DCHECK(!instance_); |
| instance_ = new UserManagerMac(guest_profile); |
| [instance_->window_controller() showURL:GURL(url)]; |
| } |
| |
| void UserManagerMac::WindowWasClosed() { |
| instance_ = NULL; |
| delete this; |
| } |