browser_state_monitor.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2012 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/chromeos/input_method/browser_state_monitor.h"
6
7#include "base/logging.h"
8#include "chrome/browser/chrome_notification_types.h"
9#include "chrome/browser/chromeos/input_method/input_method_util.h"
10#include "chromeos/ime/input_method_delegate.h"
11#include "content/public/browser/notification_service.h"
12
13namespace chromeos {
14namespace input_method {
15
16BrowserStateMonitor::BrowserStateMonitor(
17    const base::Callback<void(InputMethodManager::State)>& observer)
18    : observer_(observer),
19      state_(InputMethodManager::STATE_LOGIN_SCREEN) {
20  notification_registrar_.Add(this,
21                              chrome::NOTIFICATION_LOGIN_USER_CHANGED,
22                              content::NotificationService::AllSources());
23  notification_registrar_.Add(this,
24                              chrome::NOTIFICATION_SESSION_STARTED,
25                              content::NotificationService::AllSources());
26  notification_registrar_.Add(this,
27                              chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
28                              content::NotificationService::AllSources());
29  // We should not use ALL_BROWSERS_CLOSING here since logout might be cancelled
30  // by JavaScript after ALL_BROWSERS_CLOSING is sent (crosbug.com/11055).
31  notification_registrar_.Add(this,
32                              chrome::NOTIFICATION_APP_TERMINATING,
33                              content::NotificationService::AllSources());
34
35  if (!observer_.is_null())
36    observer_.Run(state_);
37}
38
39BrowserStateMonitor::~BrowserStateMonitor() {
40}
41
42void BrowserStateMonitor::Observe(
43    int type,
44    const content::NotificationSource& source,
45    const content::NotificationDetails& details) {
46  const InputMethodManager::State old_state = state_;
47  switch (type) {
48    case chrome::NOTIFICATION_APP_TERMINATING: {
49      state_ = InputMethodManager::STATE_TERMINATING;
50      break;
51    }
52    case chrome::NOTIFICATION_LOGIN_USER_CHANGED: {
53      // The user logged in, but the browser window for user session is not yet
54      // ready. An initial input method hasn't been set to the manager.
55      // Note that the notification is also sent when Chrome crashes/restarts
56      // as of writing, but it might be changed in the future (therefore we need
57      // to listen to NOTIFICATION_SESSION_STARTED as well.)
58      DVLOG(1) << "Received chrome::NOTIFICATION_LOGIN_USER_CHANGED";
59      state_ = InputMethodManager::STATE_BROWSER_SCREEN;
60      break;
61    }
62    case chrome::NOTIFICATION_SESSION_STARTED: {
63      // The user logged in, and the browser window for user session is ready.
64      // An initial input method has already been set.
65      // We should NOT call InitializePrefMembers() here since the notification
66      // is sent in the PreProfileInit phase in case when Chrome crashes and
67      // restarts.
68      DVLOG(1) << "Received chrome::NOTIFICATION_SESSION_STARTED";
69      state_ = InputMethodManager::STATE_BROWSER_SCREEN;
70      break;
71    }
72    case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: {
73      const bool is_screen_locked = *content::Details<bool>(details).ptr();
74      state_ = is_screen_locked ? InputMethodManager::STATE_LOCK_SCREEN :
75          InputMethodManager::STATE_BROWSER_SCREEN;
76      break;
77    }
78    default: {
79      NOTREACHED();
80      break;
81    }
82  }
83
84  if (old_state != state_ && !observer_.is_null())
85    observer_.Run(state_);
86
87  // Note: browser notifications are sent in the following order.
88  //
89  // Normal login:
90  // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED is sent.
91  // 2. Preferences::NotifyPrefChanged() is called. preload_engines (which
92  //    might change the current input method) and current/previous input method
93  //    are sent to the manager.
94  // 3. chrome::NOTIFICATION_SESSION_STARTED is sent.
95  //
96  // Chrome crash/restart (after logging in):
97  // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED might be sent.
98  // 2. chrome::NOTIFICATION_SESSION_STARTED is sent.
99  // 3. Preferences::NotifyPrefChanged() is called. The same things as above
100  //    happen.
101  //
102  // We have to be careful not to overwrite both local and user prefs when
103  // preloaded engine is set. Note that it does not work to do nothing in
104  // InputMethodChanged() between chrome::NOTIFICATION_LOGIN_USER_CHANGED and
105  // chrome::NOTIFICATION_SESSION_STARTED because SESSION_STARTED is sent very
106  // early on Chrome crash/restart.
107}
108
109}  // namespace input_method
110}  // namespace chromeos
111