Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / profiles / user_manager_mac.mm
blob857753ee0d0e060e9003afb7198584b4a1282ee9
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_avatar_icon_util.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/profiles/profile_metrics.h"
14 #include "chrome/browser/profiles/profiles_state.h"
15 #include "chrome/browser/ui/browser_dialogs.h"
16 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
17 #include "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
18 #include "chrome/browser/ui/user_manager.h"
19 #include "chrome/grit/chromium_strings.h"
20 #include "content/public/browser/native_web_keyboard_event.h"
21 #include "content/public/browser/render_widget_host_view.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_delegate.h"
24 #include "ui/base/l10n/l10n_util_mac.h"
25 #include "ui/events/keycodes/keyboard_codes.h"
27 namespace {
29 // Update the App Controller with a new Profile. Used when a Profile is locked
30 // to set the Controller to the Guest profile so the old Profile's bookmarks,
31 // etc... cannot be accessed.
32 void ChangeAppControllerForProfile(Profile* profile,
33                                    Profile::CreateStatus status) {
34   if (status == Profile::CREATE_STATUS_INITIALIZED) {
35     AppController* controller =
36         base::mac::ObjCCast<AppController>([NSApp delegate]);
37     [controller windowChangedToProfile:profile];
38   }
41 }  // namespace
43 // An open User Manager window. There can only be one open at a time. This
44 // is reset to NULL when the window is closed.
45 UserManagerMac* instance_ = NULL;  // Weak.
47 // Custom WebContentsDelegate that allows handling of hotkeys.
48 class UserManagerWebContentsDelegate : public content::WebContentsDelegate {
49  public:
50   UserManagerWebContentsDelegate() {}
52   // WebContentsDelegate implementation. Forwards all unhandled keyboard events
53   // to the current window.
54   void HandleKeyboardEvent(
55       content::WebContents* source,
56       const content::NativeWebKeyboardEvent& event) override {
57     if (![BrowserWindowUtils shouldHandleKeyboardEvent:event])
58       return;
60     // -getCommandId returns -1 if the event isn't a chrome accelerator.
61     int chromeCommandId = [BrowserWindowUtils getCommandId:event];
63     // Check for Cmd+A and Cmd+V events that could come from a password field.
64     bool isTextEditingCommand =
65         (event.modifiers & blink::WebInputEvent::MetaKey) &&
66         (event.windowsKeyCode == ui::VKEY_A ||
67          event.windowsKeyCode == ui::VKEY_V);
69     // Only handle close window Chrome accelerators and text editing ones.
70     if (chromeCommandId == IDC_CLOSE_WINDOW || chromeCommandId == IDC_EXIT ||
71         isTextEditingCommand) {
72       [[NSApp mainMenu] performKeyEquivalent:event.os_event];
73     }
74   }
77 // Window controller for the User Manager view.
78 @interface UserManagerWindowController : NSWindowController <NSWindowDelegate> {
79  @private
80   scoped_ptr<content::WebContents> webContents_;
81   scoped_ptr<UserManagerWebContentsDelegate> webContentsDelegate_;
82   UserManagerMac* userManagerObserver_;  // Weak.
84 - (void)windowWillClose:(NSNotification*)notification;
85 - (void)dealloc;
86 - (id)initWithProfile:(Profile*)profile
87          withObserver:(UserManagerMac*)userManagerObserver;
88 - (void)showURL:(const GURL&)url;
89 - (void)show;
90 - (void)close;
91 - (BOOL)isVisible;
92 @end
94 @implementation UserManagerWindowController
96 - (id)initWithProfile:(Profile*)profile
97          withObserver:(UserManagerMac*)userManagerObserver {
99   // Center the window on the screen that currently has focus.
100   NSScreen* mainScreen = [NSScreen mainScreen];
101   CGFloat screenHeight = [mainScreen frame].size.height;
102   CGFloat screenWidth = [mainScreen frame].size.width;
104   NSRect contentRect =
105       NSMakeRect((screenWidth - UserManager::kWindowWidth) / 2,
106                  (screenHeight - UserManager::kWindowHeight) / 2,
107                  UserManager::kWindowWidth, UserManager::kWindowHeight);
108   ChromeEventProcessingWindow* window = [[ChromeEventProcessingWindow alloc]
109       initWithContentRect:contentRect
110                 styleMask:NSTitledWindowMask |
111                           NSClosableWindowMask |
112                           NSResizableWindowMask
113                   backing:NSBackingStoreBuffered
114                     defer:NO
115                    screen:mainScreen];
116   [window setTitle:l10n_util::GetNSString(IDS_PRODUCT_NAME)];
117   [window setMinSize:NSMakeSize(UserManager::kWindowWidth,
118                                 UserManager::kWindowHeight)];
120   if ((self = [super initWithWindow:window])) {
121     userManagerObserver_ = userManagerObserver;
123     // Initialize the web view.
124     webContents_.reset(content::WebContents::Create(
125         content::WebContents::CreateParams(profile)));
126     window.contentView = webContents_->GetNativeView();
127     webContentsDelegate_.reset(new UserManagerWebContentsDelegate());
128     webContents_->SetDelegate(webContentsDelegate_.get());
129     DCHECK(window.contentView);
131     [[NSNotificationCenter defaultCenter]
132         addObserver:self
133            selector:@selector(windowWillClose:)
134                name:NSWindowWillCloseNotification
135              object:self.window];
136   }
137   return self;
140 - (void)dealloc {
141   [[NSNotificationCenter defaultCenter] removeObserver:self];
142   [super dealloc];
145 - (void)showURL:(const GURL&)url {
146   webContents_->GetController().LoadURL(url, content::Referrer(),
147                                         ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
148                                         std::string());
149   content::RenderWidgetHostView* rwhv = webContents_->GetRenderWidgetHostView();
150   if (rwhv)
151     rwhv->SetBackgroundColor(profiles::kUserManagerBackgroundColor);
152   [self show];
155 - (void)show {
156   // Because the User Manager isn't a BrowserWindowController, activating it
157   // will not trigger a -windowChangedToProfile and update the menu bar.
158   // This is only important if the active profile is Guest, which may have
159   // happened after locking a profile.
160   if (profiles::SetActiveProfileToGuestIfLocked()) {
161     g_browser_process->profile_manager()->CreateProfileAsync(
162         ProfileManager::GetGuestProfilePath(),
163         base::Bind(&ChangeAppControllerForProfile),
164         base::string16(),
165         base::string16(),
166         std::string());
167   }
168   [[self window] makeKeyAndOrderFront:self];
171 - (void)close {
172   [[self window] close];
175 -(BOOL)isVisible {
176   return [[self window] isVisible];
179 - (void)windowWillClose:(NSNotification*)notification {
180   [[NSNotificationCenter defaultCenter] removeObserver:self];
181   DCHECK(userManagerObserver_);
182   userManagerObserver_->WindowWasClosed();
185 @end
188 void UserManager::Show(
189     const base::FilePath& profile_path_to_focus,
190     profiles::UserManagerTutorialMode tutorial_mode,
191     profiles::UserManagerProfileSelected profile_open_action) {
192   DCHECK(profile_path_to_focus != ProfileManager::GetGuestProfilePath());
194   ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::OPEN_USER_MANAGER);
195   if (instance_) {
196     // If there's a user manager window open already, just activate it.
197     [instance_->window_controller() show];
198     instance_->set_user_manager_started_showing(base::Time::Now());
199     return;
200   }
202   // Create the guest profile, if necessary, and open the User Manager
203   // from the guest profile.
204   profiles::CreateSystemProfileForUserManager(
205       profile_path_to_focus,
206       tutorial_mode,
207       profile_open_action,
208       base::Bind(&UserManagerMac::OnSystemProfileCreated, base::Time::Now()));
211 void UserManager::Hide() {
212   if (instance_)
213     [instance_->window_controller() close];
216 bool UserManager::IsShowing() {
217   return instance_ ? [instance_->window_controller() isVisible]: false;
220 void UserManager::OnUserManagerShown() {
221   if (instance_)
222     instance_->LogTimeToOpen();
225 UserManagerMac::UserManagerMac(Profile* profile) {
226   window_controller_.reset([[UserManagerWindowController alloc]
227       initWithProfile:profile withObserver:this]);
230 UserManagerMac::~UserManagerMac() {
233 // static
234 void UserManagerMac::OnSystemProfileCreated(const base::Time& start_time,
235                                             Profile* system_profile,
236                                             const std::string& url) {
237   DCHECK(!instance_);
238   instance_ = new UserManagerMac(system_profile);
239   instance_->set_user_manager_started_showing(start_time);
240   [instance_->window_controller() showURL:GURL(url)];
243 void UserManagerMac::LogTimeToOpen() {
244   if (user_manager_started_showing_ == base::Time())
245     return;
247   ProfileMetrics::LogTimeToOpenUserManager(
248       base::Time::Now() - user_manager_started_showing_);
249   user_manager_started_showing_ = base::Time();
252 void UserManagerMac::WindowWasClosed() {
253   instance_ = NULL;
254   delete this;