Home | History | Annotate | Download | only in input_method
      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 
     13 namespace chromeos {
     14 namespace input_method {
     15 
     16 BrowserStateMonitor::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 
     39 BrowserStateMonitor::~BrowserStateMonitor() {
     40 }
     41 
     42 void 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