summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/chromeos')
-rw-r--r--chrome/browser/chromeos/DEPS1
-rwxr-xr-xchrome/browser/chromeos/PRESUBMIT.py4
-rw-r--r--chrome/browser/chromeos/audio_handler.cc60
-rw-r--r--chrome/browser/chromeos/audio_handler.h10
-rw-r--r--chrome/browser/chromeos/boot_times_loader.cc26
-rw-r--r--chrome/browser/chromeos/boot_times_loader.h1
-rw-r--r--chrome/browser/chromeos/cros/cros_api.gyp0
-rw-r--r--chrome/browser/chromeos/cros/cros_in_process_browser_test.cc288
-rw-r--r--chrome/browser/chromeos/cros/cros_in_process_browser_test.h74
-rw-r--r--chrome/browser/chromeos/cros/cros_library.cc274
-rw-r--r--chrome/browser/chromeos/cros/cros_library.h107
-rw-r--r--chrome/browser/chromeos/cros/cros_library_loader.h1
-rw-r--r--chrome/browser/chromeos/cros/cryptohome_library.cc253
-rw-r--r--chrome/browser/chromeos/cros/cryptohome_library.h102
-rw-r--r--chrome/browser/chromeos/cros/input_method_library.cc907
-rw-r--r--chrome/browser/chromeos/cros/input_method_library.h138
-rw-r--r--chrome/browser/chromeos/cros/keyboard_library.cc148
-rw-r--r--chrome/browser/chromeos/cros/keyboard_library.h35
-rw-r--r--chrome/browser/chromeos/cros/login_library.cc230
-rw-r--r--chrome/browser/chromeos/cros/login_library.h82
-rw-r--r--chrome/browser/chromeos/cros/mock_cros_library.h1
-rw-r--r--chrome/browser/chromeos/cros/mock_cryptohome_library.h59
-rw-r--r--chrome/browser/chromeos/cros/mock_input_method_library.h5
-rw-r--r--chrome/browser/chromeos/cros/mock_keyboard_library.h7
-rw-r--r--chrome/browser/chromeos/cros/mock_library_loader.h1
-rw-r--r--chrome/browser/chromeos/cros/mock_login_library.h20
-rw-r--r--chrome/browser/chromeos/cros/mock_mount_library.h11
-rw-r--r--chrome/browser/chromeos/cros/mock_network_library.h6
-rw-r--r--chrome/browser/chromeos/cros/mock_power_library.h1
-rw-r--r--chrome/browser/chromeos/cros/mock_screen_lock_library.h1
-rw-r--r--chrome/browser/chromeos/cros/mock_speech_synthesis_library.h1
-rw-r--r--chrome/browser/chromeos/cros/mock_synaptics_library.h24
-rw-r--r--chrome/browser/chromeos/cros/mock_system_library.h3
-rw-r--r--chrome/browser/chromeos/cros/mock_update_library.h4
-rw-r--r--chrome/browser/chromeos/cros/mount_library.cc191
-rw-r--r--chrome/browser/chromeos/cros/mount_library.h50
-rw-r--r--chrome/browser/chromeos/cros/network_library.cc1225
-rw-r--r--chrome/browser/chromeos/cros/network_library.h283
-rw-r--r--chrome/browser/chromeos/cros/power_library.cc168
-rw-r--r--chrome/browser/chromeos/cros/power_library.h62
-rw-r--r--chrome/browser/chromeos/cros/screen_lock_library.cc245
-rw-r--r--chrome/browser/chromeos/cros/screen_lock_library.h45
-rw-r--r--chrome/browser/chromeos/cros/speech_synthesis_library.cc59
-rw-r--r--chrome/browser/chromeos/cros/speech_synthesis_library.h20
-rw-r--r--chrome/browser/chromeos/cros/synaptics_library.cc37
-rw-r--r--chrome/browser/chromeos/cros/synaptics_library.h55
-rw-r--r--chrome/browser/chromeos/cros/syslogs_library.cc71
-rw-r--r--chrome/browser/chromeos/cros/syslogs_library.h35
-rw-r--r--chrome/browser/chromeos/cros/system_library.cc147
-rw-r--r--chrome/browser/chromeos/cros/system_library.h27
-rw-r--r--chrome/browser/chromeos/cros/update_library.cc132
-rw-r--r--chrome/browser/chromeos/cros/update_library.h47
-rw-r--r--chrome/browser/chromeos/cros_settings.cc155
-rw-r--r--chrome/browser/chromeos/cros_settings.h68
-rw-r--r--chrome/browser/chromeos/cros_settings_names.cc11
-rw-r--r--chrome/browser/chromeos/cros_settings_names.h11
-rw-r--r--chrome/browser/chromeos/customization_document.cc60
-rw-r--r--chrome/browser/chromeos/customization_document.h46
-rw-r--r--chrome/browser/chromeos/customization_document_unittest.cc8
-rw-r--r--chrome/browser/chromeos/dom_ui/accounts_options_handler.cc67
-rw-r--r--chrome/browser/chromeos/dom_ui/accounts_options_handler.h16
-rw-r--r--chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc75
-rw-r--r--chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h28
-rw-r--r--chrome/browser/chromeos/dom_ui/labs_handler.cc40
-rw-r--r--chrome/browser/chromeos/dom_ui/labs_handler.h4
-rw-r--r--chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc21
-rw-r--r--chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h5
-rw-r--r--chrome/browser/chromeos/dom_ui/language_options_handler.cc281
-rw-r--r--chrome/browser/chromeos/dom_ui/language_options_handler.h58
-rw-r--r--chrome/browser/chromeos/dom_ui/sync_options_handler.cc49
-rw-r--r--chrome/browser/chromeos/dom_ui/sync_options_handler.h23
-rw-r--r--chrome/browser/chromeos/dom_ui/system_options_handler.cc146
-rw-r--r--chrome/browser/chromeos/dom_ui/system_options_handler.h21
-rw-r--r--chrome/browser/chromeos/drop_shadow_label.h1
-rw-r--r--chrome/browser/chromeos/external_cookie_handler.h1
-rw-r--r--chrome/browser/chromeos/external_metrics.h1
-rw-r--r--chrome/browser/chromeos/external_protocol_dialog.cc4
-rw-r--r--chrome/browser/chromeos/external_protocol_dialog.h5
-rw-r--r--chrome/browser/chromeos/frame/browser_frame_chromeos.cc32
-rw-r--r--chrome/browser/chromeos/frame/browser_frame_chromeos.h1
-rw-r--r--chrome/browser/chromeos/frame/browser_view.cc134
-rw-r--r--chrome/browser/chromeos/frame/browser_view.h12
-rw-r--r--chrome/browser/chromeos/frame/normal_browser_frame_view.cc371
-rw-r--r--chrome/browser/chromeos/frame/normal_browser_frame_view.h92
-rw-r--r--chrome/browser/chromeos/frame/panel_browser_view.cc12
-rw-r--r--chrome/browser/chromeos/frame/panel_browser_view.h1
-rw-r--r--chrome/browser/chromeos/frame/panel_controller.cc98
-rw-r--r--chrome/browser/chromeos/frame/panel_controller.h5
-rw-r--r--chrome/browser/chromeos/google_update_chromeos.cc2
-rw-r--r--chrome/browser/chromeos/gview_request_interceptor.cc5
-rw-r--r--chrome/browser/chromeos/gview_request_interceptor.h1
-rw-r--r--chrome/browser/chromeos/gview_request_interceptor_unittest.cc79
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window.cc539
-rw-r--r--chrome/browser/chromeos/input_method/candidate_window.gyp1
-rw-r--r--chrome/browser/chromeos/input_method/input_method_util.cc111
-rw-r--r--chrome/browser/chromeos/input_method/input_method_util.h32
-rw-r--r--chrome/browser/chromeos/input_method/input_method_util_unittest.cc85
-rw-r--r--chrome/browser/chromeos/language_preferences.h455
-rw-r--r--chrome/browser/chromeos/language_preferences_unittest.cc6
-rw-r--r--chrome/browser/chromeos/login/account_creation_view.cc2
-rw-r--r--chrome/browser/chromeos/login/account_creation_view.h1
-rw-r--r--chrome/browser/chromeos/login/account_screen.cc12
-rw-r--r--chrome/browser/chromeos/login/account_screen.h2
-rw-r--r--chrome/browser/chromeos/login/account_screen_browsertest.cc13
-rw-r--r--chrome/browser/chromeos/login/auth_response_handler.h1
-rw-r--r--chrome/browser/chromeos/login/authentication_notification_details.h1
-rw-r--r--chrome/browser/chromeos/login/authenticator.h21
-rw-r--r--chrome/browser/chromeos/login/background_view.cc282
-rw-r--r--chrome/browser/chromeos/login/background_view.h96
-rw-r--r--chrome/browser/chromeos/login/camera.cc5
-rw-r--r--chrome/browser/chromeos/login/camera.h1
-rw-r--r--chrome/browser/chromeos/login/captcha_view.h1
-rw-r--r--chrome/browser/chromeos/login/client_login_response_handler.h3
-rw-r--r--chrome/browser/chromeos/login/cookie_fetcher.cc1
-rw-r--r--chrome/browser/chromeos/login/cookie_fetcher.h1
-rw-r--r--chrome/browser/chromeos/login/cookie_fetcher_unittest.cc5
-rw-r--r--chrome/browser/chromeos/login/eula_view.cc382
-rw-r--r--chrome/browser/chromeos/login/eula_view.h104
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.cc337
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.h61
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.cc86
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.h22
-rw-r--r--chrome/browser/chromeos/login/google_authenticator_unittest.cc306
-rw-r--r--chrome/browser/chromeos/login/helper.cc11
-rw-r--r--chrome/browser/chromeos/login/helper.h22
-rw-r--r--chrome/browser/chromeos/login/image_decoder.h1
-rw-r--r--chrome/browser/chromeos/login/image_downloader.cc4
-rw-r--r--chrome/browser/chromeos/login/image_downloader.h1
-rw-r--r--chrome/browser/chromeos/login/issue_response_handler.cc5
-rw-r--r--chrome/browser/chromeos/login/issue_response_handler.h3
-rw-r--r--chrome/browser/chromeos/login/language_switch_menu.cc25
-rw-r--r--chrome/browser/chromeos/login/language_switch_menu.h6
-rw-r--r--chrome/browser/chromeos/login/login_browsertest.cc19
-rw-r--r--chrome/browser/chromeos/login/login_html_dialog.cc43
-rw-r--r--chrome/browser/chromeos/login/login_html_dialog.h10
-rw-r--r--chrome/browser/chromeos/login/login_screen.cc29
-rw-r--r--chrome/browser/chromeos/login/login_screen.h9
-rw-r--r--chrome/browser/chromeos/login/login_screen_browsertest.cc28
-rw-r--r--chrome/browser/chromeos/login/login_status_consumer.h78
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc160
-rw-r--r--chrome/browser/chromeos/login/login_utils.h15
-rw-r--r--chrome/browser/chromeos/login/message_bubble.cc43
-rw-r--r--chrome/browser/chromeos/login/message_bubble.h32
-rw-r--r--chrome/browser/chromeos/login/mock_auth_response_handler.h1
-rw-r--r--chrome/browser/chromeos/login/mock_authenticator.h13
-rw-r--r--chrome/browser/chromeos/login/mock_screen_observer.h1
-rw-r--r--chrome/browser/chromeos/login/mock_update_screen.h1
-rw-r--r--chrome/browser/chromeos/login/network_screen.cc301
-rw-r--r--chrome/browser/chromeos/login/network_screen.h94
-rw-r--r--chrome/browser/chromeos/login/network_screen_browsertest.cc553
-rw-r--r--chrome/browser/chromeos/login/network_screen_delegate.h14
-rw-r--r--chrome/browser/chromeos/login/network_selection_view.cc422
-rw-r--r--chrome/browser/chromeos/login/network_selection_view.h74
-rw-r--r--chrome/browser/chromeos/login/new_user_view.cc265
-rw-r--r--chrome/browser/chromeos/login/new_user_view.h59
-rw-r--r--chrome/browser/chromeos/login/owner_key_utils.cc285
-rw-r--r--chrome/browser/chromeos/login/owner_key_utils.h81
-rw-r--r--chrome/browser/chromeos/login/owner_key_utils_unittest.cc105
-rw-r--r--chrome/browser/chromeos/login/password_changed_view.cc9
-rw-r--r--chrome/browser/chromeos/login/password_changed_view.h2
-rw-r--r--chrome/browser/chromeos/login/registration_screen.cc17
-rw-r--r--chrome/browser/chromeos/login/registration_screen.h2
-rw-r--r--chrome/browser/chromeos/login/rounded_rect_painter.cc68
-rw-r--r--chrome/browser/chromeos/login/rounded_rect_painter.h8
-rw-r--r--chrome/browser/chromeos/login/screen_lock_view.cc24
-rw-r--r--chrome/browser/chromeos/login/screen_lock_view.h7
-rw-r--r--chrome/browser/chromeos/login/screen_locker.cc238
-rw-r--r--chrome/browser/chromeos/login/screen_locker.h30
-rw-r--r--chrome/browser/chromeos/login/screen_locker_browsertest.cc36
-rw-r--r--chrome/browser/chromeos/login/screen_locker_tester.cc11
-rw-r--r--chrome/browser/chromeos/login/screen_locker_tester.h3
-rw-r--r--chrome/browser/chromeos/login/screen_observer.h2
-rw-r--r--chrome/browser/chromeos/login/update_screen.cc211
-rw-r--r--chrome/browser/chromeos/login/update_screen.h51
-rw-r--r--chrome/browser/chromeos/login/update_view.cc156
-rw-r--r--chrome/browser/chromeos/login/update_view.h44
-rw-r--r--chrome/browser/chromeos/login/user_controller.cc322
-rw-r--r--chrome/browser/chromeos/login/user_controller.h54
-rw-r--r--chrome/browser/chromeos/login/user_image_downloader.cc21
-rw-r--r--chrome/browser/chromeos/login/user_image_downloader.h3
-rw-r--r--chrome/browser/chromeos/login/user_image_loader.h1
-rw-r--r--chrome/browser/chromeos/login/user_image_screen.cc12
-rw-r--r--chrome/browser/chromeos/login/user_image_screen.h3
-rw-r--r--chrome/browser/chromeos/login/user_image_view.cc269
-rw-r--r--chrome/browser/chromeos/login/user_image_view.h36
-rw-r--r--chrome/browser/chromeos/login/user_manager.cc80
-rw-r--r--chrome/browser/chromeos/login/user_manager.h31
-rw-r--r--chrome/browser/chromeos/login/user_view.cc223
-rw-r--r--chrome/browser/chromeos/login/user_view.h50
-rw-r--r--chrome/browser/chromeos/login/view_screen.h22
-rw-r--r--chrome/browser/chromeos/login/web_page_screen.h11
-rw-r--r--chrome/browser/chromeos/login/web_page_view.cc10
-rw-r--r--chrome/browser/chromeos/login/web_page_view.h1
-rw-r--r--chrome/browser/chromeos/login/wizard_controller.cc537
-rw-r--r--chrome/browser/chromeos/login/wizard_controller.h66
-rw-r--r--chrome/browser/chromeos/login/wizard_controller_browsertest.cc73
-rw-r--r--chrome/browser/chromeos/login/wizard_in_process_browser_test.h1
-rw-r--r--chrome/browser/chromeos/login/wizard_screen.h7
-rw-r--r--chrome/browser/chromeos/low_battery_observer.cc3
-rw-r--r--chrome/browser/chromeos/low_battery_observer.h1
-rw-r--r--chrome/browser/chromeos/mock_cros_settings.cc36
-rw-r--r--chrome/browser/chromeos/mock_cros_settings.h30
-rw-r--r--chrome/browser/chromeos/native_dialog_window.cc43
-rw-r--r--chrome/browser/chromeos/native_dialog_window.h1
-rw-r--r--chrome/browser/chromeos/network_list.cc2
-rw-r--r--chrome/browser/chromeos/network_list.h2
-rw-r--r--chrome/browser/chromeos/network_message_observer.cc107
-rw-r--r--chrome/browser/chromeos/network_message_observer.h17
-rw-r--r--chrome/browser/chromeos/network_state_notifier.h2
-rw-r--r--chrome/browser/chromeos/network_state_notifier_browsertest.cc14
-rw-r--r--chrome/browser/chromeos/notifications/balloon_collection_impl.cc20
-rw-r--r--chrome/browser/chromeos/notifications/balloon_collection_impl.h13
-rw-r--r--chrome/browser/chromeos/notifications/balloon_view.cc17
-rw-r--r--chrome/browser/chromeos/notifications/balloon_view.h10
-rw-r--r--chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc12
-rw-r--r--chrome/browser/chromeos/notifications/desktop_notifications_unittest.h1
-rw-r--r--chrome/browser/chromeos/notifications/notification_browsertest.cc93
-rw-r--r--chrome/browser/chromeos/notifications/notification_panel.cc2
-rw-r--r--chrome/browser/chromeos/notifications/notification_panel.h3
-rw-r--r--chrome/browser/chromeos/notifications/system_notification.cc24
-rw-r--r--chrome/browser/chromeos/notifications/system_notification.h7
-rw-r--r--chrome/browser/chromeos/notifications/system_notification_factory.cc3
-rw-r--r--chrome/browser/chromeos/notifications/system_notification_factory.h1
-rw-r--r--chrome/browser/chromeos/offline/offline_load_page.cc29
-rw-r--r--chrome/browser/chromeos/offline/offline_load_page.h1
-rw-r--r--chrome/browser/chromeos/offline/offline_load_page_unittest.cc2
-rw-r--r--chrome/browser/chromeos/offline/offline_load_service.cc6
-rw-r--r--chrome/browser/chromeos/offline/offline_load_service.h3
-rw-r--r--chrome/browser/chromeos/options/cellular_config_view.cc192
-rw-r--r--chrome/browser/chromeos/options/cellular_config_view.h33
-rw-r--r--chrome/browser/chromeos/options/internet_page_view.cc27
-rw-r--r--chrome/browser/chromeos/options/internet_page_view.h2
-rw-r--r--chrome/browser/chromeos/options/ip_config_view.cc1
-rw-r--r--chrome/browser/chromeos/options/ip_config_view.h1
-rw-r--r--chrome/browser/chromeos/options/language_chewing_config_view.cc62
-rw-r--r--chrome/browser/chromeos/options/language_chewing_config_view.h17
-rw-r--r--chrome/browser/chromeos/options/language_config_model.cc13
-rw-r--r--chrome/browser/chromeos/options/language_config_model.h11
-rw-r--r--chrome/browser/chromeos/options/language_config_model_unittest.cc8
-rw-r--r--chrome/browser/chromeos/options/language_config_util.h17
-rw-r--r--chrome/browser/chromeos/options/language_config_view.cc5
-rw-r--r--chrome/browser/chromeos/options/language_config_view.h2
-rw-r--r--chrome/browser/chromeos/options/language_hangul_config_view.cc19
-rw-r--r--chrome/browser/chromeos/options/language_hangul_config_view.h3
-rw-r--r--chrome/browser/chromeos/options/language_mozc_config_view.cc72
-rw-r--r--chrome/browser/chromeos/options/language_mozc_config_view.h10
-rw-r--r--chrome/browser/chromeos/options/language_pinyin_config_view.cc28
-rw-r--r--chrome/browser/chromeos/options/language_pinyin_config_view.h9
-rw-r--r--chrome/browser/chromeos/options/network_config_view.cc3
-rw-r--r--chrome/browser/chromeos/options/network_config_view.h4
-rw-r--r--chrome/browser/chromeos/options/options_window_view.cc9
-rw-r--r--chrome/browser/chromeos/options/options_window_view.h1
-rw-r--r--chrome/browser/chromeos/options/settings_page_view.cc3
-rw-r--r--chrome/browser/chromeos/options/settings_page_view.h3
-rw-r--r--chrome/browser/chromeos/options/system_page_view.cc173
-rw-r--r--chrome/browser/chromeos/options/system_page_view.h1
-rw-r--r--chrome/browser/chromeos/options/wifi_config_view.cc57
-rw-r--r--chrome/browser/chromeos/options/wifi_config_view.h10
-rw-r--r--chrome/browser/chromeos/options/wifi_config_view_browsertest.cc14
-rw-r--r--chrome/browser/chromeos/panels/panel_scroller.cc3
-rw-r--r--chrome/browser/chromeos/panels/panel_scroller.h7
-rw-r--r--chrome/browser/chromeos/panels/panel_scroller_container.h8
-rw-r--r--chrome/browser/chromeos/panels/panel_scroller_header.h14
-rw-r--r--chrome/browser/chromeos/pipe_reader.cc17
-rw-r--r--chrome/browser/chromeos/pipe_reader.h19
-rw-r--r--chrome/browser/chromeos/pipe_reader_unittest.cc5
-rw-r--r--chrome/browser/chromeos/preferences.cc407
-rw-r--r--chrome/browser/chromeos/preferences.h55
-rw-r--r--chrome/browser/chromeos/pulse_audio_mixer.cc273
-rw-r--r--chrome/browser/chromeos/pulse_audio_mixer.h72
-rw-r--r--chrome/browser/chromeos/status/clock_menu_button.cc25
-rw-r--r--chrome/browser/chromeos/status/clock_menu_button.h4
-rw-r--r--chrome/browser/chromeos/status/clock_menu_button_browsertest.cc18
-rw-r--r--chrome/browser/chromeos/status/feedback_menu_button.cc2
-rw-r--r--chrome/browser/chromeos/status/feedback_menu_button.h2
-rw-r--r--chrome/browser/chromeos/status/language_menu_button.cc105
-rw-r--r--chrome/browser/chromeos/status/language_menu_button.h13
-rw-r--r--chrome/browser/chromeos/status/language_menu_button_browsertest.cc4
-rw-r--r--chrome/browser/chromeos/status/language_menu_button_unittest.cc101
-rw-r--r--chrome/browser/chromeos/status/network_menu_button.cc508
-rw-r--r--chrome/browser/chromeos/status/network_menu_button.h103
-rw-r--r--chrome/browser/chromeos/status/power_menu_button.cc198
-rw-r--r--chrome/browser/chromeos/status/power_menu_button.h22
-rw-r--r--chrome/browser/chromeos/status/power_menu_button_browsertest.cc95
-rw-r--r--chrome/browser/chromeos/status/status_area_button.cc56
-rw-r--r--chrome/browser/chromeos/status/status_area_button.h16
-rw-r--r--chrome/browser/chromeos/status/status_area_host.h1
-rw-r--r--chrome/browser/chromeos/status/status_area_view.cc3
-rw-r--r--chrome/browser/chromeos/status/status_area_view.h1
-rw-r--r--chrome/browser/chromeos/system_key_event_listener.h1
-rw-r--r--chrome/browser/chromeos/tab_closeable_state_watcher.cc17
-rw-r--r--chrome/browser/chromeos/tab_closeable_state_watcher.h17
-rw-r--r--chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc16
-rw-r--r--chrome/browser/chromeos/testdata/services_manifest.json19
-rw-r--r--chrome/browser/chromeos/testdata/startup_manifest.json23
-rw-r--r--chrome/browser/chromeos/update_browsertest.cc6
-rw-r--r--chrome/browser/chromeos/update_observer.cc52
-rw-r--r--chrome/browser/chromeos/update_observer.h4
-rw-r--r--chrome/browser/chromeos/usb_mount_observer.cc10
-rw-r--r--chrome/browser/chromeos/usb_mount_observer.h3
-rw-r--r--chrome/browser/chromeos/usb_mount_observer_browsertest.cc2
-rw-r--r--chrome/browser/chromeos/version_loader.cc3
-rw-r--r--chrome/browser/chromeos/version_loader.h1
-rw-r--r--chrome/browser/chromeos/view_ids.h2
-rw-r--r--chrome/browser/chromeos/volume_bubble.cc2
-rw-r--r--chrome/browser/chromeos/volume_bubble.h2
-rw-r--r--chrome/browser/chromeos/volume_bubble_view.cc2
-rw-r--r--chrome/browser/chromeos/volume_bubble_view.h1
-rw-r--r--chrome/browser/chromeos/wm_ipc.cc2
-rw-r--r--chrome/browser/chromeos/wm_ipc.h1
-rw-r--r--chrome/browser/chromeos/wm_message_listener.h1
-rw-r--r--chrome/browser/chromeos/wm_overview_controller.cc1
-rw-r--r--chrome/browser/chromeos/wm_overview_controller.h1
-rw-r--r--chrome/browser/chromeos/wm_overview_fav_icon.cc2
-rw-r--r--chrome/browser/chromeos/wm_overview_fav_icon.h1
-rw-r--r--chrome/browser/chromeos/wm_overview_snapshot.h3
-rw-r--r--chrome/browser/chromeos/wm_overview_title.cc5
-rw-r--r--chrome/browser/chromeos/wm_overview_title.h1
318 files changed, 11515 insertions, 8532 deletions
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index 29b7aa6..b12714a 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+third_party/cros",
"+cros",
]
diff --git a/chrome/browser/chromeos/PRESUBMIT.py b/chrome/browser/chromeos/PRESUBMIT.py
index 5762625..430c0f6 100755
--- a/chrome/browser/chromeos/PRESUBMIT.py
+++ b/chrome/browser/chromeos/PRESUBMIT.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Copyright (c) 2010 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.
@@ -9,4 +9,4 @@ for more details on the presubmit API built into gcl.
"""
def GetPreferredTrySlaves():
- return ['linux_chromeos']
+ return ['linux_view', 'linux_chromeos']
diff --git a/chrome/browser/chromeos/audio_handler.cc b/chrome/browser/chromeos/audio_handler.cc
index f3157ee..f069b18 100644
--- a/chrome/browser/chromeos/audio_handler.cc
+++ b/chrome/browser/chromeos/audio_handler.cc
@@ -21,6 +21,8 @@ const double kMaxVolumeDb = 6.0;
// A value of less than one adjusts quieter volumes in larger steps (giving
// finer resolution in the higher volumes).
const double kVolumeBias = 0.5;
+// If a connection is lost, we try again this many times
+const int kMaxReconnectTries = 4;
} // namespace
@@ -28,11 +30,9 @@ const double kVolumeBias = 0.5;
// handles the volume level logic.
// TODO(davej): Serialize volume/mute for next startup?
-// TODO(davej): Should we try to regain a connection if for some reason all was
-// initialized fine, but later IsValid() returned false? Maybe N retries?
-double AudioHandler::GetVolumePercent() const {
- if (!SanityCheck())
+double AudioHandler::GetVolumePercent() {
+ if (!VerifyMixerConnection())
return 0;
return VolumeDbToPercent(mixer_->GetVolumeDb());
@@ -41,7 +41,7 @@ double AudioHandler::GetVolumePercent() const {
// Set volume using our internal 0-100% range. Notice 0% is a special case of
// silence, so we set the mixer volume to kSilenceDb instead of kMinVolumeDb.
void AudioHandler::SetVolumePercent(double volume_percent) {
- if (!SanityCheck())
+ if (!VerifyMixerConnection())
return;
DCHECK(volume_percent >= 0.0);
@@ -55,7 +55,7 @@ void AudioHandler::SetVolumePercent(double volume_percent) {
}
void AudioHandler::AdjustVolumeByPercent(double adjust_by_percent) {
- if (!SanityCheck())
+ if (!VerifyMixerConnection())
return;
DLOG(INFO) << "Adjusting Volume by " << adjust_by_percent << " percent";
@@ -79,15 +79,15 @@ void AudioHandler::AdjustVolumeByPercent(double adjust_by_percent) {
mixer_->SetVolumeDb(new_volume);
}
-bool AudioHandler::IsMute() const {
- if (!SanityCheck())
+bool AudioHandler::IsMute() {
+ if (!VerifyMixerConnection())
return false;
return mixer_->IsMute();
}
void AudioHandler::SetMute(bool do_mute) {
- if (!SanityCheck())
+ if (!VerifyMixerConnection())
return;
DLOG(INFO) << "Setting Mute to " << do_mute;
@@ -101,7 +101,8 @@ void AudioHandler::OnMixerInitialized(bool success) {
}
AudioHandler::AudioHandler()
- : connected_(false) {
+ : connected_(false),
+ reconnect_tries_(0) {
mixer_.reset(new PulseAudioMixer());
if (!mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) {
LOG(ERROR) << "Unable to connect to PulseAudio";
@@ -109,22 +110,39 @@ AudioHandler::AudioHandler()
}
AudioHandler::~AudioHandler() {
+ mixer_.reset();
};
-inline bool AudioHandler::SanityCheck() const {
- if (!mixer_->IsValid()) {
+bool AudioHandler::VerifyMixerConnection() {
+ PulseAudioMixer::State mixer_state = mixer_->CheckState();
+ if (mixer_state == PulseAudioMixer::READY)
+ return true;
+ if (connected_) {
+ // Something happened and the mixer is no longer valid after having been
+ // initialized earlier.
+ connected_ = false;
+ LOG(ERROR) << "Lost connection to PulseAudio";
+ } else {
+ LOG(ERROR) << "Mixer not valid";
+ }
+
+ if ((mixer_state == PulseAudioMixer::INITIALIZING) ||
+ (mixer_state == PulseAudioMixer::SHUTTING_DOWN))
+ return false;
+
+ if (reconnect_tries_ < kMaxReconnectTries) {
+ reconnect_tries_++;
+ LOG(INFO) << "Re-connecting to PulseAudio attempt " << reconnect_tries_
+ << "/" << kMaxReconnectTries;
+ mixer_.reset(new PulseAudioMixer());
+ connected_ = mixer_->InitSync();
if (connected_) {
- // Something happened and the mixer is no longer valid after having been
- // initialized earlier.
- // TODO(davej): Try to reconnect now?
- connected_ = false;
- LOG(ERROR) << "Lost connection to PulseAudio";
- } else {
- LOG(ERROR) << "Mixer not valid";
+ reconnect_tries_ = 0;
+ return true;
}
- return false;
+ LOG(ERROR) << "Unable to re-connect to PulseAudio";
}
- return true;
+ return false;
}
// VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us
diff --git a/chrome/browser/chromeos/audio_handler.h b/chrome/browser/chromeos/audio_handler.h
index 7e443a6..67addcb 100644
--- a/chrome/browser/chromeos/audio_handler.h
+++ b/chrome/browser/chromeos/audio_handler.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_AUDIO_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_AUDIO_HANDLER_H_
+#pragma once
#include "base/scoped_ptr.h"
#include "base/singleton.h"
@@ -22,7 +23,7 @@ class AudioHandler {
// Volume may go above 100% if another process changes PulseAudio's volume.
// Returns default of 0 on error. This function will block until the volume
// is retrieved or fails. Blocking call.
- double GetVolumePercent() const;
+ double GetVolumePercent();
// Set volume level from 0-100%. Volumes above 100% are OK and boost volume,
// although clipping will occur more at higher volumes. Volume gets quieter
@@ -36,7 +37,7 @@ class AudioHandler {
// Just returns true if mute, false if not or an error occurred.
// Blocking call.
- bool IsMute() const;
+ bool IsMute();
// Mutes all audio. Non-blocking call.
void SetMute(bool do_mute);
@@ -50,14 +51,15 @@ class AudioHandler {
AudioHandler();
virtual ~AudioHandler();
- inline bool SanityCheck() const;
+ bool VerifyMixerConnection();
// Conversion between our internal scaling (0-100%) and decibels.
static double VolumeDbToPercent(double volume_db);
static double PercentToVolumeDb(double volume_percent);
scoped_ptr<PulseAudioMixer> mixer_;
- mutable bool connected_; // Mutable for sanity checking only
+ bool connected_;
+ int reconnect_tries_;
DISALLOW_COPY_AND_ASSIGN(AudioHandler);
};
diff --git a/chrome/browser/chromeos/boot_times_loader.cc b/chrome/browser/chromeos/boot_times_loader.cc
index acdadce..c6b2628 100644
--- a/chrome/browser/chromeos/boot_times_loader.cc
+++ b/chrome/browser/chromeos/boot_times_loader.cc
@@ -13,7 +13,9 @@
#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/singleton.h"
+#include "base/string_number_conversions.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/thread.h"
#include "base/time.h"
#include "chrome/browser/browser_process.h"
@@ -96,7 +98,7 @@ static bool GetTime(const std::string& log, double* value) {
size_t chars_left =
space_index != std::string::npos ? space_index : std::string::npos;
std::string value_string = contents.substr(0, chars_left);
- return StringToDouble(value_string, value);
+ return base::StringToDouble(value_string, value);
}
return false;
}
@@ -134,16 +136,16 @@ static void SendBootTimesToUMA(const BootTimesLoader::BootTimes& boot_times) {
// Stores the boot times to a file in /tmp to indicate that the
// times for the most recent boot event have been reported
// already. The file will be deleted at system shutdown/reboot.
- std::string boot_times_text = StringPrintf("total: %.2f\n"
- "firmware: %.2f\n"
- "kernel: %.2f\n"
- "system: %.2f\n"
- "chrome: %.2f\n",
- boot_times.total,
- boot_times.firmware,
- boot_times.pre_startup,
- boot_times.system,
- boot_times.chrome);
+ std::string boot_times_text = base::StringPrintf("total: %.2f\n"
+ "firmware: %.2f\n"
+ "kernel: %.2f\n"
+ "system: %.2f\n"
+ "chrome: %.2f\n",
+ boot_times.total,
+ boot_times.firmware,
+ boot_times.pre_startup,
+ boot_times.system,
+ boot_times.chrome);
file_util::WriteFile(sent, boot_times_text.data(), boot_times_text.size());
DCHECK(file_util::PathExists(sent));
}
@@ -219,7 +221,7 @@ static void WriteLoginTimes(
base::Time chrome_first_render) {
const FilePath log_path(kLogPath);
std::string output =
- StringPrintf("total: %.2f\nauth: %.2f\nlogin: %.2f\n",
+ base::StringPrintf("total: %.2f\nauth: %.2f\nlogin: %.2f\n",
(chrome_first_render - login_attempt).InSecondsF(),
(login_success - login_attempt).InSecondsF(),
(chrome_first_render - login_success).InSecondsF());
diff --git a/chrome/browser/chromeos/boot_times_loader.h b/chrome/browser/chromeos/boot_times_loader.h
index 143e425..95dd394 100644
--- a/chrome/browser/chromeos/boot_times_loader.h
+++ b/chrome/browser/chromeos/boot_times_loader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/cros/cros_api.gyp b/chrome/browser/chromeos/cros/cros_api.gyp
deleted file mode 100644
index e69de29..0000000
--- a/chrome/browser/chromeos/cros/cros_api.gyp
+++ /dev/null
diff --git a/chrome/browser/chromeos/cros/cros_in_process_browser_test.cc b/chrome/browser/chromeos/cros/cros_in_process_browser_test.cc
index 58055b5..ad88ae9 100644
--- a/chrome/browser/chromeos/cros/cros_in_process_browser_test.cc
+++ b/chrome/browser/chromeos/cros/cros_in_process_browser_test.cc
@@ -3,299 +3,19 @@
// found in the LICENSE file.
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
-
-#include "base/message_loop.h"
-#include "base/ref_counted.h"
-#include "base/time.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
-#include "chrome/browser/chromeos/cros/mock_keyboard_library.h"
-#include "chrome/browser/chromeos/cros/mock_input_method_library.h"
-#include "chrome/browser/chromeos/cros/mock_library_loader.h"
-#include "chrome/browser/chromeos/cros/mock_network_library.h"
-#include "chrome/browser/chromeos/cros/mock_power_library.h"
-#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
-#include "chrome/browser/chromeos/cros/mock_synaptics_library.h"
-#include "chrome/browser/chromeos/cros/mock_system_library.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/login/wizard_screen.h"
#include "chrome/test/in_process_browser_test.h"
-#include "chrome/test/ui_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gmock/include/gmock/gmock.h"
namespace chromeos {
-using ::testing::AnyNumber;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-using ::testing::ReturnRef;
-using ::testing::StrictMock;
-using ::testing::_;
-
-CrosInProcessBrowserTest::CrosInProcessBrowserTest()
- : loader_(NULL),
- mock_cryptohome_library_(NULL),
- mock_keyboard_library_(NULL),
- mock_input_method_library_(NULL),
- mock_network_library_(NULL),
- mock_power_library_(NULL),
- mock_screen_lock_library_(NULL),
- mock_synaptics_library_(NULL),
- mock_system_library_(NULL) {}
-
-CrosInProcessBrowserTest::~CrosInProcessBrowserTest() {
-}
-
-chromeos::CrosLibrary::TestApi* CrosInProcessBrowserTest::test_api() {
- return chromeos::CrosLibrary::Get()->GetTestApi();
-}
-
-void CrosInProcessBrowserTest::InitStatusAreaMocks() {
- InitMockKeyboardLibrary();
- InitMockInputMethodLibrary();
- InitMockNetworkLibrary();
- InitMockPowerLibrary();
- InitMockSynapticsLibrary();
- InitMockSystemLibrary();
-}
-
-void CrosInProcessBrowserTest::InitMockLibraryLoader() {
- if (loader_)
- return;
- loader_ = new StrictMock<MockLibraryLoader>();
- EXPECT_CALL(*loader_, Load(_))
- .Times(AnyNumber())
- .WillRepeatedly(Return(true));
- test_api()->SetLibraryLoader(loader_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockCryptohomeLibrary() {
- InitMockLibraryLoader();
- if (mock_cryptohome_library_)
- return;
- mock_cryptohome_library_ = new StrictMock<MockCryptohomeLibrary>();
- test_api()->SetCryptohomeLibrary(mock_cryptohome_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockKeyboardLibrary() {
- InitMockLibraryLoader();
- if (mock_keyboard_library_)
- return;
- mock_keyboard_library_ = new StrictMock<MockKeyboardLibrary>();
- test_api()->SetKeyboardLibrary(mock_keyboard_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockInputMethodLibrary() {
- InitMockLibraryLoader();
- if (mock_input_method_library_)
- return;
- mock_input_method_library_ = new StrictMock<MockInputMethodLibrary>();
- test_api()->SetInputMethodLibrary(mock_input_method_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockNetworkLibrary() {
- InitMockLibraryLoader();
- if (mock_network_library_)
- return;
- mock_network_library_ = new StrictMock<MockNetworkLibrary>();
- test_api()->SetNetworkLibrary(mock_network_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockPowerLibrary() {
- InitMockLibraryLoader();
- if (mock_power_library_)
- return;
- mock_power_library_ = new StrictMock<MockPowerLibrary>();
- test_api()->SetPowerLibrary(mock_power_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockScreenLockLibrary() {
- InitMockLibraryLoader();
- if (mock_screen_lock_library_)
- return;
- mock_screen_lock_library_ = new StrictMock<MockScreenLockLibrary>();
- test_api()->SetScreenLockLibrary(mock_screen_lock_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockSynapticsLibrary() {
- InitMockLibraryLoader();
- if (mock_synaptics_library_)
- return;
- mock_synaptics_library_ = new StrictMock<MockSynapticsLibrary>();
- test_api()->SetSynapticsLibrary(mock_synaptics_library_, true);
-}
-
-void CrosInProcessBrowserTest::InitMockSystemLibrary() {
- InitMockLibraryLoader();
- if (mock_system_library_)
- return;
- mock_system_library_ = new StrictMock<MockSystemLibrary>();
- test_api()->SetSystemLibrary(mock_system_library_, true);
-}
-
-void CrosInProcessBrowserTest::SetStatusAreaMocksExpectations() {
- SetKeyboardLibraryStatusAreaExpectations();
- SetInputMethodLibraryStatusAreaExpectations();
- SetNetworkLibraryStatusAreaExpectations();
- SetPowerLibraryStatusAreaExpectations();
- SetSynapticsLibraryExpectations();
- SetSystemLibraryStatusAreaExpectations();
-}
-
-void CrosInProcessBrowserTest::SetKeyboardLibraryStatusAreaExpectations() {
- EXPECT_CALL(*mock_keyboard_library_, GetCurrentKeyboardLayoutName())
- .Times(AnyNumber())
- .WillRepeatedly((Return("us")))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_keyboard_library_, SetCurrentKeyboardLayoutByName(_))
- .Times(AnyNumber())
- .WillRepeatedly((Return(true)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_keyboard_library_, SetKeyboardLayoutPerWindow(_))
- .Times(AnyNumber())
- .WillRepeatedly((Return(true)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_keyboard_library_, GetKeyboardLayoutPerWindow(_))
- .Times(AnyNumber())
- .WillRepeatedly((Return(true)))
- .RetiresOnSaturation();
-}
-
-void CrosInProcessBrowserTest::SetInputMethodLibraryStatusAreaExpectations() {
- EXPECT_CALL(*mock_input_method_library_, AddObserver(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_input_method_library_, GetActiveInputMethods())
- .Times(AnyNumber())
- .WillRepeatedly(InvokeWithoutArgs(CreateFallbackInputMethodDescriptors))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_input_method_library_, GetSupportedInputMethods())
- .Times(AnyNumber())
- .WillRepeatedly(InvokeWithoutArgs(CreateFallbackInputMethodDescriptors))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_input_method_library_, current_ime_properties())
- .Times(1)
- .WillOnce((ReturnRef(ime_properties_)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_input_method_library_, SetImeConfig(_, _, _))
- .Times(AnyNumber())
- .WillRepeatedly((Return(true)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_input_method_library_, RemoveObserver(_))
- .Times(1)
- .RetiresOnSaturation();
-}
-
-void CrosInProcessBrowserTest::SetNetworkLibraryStatusAreaExpectations() {
- EXPECT_CALL(*mock_network_library_, AddObserver(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, wifi_connecting())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, wifi_connected())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, cellular_connecting())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, cellular_connected())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, ethernet_connected())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, Connected())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, Connecting())
- .Times(1)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_network_library_, RemoveObserver(_))
- .Times(1)
- .RetiresOnSaturation();
-}
-void CrosInProcessBrowserTest::SetPowerLibraryStatusAreaExpectations() {
- EXPECT_CALL(*mock_power_library_, AddObserver(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, battery_fully_charged())
- .Times(3)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, battery_is_present())
- .Times(1)
- .WillOnce((Return(true)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, battery_percentage())
- .Times(2)
- .WillRepeatedly((Return(42.0)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, line_power_on())
- .Times(4)
- .WillRepeatedly((Return(false)))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, battery_time_to_empty())
- .Times(1)
- .WillOnce((Return(base::TimeDelta::FromMinutes(42))))
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_power_library_, RemoveObserver(_))
- .Times(1)
- .RetiresOnSaturation();
+CrosInProcessBrowserTest::CrosInProcessBrowserTest() {
+ cros_mock_.reset(new CrosMock());
}
-void CrosInProcessBrowserTest::SetSystemLibraryStatusAreaExpectations() {
- EXPECT_CALL(*mock_system_library_, AddObserver(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*mock_system_library_, RemoveObserver(_))
- .Times(1)
- .RetiresOnSaturation();
-}
-
-void CrosInProcessBrowserTest::SetSynapticsLibraryExpectations() {
- EXPECT_CALL(*mock_synaptics_library_, SetBoolParameter(_, _))
- .Times(AnyNumber());
- EXPECT_CALL(*mock_synaptics_library_, SetRangeParameter(_, _))
- .Times(AnyNumber());
-}
-
-void CrosInProcessBrowserTest::SetSystemLibraryExpectations() {
- EXPECT_CALL(*mock_system_library_, GetTimezone())
- .Times(AnyNumber());
- EXPECT_CALL(*mock_system_library_, SetTimezone(_))
- .Times(AnyNumber());
+CrosInProcessBrowserTest::~CrosInProcessBrowserTest() {
}
void CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture() {
- // Prevent bogus gMock leak check from firing.
- if (loader_)
- test_api()->SetLibraryLoader(NULL, false);
- if (mock_cryptohome_library_)
- test_api()->SetCryptohomeLibrary(NULL, false);
- if (mock_keyboard_library_)
- test_api()->SetKeyboardLibrary(NULL, false);
- if (mock_input_method_library_)
- test_api()->SetInputMethodLibrary(NULL, false);
- if (mock_network_library_)
- test_api()->SetNetworkLibrary(NULL, false);
- if (mock_power_library_)
- test_api()->SetPowerLibrary(NULL, false);
- if (mock_screen_lock_library_)
- test_api()->SetScreenLockLibrary(NULL, false);
- if (mock_synaptics_library_)
- test_api()->SetSynapticsLibrary(NULL, false);
- if (mock_system_library_)
- test_api()->SetSystemLibrary(NULL, false);
+ cros_mock_->TearDownMocks();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/cros_in_process_browser_test.h b/chrome/browser/chromeos/cros/cros_in_process_browser_test.h
index 52e11db..b4e9a2e 100644
--- a/chrome/browser/chromeos/cros/cros_in_process_browser_test.h
+++ b/chrome/browser/chromeos/cros/cros_in_process_browser_test.h
@@ -4,32 +4,19 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_CROS_IN_PROCESS_BROWSER_TEST_H_
#define CHROME_BROWSER_CHROMEOS_CROS_CROS_IN_PROCESS_BROWSER_TEST_H_
+#pragma once
#include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/cros_mock.h"
#include "chrome/test/in_process_browser_test.h"
-#include "cros/chromeos_input_method.h"
namespace chromeos {
-class MockCryptohomeLibrary;
-class MockKeyboardLibrary;
-class MockInputMethodLibrary;
-class MockLibraryLoader;
-class MockNetworkLibrary;
-class MockPowerLibrary;
-class MockScreenLockLibrary;
-class MockScreenLockLibrary;
-class MockSynapticsLibrary;
-class MockSystemLibrary;
-
// Base class for Chromium OS tests wanting to bring up a browser in the
// unit test process and mock some parts of CrosLibrary. Once you mock part of
// CrosLibrary it will be considered as successfully loaded and libraries
-// that compose CrosLibrary will be created. The issue here is that you do
-// need to specify minimum set of mocks for you test to succeed.
-// CrosInProcessBrowserTest defines minimum set of mocks that is used
-// by status area elements (network, input language, power).
+// that compose CrosLibrary will be created. Use CrosMock to specify minimum
+// set of mocks for you test to succeed.
// See comments for InProcessBrowserTest base class too.
class CrosInProcessBrowserTest : public InProcessBrowserTest {
public:
@@ -37,62 +24,11 @@ class CrosInProcessBrowserTest : public InProcessBrowserTest {
virtual ~CrosInProcessBrowserTest();
protected:
- // This method setups basic mocks that are used by status area items:
- // LibraryLoader, Language, Network, Power, Synaptics libraries.
- // Add call to this method at the beginning of your
- // SetUpInProcessBrowserTestFixture.
- void InitStatusAreaMocks();
-
- // Initialization of CrosLibrary mock loader. If you intend calling
- // separate init methods for mocks call this one first.
- void InitMockLibraryLoader();
-
- // Initialization of mocks.
- void InitMockCryptohomeLibrary();
- void InitMockKeyboardLibrary();
- void InitMockInputMethodLibrary();
- void InitMockNetworkLibrary();
- void InitMockPowerLibrary();
- void InitMockScreenLockLibrary();
- void InitMockSynapticsLibrary();
- void InitMockSystemLibrary();
-
- // This method setups corresponding expectations for basic mocks that
- // are used by status area items.
- // Make sure that InitStatusAreaMocks was called before.
- // Add call to this method in your SetUpInProcessBrowserTestFixture.
- // They are all configured with RetiresOnSaturation().
- // Once such expectation is used it won't block expectations you've defined.
- void SetStatusAreaMocksExpectations();
-
- // Methods to setup minimal mocks expectations for status area.
- void SetKeyboardLibraryStatusAreaExpectations();
- void SetInputMethodLibraryStatusAreaExpectations();
- void SetNetworkLibraryStatusAreaExpectations();
- void SetPowerLibraryStatusAreaExpectations();
- void SetSystemLibraryStatusAreaExpectations();
- void SetSynapticsLibraryExpectations();
- void SetSystemLibraryExpectations();
+ scoped_ptr<CrosMock> cros_mock_;
// Overriden for things you would normally override TearDown for.
virtual void TearDownInProcessBrowserTestFixture();
- // TestApi gives access to CrosLibrary private members.
- chromeos::CrosLibrary::TestApi* test_api();
-
- // Mocks, destroyed by CrosLibrary class.
- MockLibraryLoader* loader_;
- MockCryptohomeLibrary* mock_cryptohome_library_;
- MockKeyboardLibrary* mock_keyboard_library_;
- MockInputMethodLibrary* mock_input_method_library_;
- MockNetworkLibrary* mock_network_library_;
- MockPowerLibrary* mock_power_library_;
- MockScreenLockLibrary* mock_screen_lock_library_;
- MockSynapticsLibrary* mock_synaptics_library_;
- MockSystemLibrary* mock_system_library_;
-
- ImePropertyList ime_properties_;
-
private:
DISALLOW_COPY_AND_ASSIGN(CrosInProcessBrowserTest);
};
diff --git a/chrome/browser/chromeos/cros/cros_library.cc b/chrome/browser/chromeos/cros/cros_library.cc
index a9e469d..9065304 100644
--- a/chrome/browser/chromeos/cros/cros_library.cc
+++ b/chrome/browser/chromeos/cros/cros_library.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/burn_library.h"
#include "chrome/browser/chromeos/cros/cros_library_loader.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
@@ -14,77 +15,24 @@
#include "chrome/browser/chromeos/cros/power_library.h"
#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "chrome/browser/chromeos/cros/speech_synthesis_library.h"
-#include "chrome/browser/chromeos/cros/synaptics_library.h"
#include "chrome/browser/chromeos/cros/syslogs_library.h"
#include "chrome/browser/chromeos/cros/system_library.h"
+#include "chrome/browser/chromeos/cros/touchpad_library.h"
#include "chrome/browser/chromeos/cros/update_library.h"
namespace chromeos {
CrosLibrary::CrosLibrary() : library_loader_(NULL),
- crypto_lib_(NULL),
- keyboard_lib_(NULL),
- input_method_lib_(NULL),
- login_lib_(NULL),
- mount_lib_(NULL),
- network_lib_(NULL),
- power_lib_(NULL),
- screen_lock_lib_(NULL),
- speech_synthesis_lib_(NULL),
- synaptics_lib_(NULL),
- syslogs_lib_(NULL),
- system_lib_(NULL),
- update_lib_(NULL),
- own_library_loader_(true),
- own_cryptohome_lib_(true),
- own_keyboard_lib_(true),
- own_input_method_lib_(true),
- own_login_lib_(true),
- own_mount_lib_(true),
- own_network_lib_(true),
- own_power_lib_(true),
- own_screen_lock_lib_(true),
- own_speech_synthesis_lib_(true),
- own_synaptics_lib_(true),
- own_syslogs_lib_(true),
- own_system_lib_(true),
- own_update_lib_(true),
+ own_library_loader_(false),
+ use_stub_impl_(false),
loaded_(false),
load_error_(false),
test_api_(NULL) {
-
}
CrosLibrary::~CrosLibrary() {
if (own_library_loader_)
delete library_loader_;
- if (own_cryptohome_lib_)
- delete crypto_lib_;
- if (own_keyboard_lib_)
- delete keyboard_lib_;
- if (own_input_method_lib_)
- delete input_method_lib_;
- if (own_login_lib_)
- delete login_lib_;
- if (own_mount_lib_)
- delete mount_lib_;
- if (own_network_lib_)
- delete network_lib_;
- if (own_power_lib_)
- delete power_lib_;
- if (own_screen_lock_lib_)
- delete screen_lock_lib_;
- if (own_speech_synthesis_lib_)
- delete speech_synthesis_lib_;
- if (own_synaptics_lib_)
- delete synaptics_lib_;
- if (own_syslogs_lib_)
- delete syslogs_lib_;
- if (own_system_lib_)
- delete system_lib_;
- if (own_update_lib_)
- delete update_lib_;
- delete test_api_;
}
// static
@@ -92,88 +40,71 @@ CrosLibrary* CrosLibrary::Get() {
return Singleton<CrosLibrary>::get();
}
+BurnLibrary* CrosLibrary::GetBurnLibrary() {
+ return burn_lib_.GetDefaultImpl(use_stub_impl_);
+}
+
CryptohomeLibrary* CrosLibrary::GetCryptohomeLibrary() {
- if (!crypto_lib_)
- crypto_lib_ = new CryptohomeLibraryImpl();
- return crypto_lib_;
+ return crypto_lib_.GetDefaultImpl(use_stub_impl_);
}
KeyboardLibrary* CrosLibrary::GetKeyboardLibrary() {
- if (!keyboard_lib_)
- keyboard_lib_ = new KeyboardLibraryImpl();
- return keyboard_lib_;
+ return keyboard_lib_.GetDefaultImpl(use_stub_impl_);
}
InputMethodLibrary* CrosLibrary::GetInputMethodLibrary() {
- if (!input_method_lib_)
- input_method_lib_ = new InputMethodLibraryImpl();
- return input_method_lib_;
+ return input_method_lib_.GetDefaultImpl(use_stub_impl_);
}
LoginLibrary* CrosLibrary::GetLoginLibrary() {
- if (!login_lib_)
- login_lib_ = new LoginLibraryImpl();
- return login_lib_;
+ return login_lib_.GetDefaultImpl(use_stub_impl_);
}
MountLibrary* CrosLibrary::GetMountLibrary() {
- if (!mount_lib_)
- mount_lib_ = new MountLibraryImpl();
- return mount_lib_;
+ return mount_lib_.GetDefaultImpl(use_stub_impl_);
}
NetworkLibrary* CrosLibrary::GetNetworkLibrary() {
- if (!network_lib_)
- network_lib_ = new NetworkLibraryImpl();
- return network_lib_;
+ return network_lib_.GetDefaultImpl(use_stub_impl_);
}
PowerLibrary* CrosLibrary::GetPowerLibrary() {
- if (!power_lib_)
- power_lib_ = new PowerLibraryImpl();
- return power_lib_;
+ return power_lib_.GetDefaultImpl(use_stub_impl_);
}
ScreenLockLibrary* CrosLibrary::GetScreenLockLibrary() {
- if (!screen_lock_lib_)
- screen_lock_lib_ = new ScreenLockLibraryImpl();
- return screen_lock_lib_;
+ return screen_lock_lib_.GetDefaultImpl(use_stub_impl_);
}
SpeechSynthesisLibrary* CrosLibrary::GetSpeechSynthesisLibrary() {
- if (!speech_synthesis_lib_)
- speech_synthesis_lib_ = new SpeechSynthesisLibraryImpl();
- return speech_synthesis_lib_;
-}
-
-SynapticsLibrary* CrosLibrary::GetSynapticsLibrary() {
- if (!synaptics_lib_)
- synaptics_lib_ = new SynapticsLibraryImpl();
- return synaptics_lib_;
+ return speech_synthesis_lib_.GetDefaultImpl(use_stub_impl_);
}
SyslogsLibrary* CrosLibrary::GetSyslogsLibrary() {
- if (!syslogs_lib_)
- syslogs_lib_ = new SyslogsLibraryImpl();
- return syslogs_lib_;
+ return syslogs_lib_.GetDefaultImpl(use_stub_impl_);
}
SystemLibrary* CrosLibrary::GetSystemLibrary() {
- if (!system_lib_)
- system_lib_ = new SystemLibraryImpl();
- return system_lib_;
+ return system_lib_.GetDefaultImpl(use_stub_impl_);
+}
+
+TouchpadLibrary* CrosLibrary::GetTouchpadLibrary() {
+ return touchpad_lib_.GetDefaultImpl(use_stub_impl_);
}
UpdateLibrary* CrosLibrary::GetUpdateLibrary() {
- if (!update_lib_)
- update_lib_ = new UpdateLibraryImpl();
- return update_lib_;
+ return update_lib_.GetDefaultImpl(use_stub_impl_);
}
bool CrosLibrary::EnsureLoaded() {
+ if (use_stub_impl_)
+ return true;
+
if (!loaded_ && !load_error_) {
- if (!library_loader_)
+ if (!library_loader_) {
library_loader_ = new CrosLibraryLoader();
+ own_library_loader_ = true;
+ }
loaded_ = library_loader_->Load(&load_error_string_);
load_error_ = !loaded_;
}
@@ -181,9 +112,17 @@ bool CrosLibrary::EnsureLoaded() {
}
CrosLibrary::TestApi* CrosLibrary::GetTestApi() {
- if (!test_api_)
- test_api_ = new TestApi(this);
- return test_api_;
+ if (!test_api_.get())
+ test_api_.reset(new TestApi(this));
+ return test_api_.get();
+}
+
+void CrosLibrary::TestApi::SetUseStubImpl() {
+ library_->use_stub_impl_ = true;
+}
+
+void CrosLibrary::TestApi::ResetUseStubImpl() {
+ library_->use_stub_impl_ = false;
}
void CrosLibrary::TestApi::SetLibraryLoader(LibraryLoader* loader, bool own) {
@@ -199,105 +138,74 @@ void CrosLibrary::TestApi::SetLibraryLoader(LibraryLoader* loader, bool own) {
library_->load_error_ = false;
}
-void CrosLibrary::TestApi::SetCryptohomeLibrary(CryptohomeLibrary* library,
- bool own) {
- if (library_->own_cryptohome_lib_)
- delete library_->crypto_lib_;
- library_->own_cryptohome_lib_ = own;
- library_->crypto_lib_ = library;
+void CrosLibrary::TestApi::SetBurnLibrary(
+ BurnLibrary* library, bool own) {
+ library_->burn_lib_.SetImpl(library, own);
+}
+
+void CrosLibrary::TestApi::SetCryptohomeLibrary(
+ CryptohomeLibrary* library, bool own) {
+ library_->crypto_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetKeyboardLibrary(KeyboardLibrary* library,
- bool own) {
- if (library_->own_keyboard_lib_)
- delete library_->keyboard_lib_;
- library_->own_keyboard_lib_ = own;
- library_->keyboard_lib_ = library;
+void CrosLibrary::TestApi::SetKeyboardLibrary(
+ KeyboardLibrary* library, bool own) {
+ library_->keyboard_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetInputMethodLibrary(InputMethodLibrary* library,
- bool own) {
- if (library_->own_input_method_lib_)
- delete library_->input_method_lib_;
- library_->own_input_method_lib_ = own;
- library_->input_method_lib_ = library;
+void CrosLibrary::TestApi::SetInputMethodLibrary(
+ InputMethodLibrary* library, bool own) {
+ library_->input_method_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetLoginLibrary(LoginLibrary* library, bool own) {
- if (library_->own_login_lib_)
- delete library_->login_lib_;
- library_->own_login_lib_ = own;
- library_->login_lib_ = library;
+void CrosLibrary::TestApi::SetLoginLibrary(
+ LoginLibrary* library, bool own) {
+ library_->login_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetMountLibrary(MountLibrary* library, bool own) {
- if (library_->own_mount_lib_)
- delete library_->mount_lib_;
- library_->own_mount_lib_ = own;
- library_->mount_lib_ = library;
+void CrosLibrary::TestApi::SetMountLibrary(
+ MountLibrary* library, bool own) {
+ library_->mount_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetNetworkLibrary(NetworkLibrary* library,
- bool own) {
- if (library_->own_network_lib_)
- delete library_->network_lib_;
- library_->own_network_lib_ = own;
- library_->network_lib_ = library;
+void CrosLibrary::TestApi::SetNetworkLibrary(
+ NetworkLibrary* library, bool own) {
+ library_->network_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetPowerLibrary(PowerLibrary* library, bool own) {
- if (library_->own_power_lib_)
- delete library_->power_lib_;
- library_->own_power_lib_ = own;
- library_->power_lib_ = library;
+void CrosLibrary::TestApi::SetPowerLibrary(
+ PowerLibrary* library, bool own) {
+ library_->power_lib_.SetImpl(library, own);
}
-void CrosLibrary::TestApi::SetScreenLockLibrary(ScreenLockLibrary* library,
- bool own) {
- if (library_->own_screen_lock_lib_)
- delete library_->screen_lock_lib_;
- library_->own_screen_lock_lib_ = own;
- library_->screen_lock_lib_ = library;
+void CrosLibrary::TestApi::SetScreenLockLibrary(
+ ScreenLockLibrary* library, bool own) {
+ library_->screen_lock_lib_.SetImpl(library, own);
}
void CrosLibrary::TestApi::SetSpeechSynthesisLibrary(
SpeechSynthesisLibrary* library, bool own) {
- if (library_->own_speech_synthesis_lib_)
- delete library_->speech_synthesis_lib_;
- library_->own_speech_synthesis_lib_ = own;
- library_->speech_synthesis_lib_ = library;
-}
-
-void CrosLibrary::TestApi::SetSynapticsLibrary(SynapticsLibrary* library,
- bool own) {
- if (library_->own_synaptics_lib_)
- delete library_->synaptics_lib_;
- library_->own_synaptics_lib_ = own;
- library_->synaptics_lib_ = library;
-}
-
-void CrosLibrary::TestApi::SetSyslogsLibrary(SyslogsLibrary* library,
- bool own) {
- if (library_->syslogs_lib_)
- delete library_->syslogs_lib_;
- library_->own_syslogs_lib_ = own;
- library_->syslogs_lib_ = library;
-}
-
-void CrosLibrary::TestApi::SetSystemLibrary(SystemLibrary* library,
- bool own) {
- if (library_->system_lib_)
- delete library_->system_lib_;
- library_->own_system_lib_ = own;
- library_->system_lib_ = library;
-}
-
-void CrosLibrary::TestApi::SetUpdateLibrary(UpdateLibrary* library,
- bool own) {
- if (library_->update_lib_)
- delete library_->update_lib_;
- library_->own_update_lib_ = own;
- library_->update_lib_ = library;
+ library_->speech_synthesis_lib_.SetImpl(library, own);
+}
+
+void CrosLibrary::TestApi::SetTouchpadLibrary(
+ TouchpadLibrary* library, bool own) {
+ library_->touchpad_lib_.SetImpl(library, own);
+}
+
+void CrosLibrary::TestApi::SetSyslogsLibrary(
+ SyslogsLibrary* library, bool own) {
+ library_->syslogs_lib_.SetImpl(library, own);
+}
+
+void CrosLibrary::TestApi::SetSystemLibrary(
+ SystemLibrary* library, bool own) {
+ library_->system_lib_.SetImpl(library, own);
+}
+
+void CrosLibrary::TestApi::SetUpdateLibrary(
+ UpdateLibrary* library, bool own) {
+ library_->update_lib_.SetImpl(library, own);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/cros_library.h b/chrome/browser/chromeos/cros/cros_library.h
index b08254a..6695acf 100644
--- a/chrome/browser/chromeos/cros/cros_library.h
+++ b/chrome/browser/chromeos/cros/cros_library.h
@@ -4,13 +4,15 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_CROS_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_CROS_LIBRARY_H_
+#pragma once
#include <string>
#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
#include "base/singleton.h"
-
namespace chromeos {
+class BurnLibrary;
class CryptohomeLibrary;
class KeyboardLibrary;
class InputMethodLibrary;
@@ -21,9 +23,9 @@ class NetworkLibrary;
class PowerLibrary;
class ScreenLockLibrary;
class SpeechSynthesisLibrary;
-class SynapticsLibrary;
class SyslogsLibrary;
class SystemLibrary;
+class TouchpadLibrary;
class UpdateLibrary;
// This class handles access to sub-parts of ChromeOS library. it provides
@@ -31,16 +33,23 @@ class UpdateLibrary;
// be mocked for testing.
class CrosLibrary {
public:
-
// This class provides access to internal members of CrosLibrary class for
// purpose of testing (i.e. replacement of members' implementation with
// mock objects).
class TestApi {
public:
+ // Use the stub implementations of the library. This is mainly for
+ // running the chromeos build of chrome on the desktop.
+ void SetUseStubImpl();
+ // Reset the stub implementations of the library, called after
+ // SetUseStubImp is called.
+ void ResetUseStubImpl();
// Passing true for own for these setters will cause them to be deleted
// when the CrosLibrary is deleted (or other mocks are set).
// Setter for LibraryLoader.
void SetLibraryLoader(LibraryLoader* loader, bool own);
+ // Setter for BurnLibrary.
+ void SetBurnLibrary(BurnLibrary* library, bool own);
// Setter for CryptohomeLibrary.
void SetCryptohomeLibrary(CryptohomeLibrary* library, bool own);
// Setter for KeyboardLibrary
@@ -59,12 +68,12 @@ class CrosLibrary {
void SetScreenLockLibrary(ScreenLockLibrary* library, bool own);
// Setter for SpeechSynthesisLibrary.
void SetSpeechSynthesisLibrary(SpeechSynthesisLibrary* library, bool own);
- // Setter for SynapticsLibrary.
- void SetSynapticsLibrary(SynapticsLibrary* library, bool own);
// Setter for SyslogsLibrary.
void SetSyslogsLibrary(SyslogsLibrary* library, bool own);
// Setter for SystemLibrary.
void SetSystemLibrary(SystemLibrary* library, bool own);
+ // Setter for TouchpadLibrary.
+ void SetTouchpadLibrary(TouchpadLibrary* library, bool own);
// Setter for UpdateLibrary.
void SetUpdateLibrary(UpdateLibrary* library, bool own);
@@ -77,6 +86,9 @@ class CrosLibrary {
// This gets the CrosLibrary.
static CrosLibrary* Get();
+ // Getter for BurnLibrary.
+ BurnLibrary* GetBurnLibrary();
+
// Getter for CryptohomeLibrary.
CryptohomeLibrary* GetCryptohomeLibrary();
@@ -104,15 +116,15 @@ class CrosLibrary {
// This gets the singleton SpeechSynthesisLibrary.
SpeechSynthesisLibrary* GetSpeechSynthesisLibrary();
- // This gets the singleton SynapticsLibrary.
- SynapticsLibrary* GetSynapticsLibrary();
-
// This gets the singleton SyslogsLibrary.
SyslogsLibrary* GetSyslogsLibrary();
// This gets the singleton SystemLibrary.
SystemLibrary* GetSystemLibrary();
+ // This gets the singleton TouchpadLibrary.
+ TouchpadLibrary* GetTouchpadLibrary();
+
// This gets the singleton UpdateLibrary.
UpdateLibrary* GetUpdateLibrary();
@@ -136,42 +148,67 @@ class CrosLibrary {
virtual ~CrosLibrary();
LibraryLoader* library_loader_;
- CryptohomeLibrary* crypto_lib_;
- KeyboardLibrary* keyboard_lib_;
- InputMethodLibrary* input_method_lib_;
- LoginLibrary* login_lib_;
- MountLibrary* mount_lib_;
- NetworkLibrary* network_lib_;
- PowerLibrary* power_lib_;
- ScreenLockLibrary* screen_lock_lib_;
- SpeechSynthesisLibrary* speech_synthesis_lib_;
- SynapticsLibrary* synaptics_lib_;
- SyslogsLibrary* syslogs_lib_;
- SystemLibrary* system_lib_;
- UpdateLibrary* update_lib_;
bool own_library_loader_;
- bool own_cryptohome_lib_;
- bool own_keyboard_lib_;
- bool own_input_method_lib_;
- bool own_login_lib_;
- bool own_mount_lib_;
- bool own_network_lib_;
- bool own_power_lib_;
- bool own_screen_lock_lib_;
- bool own_speech_synthesis_lib_;
- bool own_synaptics_lib_;
- bool own_syslogs_lib_;
- bool own_system_lib_;
- bool own_update_lib_;
+ // This template supports the creation, setting and optional deletion of
+ // the cros libraries.
+ template <class L>
+ class Library {
+ public:
+ Library() : library_(NULL), own_(true) {}
+
+ ~Library() {
+ if (own_)
+ delete library_;
+ }
+
+ L* GetDefaultImpl(bool use_stub_impl) {
+ if (!library_) {
+ own_ = true;
+ library_ = L::GetImpl(use_stub_impl);
+ }
+ return library_;
+ }
+
+ void SetImpl(L* library, bool own) {
+ if (library != library_) {
+ if (own_)
+ delete library_;
+ library_ = library;
+ own_ = own;
+ }
+ }
+
+ private:
+ L* library_;
+ bool own_;
+ };
+
+ Library<BurnLibrary> burn_lib_;
+ Library<CryptohomeLibrary> crypto_lib_;
+ Library<KeyboardLibrary> keyboard_lib_;
+ Library<InputMethodLibrary> input_method_lib_;
+ Library<LoginLibrary> login_lib_;
+ Library<MountLibrary> mount_lib_;
+ Library<NetworkLibrary> network_lib_;
+ Library<PowerLibrary> power_lib_;
+ Library<ScreenLockLibrary> screen_lock_lib_;
+ Library<SpeechSynthesisLibrary> speech_synthesis_lib_;
+ Library<SyslogsLibrary> syslogs_lib_;
+ Library<SystemLibrary> system_lib_;
+ Library<TouchpadLibrary> touchpad_lib_;
+ Library<UpdateLibrary> update_lib_;
+
+ // Stub implementations of the libraries should be used.
+ bool use_stub_impl_;
// True if libcros was successfully loaded.
bool loaded_;
// True if the last load attempt had an error.
bool load_error_;
// Contains the error string from the last load attempt.
std::string load_error_string_;
- TestApi* test_api_;
+ scoped_ptr<TestApi> test_api_;
DISALLOW_COPY_AND_ASSIGN(CrosLibrary);
};
diff --git a/chrome/browser/chromeos/cros/cros_library_loader.h b/chrome/browser/chromeos/cros/cros_library_loader.h
index c326ab6..3ee1679 100644
--- a/chrome/browser/chromeos/cros/cros_library_loader.h
+++ b/chrome/browser/chromeos/cros/cros_library_loader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_CROS_LIBRARY_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_CROS_CROS_LIBRARY_LOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chrome/browser/chromeos/cros/cryptohome_library.cc
index 6ac8432..cd75a85 100644
--- a/chrome/browser/chromeos/cros/cryptohome_library.cc
+++ b/chrome/browser/chromeos/cros/cryptohome_library.cc
@@ -4,46 +4,239 @@
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "base/hash_tables.h"
#include "base/message_loop.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
namespace chromeos {
-bool CryptohomeLibraryImpl::CheckKey(const std::string& user_email,
- const std::string& passhash) {
- return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str());
-}
+// This class handles the interaction with the ChromeOS cryptohome library APIs.
+class CryptohomeLibraryImpl : public CryptohomeLibrary {
+ public:
+ CryptohomeLibraryImpl() {
+ if (CrosLibrary::Get()->EnsureLoaded())
+ Init();
+ }
+ virtual ~CryptohomeLibraryImpl() {}
-bool CryptohomeLibraryImpl::MigrateKey(const std::string& user_email,
- const std::string& old_hash,
- const std::string& new_hash) {
- return chromeos::CryptohomeMigrateKey(user_email.c_str(),
- old_hash.c_str(),
- new_hash.c_str());
-}
+ bool CheckKey(const std::string& user_email, const std::string& passhash) {
+ return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str());
+ }
-bool CryptohomeLibraryImpl::Remove(const std::string& user_email) {
- return chromeos::CryptohomeRemove(user_email.c_str());
-}
+ bool AsyncCheckKey(const std::string& user_email,
+ const std::string& passhash,
+ Delegate* d) {
+ return CacheCallback(
+ chromeos::CryptohomeAsyncCheckKey(user_email.c_str(), passhash.c_str()),
+ d,
+ "Couldn't initiate async check of user's key.");
+ }
-bool CryptohomeLibraryImpl::Mount(const std::string& user_email,
- const std::string& passhash,
- int* error_code) {
- return chromeos::CryptohomeMountAllowFail(user_email.c_str(),
- passhash.c_str(),
- error_code);
-}
+ bool MigrateKey(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash) {
+ return chromeos::CryptohomeMigrateKey(user_email.c_str(),
+ old_hash.c_str(),
+ new_hash.c_str());
+ }
-bool CryptohomeLibraryImpl::MountForBwsi(int* error_code) {
- return chromeos::CryptohomeMountGuest(error_code);
-}
+ bool AsyncMigrateKey(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash,
+ Delegate* d) {
+ return CacheCallback(
+ chromeos::CryptohomeAsyncMigrateKey(user_email.c_str(),
+ old_hash.c_str(),
+ new_hash.c_str()),
+ d,
+ "Couldn't initiate aync migration of user's key");
+ }
-bool CryptohomeLibraryImpl::IsMounted() {
- return chromeos::CryptohomeIsMounted();
-}
+ bool Mount(const std::string& user_email,
+ const std::string& passhash,
+ int* error_code) {
+ return chromeos::CryptohomeMountAllowFail(user_email.c_str(),
+ passhash.c_str(),
+ error_code);
+ }
+
+ bool AsyncMount(const std::string& user_email,
+ const std::string& passhash,
+ const bool create_if_missing,
+ Delegate* d) {
+ return CacheCallback(
+ chromeos::CryptohomeAsyncMount(user_email.c_str(),
+ passhash.c_str(),
+ create_if_missing,
+ "",
+ std::vector<std::string>()),
+ d,
+ "Couldn't initiate async mount of cryptohome.");
+ }
+
+ bool MountForBwsi(int* error_code) {
+ return chromeos::CryptohomeMountGuest(error_code);
+ }
+
+ bool AsyncMountForBwsi(Delegate* d) {
+ return CacheCallback(chromeos::CryptohomeAsyncMountGuest(),
+ d,
+ "Couldn't initiate async mount of cryptohome.");
+ }
+
+ bool Remove(const std::string& user_email) {
+ return chromeos::CryptohomeRemove(user_email.c_str());
+ }
+
+ bool AsyncRemove(const std::string& user_email, Delegate* d) {
+ return CacheCallback(
+ chromeos::CryptohomeAsyncRemove(user_email.c_str()),
+ d,
+ "Couldn't initiate async removal of cryptohome.");
+ }
+
+ bool IsMounted() {
+ return chromeos::CryptohomeIsMounted();
+ }
+
+ CryptohomeBlob GetSystemSalt() {
+ return chromeos::CryptohomeGetSystemSalt();
+ }
+
+ private:
+ static void Handler(const chromeos::CryptohomeAsyncCallStatus& event,
+ void* cryptohome_library) {
+ CryptohomeLibraryImpl* library =
+ reinterpret_cast<CryptohomeLibraryImpl*>(cryptohome_library);
+ library->Dispatch(event);
+ }
+
+ void Init() {
+ cryptohome_connection_ = chromeos::CryptohomeMonitorSession(&Handler, this);
+ }
+
+ void Dispatch(const chromeos::CryptohomeAsyncCallStatus& event) {
+ callback_map_[event.async_id]->OnComplete(event.return_status,
+ event.return_code);
+ callback_map_[event.async_id] = NULL;
+ }
+
+ bool CacheCallback(int async_id,
+ Delegate* d,
+ const char* error) {
+ if (async_id == 0) {
+ LOG(ERROR) << error;
+ return false;
+ }
+ callback_map_[async_id] = d;
+ return true;
+ }
+
+ typedef base::hash_map<int, Delegate*> CallbackMap;
+ mutable CallbackMap callback_map_;
+
+ void* cryptohome_connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl);
+};
+
+class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
+ public:
+ CryptohomeLibraryStubImpl() {}
+ virtual ~CryptohomeLibraryStubImpl() {}
+
+ bool CheckKey(const std::string& user_email, const std::string& passhash) {
+ return true;
+ }
+
+ bool AsyncCheckKey(const std::string& user_email,
+ const std::string& passhash,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+
+ bool MigrateKey(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash) {
+ return true;
+ }
+
+ bool AsyncMigrateKey(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+
+ bool Remove(const std::string& user_email) {
+ return true;
+ }
+
+ bool AsyncRemove(const std::string& user_email, Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+
+ bool Mount(const std::string& user_email,
+ const std::string& passhash,
+ int* error_code) {
+ return true;
+ }
+
+ bool AsyncMount(const std::string& user_email,
+ const std::string& passhash,
+ const bool create_if_missing,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+
+ bool MountForBwsi(int* error_code) {
+ return true;
+ }
+
+ bool AsyncMountForBwsi(Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+
+ bool IsMounted() {
+ return true;
+ }
+
+ CryptohomeBlob GetSystemSalt() {
+ CryptohomeBlob salt = CryptohomeBlob();
+ salt.push_back(0);
+ salt.push_back(0);
+ return salt;
+ }
+
+ private:
+ static void DoStubCallback(Delegate* callback) {
+ callback->OnComplete(true, kCryptohomeMountErrorNone);
+ }
+ DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl);
+};
-CryptohomeBlob CryptohomeLibraryImpl::GetSystemSalt() {
- return chromeos::CryptohomeGetSystemSalt();
+// static
+CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new CryptohomeLibraryStubImpl();
+ else
+ return new CryptohomeLibraryImpl();
}
-} // namespace chromeos
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.h b/chrome/browser/chromeos/cros/cryptohome_library.h
index 6e91d30..9a72761 100644
--- a/chrome/browser/chromeos/cros/cryptohome_library.h
+++ b/chrome/browser/chromeos/cros/cryptohome_library.h
@@ -4,10 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_CRYPTOHOME_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_CRYPTOHOME_LIBRARY_H_
+#pragma once
#include <string>
#include "base/singleton.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
#include "cros/chromeos_cryptohome.h"
namespace chromeos {
@@ -16,68 +18,90 @@ namespace chromeos {
// APIs.
class CryptohomeLibrary {
public:
- virtual ~CryptohomeLibrary() {}
-
- // Asks cryptohomed to try to find the cryptohome for |user_email| and then
- // mount it using |passhash| to unlock the key.
- virtual bool Mount(const std::string& user_email,
- const std::string& passhash,
- int* error_code) = 0;
+ class Delegate {
+ public:
+ // This will be called back on the UI thread. Consult |return_code| for
+ // further information beyond mere success or failure.
+ virtual void OnComplete(bool success, int return_code) = 0;
+ };
- // Asks cryptohomed to mount a tmpfs for BWSI mode.
- virtual bool MountForBwsi(int* error_code) = 0;
+ virtual ~CryptohomeLibrary() {}
// Asks cryptohomed to try to find the cryptohome for |user_email| and then
// use |passhash| to unlock the key.
virtual bool CheckKey(const std::string& user_email,
const std::string& passhash) = 0;
+ // Asks cryptohomed to asynchronously try to find the cryptohome for
+ // |user_email| and then use |passhash| to unlock the key.
+ // Returns true if the attempt is successfully initiated.
+ // d->OnComplete() will be called with status info on completion.
+ virtual bool AsyncCheckKey(const std::string& user_email,
+ const std::string& passhash,
+ Delegate* callback) = 0;
+
// Asks cryptohomed to try to find the cryptohome for |user_email| and then
// change from using |old_hash| to lock the key to using |new_hash|.
virtual bool MigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash) = 0;
- // Asks cryptohomed to try to find the cryptohome for |user_email| and then
- // nuke it.
- virtual bool Remove(const std::string& user_email) = 0;
-
- // Asks cryptohomed if a drive is currently mounted.
- virtual bool IsMounted() = 0;
-
- // Asks cryptohomed for the system salt.
- virtual CryptohomeBlob GetSystemSalt() = 0;
-
-};
+ // Asks cryptohomed to asynchronously try to find the cryptohome for
+ // |user_email| and then change from using |old_hash| to lock the
+ // key to using |new_hash|.
+ // Returns true if the attempt is successfully initiated.
+ // d->OnComplete() will be called with status info on completion.
+ virtual bool AsyncMigrateKey(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash,
+ Delegate* callback) = 0;
-// This class handles the interaction with the ChromeOS cryptohome library APIs.
-class CryptohomeLibraryImpl : public CryptohomeLibrary {
- public:
- CryptohomeLibraryImpl() {}
- virtual ~CryptohomeLibraryImpl() {}
-
- // CryptohomeLibrary overrides.
+ // Asks cryptohomed to try to find the cryptohome for |user_email| and then
+ // mount it using |passhash| to unlock the key.
virtual bool Mount(const std::string& user_email,
const std::string& passhash,
- int* error_code);
+ int* error_code) = 0;
- virtual bool MountForBwsi(int* error_code);
+ // Asks cryptohomed to asynchronously try to find the cryptohome for
+ // |user_email| and then mount it using |passhash| to unlock the key.
+ // |create_if_missing| controls whether or not we ask cryptohomed to
+ // create a new home dir if one does not yet exist for |user_email|.
+ // Returns true if the attempt is successfully initiated.
+ // d->OnComplete() will be called with status info on completion.
+ // If |create_if_missing| is false, and no cryptohome exists for |user_email|,
+ // we'll get d->OnComplete(false, kCryptohomeMountErrorUserDoesNotExist).
+ // Otherwise, we expect the normal range of return codes.
+ virtual bool AsyncMount(const std::string& user_email,
+ const std::string& passhash,
+ const bool create_if_missing,
+ Delegate* callback) = 0;
- virtual bool CheckKey(const std::string& user_email,
- const std::string& passhash);
+ // Asks cryptohomed to mount a tmpfs for BWSI mode.
+ virtual bool MountForBwsi(int* error_code) = 0;
- virtual bool MigrateKey(const std::string& user_email,
- const std::string& old_hash,
- const std::string& new_hash);
+ // Asks cryptohomed to asynchronously to mount a tmpfs for BWSI mode.
+ // Returns true if the attempt is successfully initiated.
+ // d->OnComplete() will be called with status info on completion.
+ virtual bool AsyncMountForBwsi(Delegate* callback) = 0;
+
+ // Asks cryptohomed to try to find the cryptohome for |user_email| and then
+ // nuke it.
+ virtual bool Remove(const std::string& user_email) = 0;
- virtual bool Remove(const std::string& user_email);
+ // Asks cryptohomed to asynchronously try to find the cryptohome for
+ // |user_email| and then nuke it.
+ virtual bool AsyncRemove(const std::string& user_email,
+ Delegate* callback) = 0;
- virtual bool IsMounted();
+ // Asks cryptohomed if a drive is currently mounted.
+ virtual bool IsMounted() = 0;
- virtual CryptohomeBlob GetSystemSalt();
+ // Asks cryptohomed for the system salt.
+ virtual CryptohomeBlob GetSystemSalt() = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static CryptohomeLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/input_method_library.cc b/chrome/browser/chromeos/cros/input_method_library.cc
index 260e507..933700b 100644
--- a/chrome/browser/chromeos/cros/input_method_library.cc
+++ b/chrome/browser/chromeos/cros/input_method_library.cc
@@ -4,20 +4,27 @@
#include "chrome/browser/chromeos/cros/input_method_library.h"
+#include <glib.h>
+#include <signal.h>
+
+#include "unicode/uloc.h"
+
#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/string_util.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
-#include "third_party/icu/public/common/unicode/uloc.h"
-
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl);
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
namespace {
+const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon";
+const char kCandidateWindowPath[] = "/opt/google/chrome/candidate_window";
// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
// property with |new_prop|. Returns true if such a property is found.
@@ -37,265 +44,737 @@ bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop,
return false;
}
-// The default keyboard layout.
-const char kDefaultKeyboardLayout[] = "us";
-
} // namespace
namespace chromeos {
-InputMethodLibraryImpl::InputMethodLibraryImpl()
- : input_method_status_connection_(NULL),
- previous_input_method_("", "", "", ""),
- current_input_method_("", "", "", "") {
- scoped_ptr<InputMethodDescriptors> input_method_descriptors(
- CreateFallbackInputMethodDescriptors());
- current_input_method_ = input_method_descriptors->at(0);
-}
-
-InputMethodLibraryImpl::~InputMethodLibraryImpl() {
- if (input_method_status_connection_) {
- chromeos::DisconnectInputMethodStatus(input_method_status_connection_);
+class InputMethodLibraryImpl : public InputMethodLibrary,
+ public NotificationObserver {
+ public:
+ InputMethodLibraryImpl()
+ : input_method_status_connection_(NULL),
+ previous_input_method_("", "", "", ""),
+ current_input_method_("", "", "", ""),
+ should_launch_ime_(false),
+ ime_connected_(false),
+ defer_ime_startup_(false),
+ should_change_input_method_(false),
+ ibus_daemon_process_id_(0),
+ candidate_window_process_id_(0),
+ failure_count_(0) {
+ scoped_ptr<InputMethodDescriptors> input_method_descriptors(
+ CreateFallbackInputMethodDescriptors());
+ current_input_method_ = input_method_descriptors->at(0);
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ current_input_method_id_ = chromeos::GetHardwareKeyboardLayoutName();
+ }
+ // Observe APP_EXITING to stop input method processes gracefully.
+ // Note that even if we fail to stop input method processes from
+ // Chrome in case of a sudden crash, we have a way to do it from an
+ // upstart script. See crosbug.com/6515 and crosbug.com/6995 for
+ // details.
+ notification_registrar_.Add(this, NotificationType::APP_EXITING,
+ NotificationService::AllSources());
}
-}
-InputMethodLibraryImpl::Observer::~Observer() {
-}
+ ~InputMethodLibraryImpl() {
+ }
-void InputMethodLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void InputMethodLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-chromeos::InputMethodDescriptors*
-InputMethodLibraryImpl::GetActiveInputMethods() {
- chromeos::InputMethodDescriptors* result = NULL;
- // The connection does not need to be alive, but it does need to be created.
- if (EnsureLoadedAndStarted()) {
- result = chromeos::GetActiveInputMethods(input_method_status_connection_);
+ InputMethodDescriptors* GetActiveInputMethods() {
+ chromeos::InputMethodDescriptors* result = NULL;
+ // The connection does not need to be alive, but it does need to be created.
+ if (EnsureLoadedAndStarted()) {
+ result = chromeos::GetActiveInputMethods(input_method_status_connection_);
+ }
+ if (!result || result->empty()) {
+ result = CreateFallbackInputMethodDescriptors();
+ }
+ return result;
}
- if (!result || result->empty()) {
- result = CreateFallbackInputMethodDescriptors();
+
+ size_t GetNumActiveInputMethods() {
+ scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
+ return input_methods->size();
}
- return result;
-}
-size_t InputMethodLibraryImpl::GetNumActiveInputMethods() {
- scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
- return input_methods->size();
-}
+ InputMethodDescriptors* GetSupportedInputMethods() {
+ InputMethodDescriptors* result = NULL;
+ // The connection does not need to be alive, but it does need to be created.
+ if (EnsureLoadedAndStarted()) {
+ result = chromeos::GetSupportedInputMethods(
+ input_method_status_connection_);
+ }
+ if (!result || result->empty()) {
+ result = CreateFallbackInputMethodDescriptors();
+ }
+ return result;
+ }
-chromeos::InputMethodDescriptors*
-InputMethodLibraryImpl::GetSupportedInputMethods() {
- chromeos::InputMethodDescriptors* result = NULL;
- // The connection does not need to be alive, but it does need to be created.
- if (EnsureLoadedAndStarted()) {
- result = chromeos::GetSupportedInputMethods(
- input_method_status_connection_);
+ void ChangeInputMethod(const std::string& input_method_id) {
+ current_input_method_id_ = input_method_id;
+ if (EnsureLoadedAndStarted()) {
+ if (input_method_id != chromeos::GetHardwareKeyboardLayoutName()) {
+ StartInputMethodProcesses();
+ }
+ chromeos::ChangeInputMethod(
+ input_method_status_connection_, input_method_id.c_str());
+ }
}
- if (!result || result->empty()) {
- result = CreateFallbackInputMethodDescriptors();
+
+ void SetImePropertyActivated(const std::string& key, bool activated) {
+ DCHECK(!key.empty());
+ if (EnsureLoadedAndStarted()) {
+ chromeos::SetImePropertyActivated(
+ input_method_status_connection_, key.c_str(), activated);
+ }
}
- return result;
-}
-void InputMethodLibraryImpl::ChangeInputMethod(
- const std::string& input_method_id) {
- if (EnsureLoadedAndStarted()) {
- chromeos::ChangeInputMethod(
- input_method_status_connection_, input_method_id.c_str());
+ bool InputMethodIsActivated(const std::string& input_method_id) {
+ scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
+ CrosLibrary::Get()->GetInputMethodLibrary()->GetActiveInputMethods());
+ for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
+ if (active_input_method_descriptors->at(i).id == input_method_id) {
+ return true;
+ }
+ }
+ return false;
}
-}
-void InputMethodLibraryImpl::SetImePropertyActivated(const std::string& key,
- bool activated) {
- DCHECK(!key.empty());
- if (EnsureLoadedAndStarted()) {
- chromeos::SetImePropertyActivated(
- input_method_status_connection_, key.c_str(), activated);
+ bool GetImeConfig(const char* section, const char* config_name,
+ ImeConfigValue* out_value) {
+ bool success = false;
+ if (EnsureLoadedAndStarted()) {
+ success = chromeos::GetImeConfig(input_method_status_connection_,
+ section, config_name, out_value);
+ }
+ return success;
}
-}
-bool InputMethodLibraryImpl::InputMethodIsActivated(
- const std::string& input_method_id) {
- scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
- CrosLibrary::Get()->GetInputMethodLibrary()->GetActiveInputMethods());
- for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
- if (active_input_method_descriptors->at(i).id == input_method_id) {
- return true;
+ bool SetImeConfig(const char* section, const char* config_name,
+ const ImeConfigValue& value) {
+ MaybeStartOrStopInputMethodProcesses(section, config_name, value);
+
+ const ConfigKeyType key = std::make_pair(section, config_name);
+ current_config_values_[key] = value;
+ if (ime_connected_) {
+ pending_config_requests_[key] = value;
+ FlushImeConfig();
}
+ return pending_config_requests_.empty();
}
- return false;
-}
-bool InputMethodLibraryImpl::GetImeConfig(
- const char* section, const char* config_name, ImeConfigValue* out_value) {
- bool success = false;
- if (EnsureLoadedAndStarted()) {
- success = chromeos::GetImeConfig(
- input_method_status_connection_, section, config_name, out_value);
+ virtual const InputMethodDescriptor& previous_input_method() const {
+ return previous_input_method_;
+ }
+ virtual const InputMethodDescriptor& current_input_method() const {
+ return current_input_method_;
}
- return success;
-}
-bool InputMethodLibraryImpl::SetImeConfig(
- const char* section, const char* config_name, const ImeConfigValue& value) {
- const ConfigKeyType key = std::make_pair(section, config_name);
- pending_config_requests_.erase(key);
- pending_config_requests_.insert(std::make_pair(key, value));
- current_config_values_[key] = value;
- FlushImeConfig();
- return pending_config_requests_.empty();
-}
+ virtual const ImePropertyList& current_ime_properties() const {
+ return current_ime_properties_;
+ }
-void InputMethodLibraryImpl::FlushImeConfig() {
- bool active_input_methods_are_changed = false;
- if (EnsureLoadedAndStarted()) {
- InputMethodConfigRequests::iterator iter = pending_config_requests_.begin();
- while (iter != pending_config_requests_.end()) {
- const std::string& section = iter->first.first;
- const std::string& config_name = iter->first.second;
- const ImeConfigValue& value = iter->second;
- if (chromeos::SetImeConfig(input_method_status_connection_,
- section.c_str(), config_name.c_str(), value)) {
- // Successfully sent. Remove the command and proceed to the next one.
- pending_config_requests_.erase(iter++);
- // Check if it's a change in active input methods.
- if (config_name == kPreloadEnginesConfigName) {
- active_input_methods_are_changed = true;
+ private:
+ // Starts or stops the input method processes based on the current state.
+ void MaybeStartOrStopInputMethodProcesses(
+ const char* section,
+ const char* config_name,
+ const ImeConfigValue& value) {
+ if (!strcmp(language_prefs::kGeneralSectionName, section) &&
+ !strcmp(language_prefs::kPreloadEnginesConfigName, config_name)) {
+ if (EnsureLoadedAndStarted()) {
+ // If there are no input methods other than one for the hardware
+ // keyboard, we'll stop the input method processes.
+ if (value.type == ImeConfigValue::kValueTypeStringList &&
+ value.string_list_value.size() == 1 &&
+ value.string_list_value[0] ==
+ chromeos::GetHardwareKeyboardLayoutName()) {
+ StopInputMethodProcesses();
+ } else if (!defer_ime_startup_) {
+ StartInputMethodProcesses();
+ }
+ chromeos::SetActiveInputMethods(input_method_status_connection_, value);
+ }
+ }
+ }
+
+ // Flushes the input method config data. The config data is queued up in
+ // |pending_config_requests_| until the config backend (ibus-memconf)
+ // starts. Since there is no good way to get notified when the config
+ // backend starts, we use a timer to periodically attempt to send the
+ // config data to the config backend.
+ void FlushImeConfig() {
+ bool active_input_methods_are_changed = false;
+ bool completed = false;
+ if (EnsureLoadedAndStarted()) {
+ InputMethodConfigRequests::iterator iter =
+ pending_config_requests_.begin();
+ while (iter != pending_config_requests_.end()) {
+ const std::string& section = iter->first.first;
+ const std::string& config_name = iter->first.second;
+ const ImeConfigValue& value = iter->second;
+ if (chromeos::SetImeConfig(input_method_status_connection_,
+ section.c_str(),
+ config_name.c_str(),
+ value)) {
+ // Check if it's a change in active input methods.
+ if (config_name == language_prefs::kPreloadEnginesConfigName) {
+ active_input_methods_are_changed = true;
+ }
+ // Successfully sent. Remove the command and proceed to the next one.
+ pending_config_requests_.erase(iter++);
+ } else {
+ // If SetImeConfig() fails, subsequent calls will likely fail.
+ break;
+ }
+ }
+ if (pending_config_requests_.empty()) {
+ // Calls to ChangeInputMethod() will fail if the input method has not
+ // yet been added to preload_engines. As such, the call is deferred
+ // until after all config values have been sent to the IME process.
+ if (should_change_input_method_) {
+ if (chromeos::ChangeInputMethod(input_method_status_connection_,
+ current_input_method_id_.c_str())) {
+ should_change_input_method_ = false;
+ completed = true;
+ active_input_methods_are_changed = true;
+ }
+ } else {
+ completed = true;
}
- } else {
- LOG(ERROR) << "chromeos::SetImeConfig failed. Will retry later: "
- << section << "/" << config_name;
- ++iter; // Do not remove the command.
}
}
- if (pending_config_requests_.empty()) {
+
+ if (completed) {
timer_.Stop(); // no-op if it's not running.
+ } else {
+ // Flush is not completed. Start a timer if it's not yet running.
+ if (!timer_.IsRunning()) {
+ static const int64 kTimerIntervalInMsec = 100;
+ failure_count_ = 0;
+ timer_.Start(base::TimeDelta::FromMilliseconds(kTimerIntervalInMsec),
+ this, &InputMethodLibraryImpl::FlushImeConfig);
+ } else {
+ // The timer is already running. We'll give up if it reaches the
+ // max retry count.
+ static const int kMaxRetries = 15;
+ ++failure_count_;
+ if (failure_count_ > kMaxRetries) {
+ LOG(ERROR) << "FlushImeConfig: Max retries exceeded. "
+ << "current_input_method_id: " << current_input_method_id_
+ << " pending_config_requests.size: "
+ << pending_config_requests_.size();
+ timer_.Stop();
+ }
+ }
}
- } else {
- if (!timer_.IsRunning()) {
- static const int64 kTimerIntervalInSec = 1;
- timer_.Start(base::TimeDelta::FromSeconds(kTimerIntervalInSec), this,
- &InputMethodLibraryImpl::FlushImeConfig);
+ if (active_input_methods_are_changed) {
+ FOR_EACH_OBSERVER(Observer, observers_, ActiveInputMethodsChanged(this));
}
}
- if (active_input_methods_are_changed) {
- FOR_EACH_OBSERVER(Observer, observers_, ActiveInputMethodsChanged(this));
+
+ static void InputMethodChangedHandler(
+ void* object,
+ const chromeos::InputMethodDescriptor& current_input_method) {
+ // The handler is called when the input method method change is
+ // notified via a DBus connection. Since the DBus notificatiosn are
+ // handled in the UI thread, we can assume that this functionalways
+ // runs on the UI thread, but just in case.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ LOG(ERROR) << "Not on UI thread";
+ return;
+ }
+
+ InputMethodLibraryImpl* input_method_library =
+ static_cast<InputMethodLibraryImpl*>(object);
+ input_method_library->ChangeCurrentInputMethod(current_input_method);
}
-}
-// static
-void InputMethodLibraryImpl::InputMethodChangedHandler(
- void* object, const chromeos::InputMethodDescriptor& current_input_method) {
- InputMethodLibraryImpl* input_method_library =
- static_cast<InputMethodLibraryImpl*>(object);
- input_method_library->UpdateCurrentInputMethod(current_input_method);
-}
+ static void RegisterPropertiesHandler(
+ void* object, const ImePropertyList& prop_list) {
+ // See comments in InputMethodChangedHandler.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ LOG(ERROR) << "Not on UI thread";
+ return;
+ }
-// static
-void InputMethodLibraryImpl::RegisterPropertiesHandler(
- void* object, const ImePropertyList& prop_list) {
- InputMethodLibraryImpl* input_method_library =
- static_cast<InputMethodLibraryImpl*>(object);
- input_method_library->RegisterProperties(prop_list);
-}
+ InputMethodLibraryImpl* input_method_library =
+ static_cast<InputMethodLibraryImpl*>(object);
+ input_method_library->RegisterProperties(prop_list);
+ }
-// static
-void InputMethodLibraryImpl::UpdatePropertyHandler(
- void* object, const ImePropertyList& prop_list) {
- InputMethodLibraryImpl* input_method_library =
- static_cast<InputMethodLibraryImpl*>(object);
- input_method_library->UpdateProperty(prop_list);
-}
+ static void UpdatePropertyHandler(
+ void* object, const ImePropertyList& prop_list) {
+ // See comments in InputMethodChangedHandler.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ LOG(ERROR) << "Not on UI thread";
+ return;
+ }
-// static
-void InputMethodLibraryImpl::ConnectionChangeHandler(void* object,
- bool connected) {
- InputMethodLibraryImpl* input_method_library =
- static_cast<InputMethodLibraryImpl*>(object);
- if (connected) {
- input_method_library->pending_config_requests_.insert(
- input_method_library->current_config_values_.begin(),
- input_method_library->current_config_values_.end());
- input_method_library->FlushImeConfig();
+ InputMethodLibraryImpl* input_method_library =
+ static_cast<InputMethodLibraryImpl*>(object);
+ input_method_library->UpdateProperty(prop_list);
}
-}
-bool InputMethodLibraryImpl::EnsureStarted() {
- if (!input_method_status_connection_) {
- input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
- this,
- &InputMethodChangedHandler,
- &RegisterPropertiesHandler,
- &UpdatePropertyHandler,
- &ConnectionChangeHandler);
+ static void ConnectionChangeHandler(void* object, bool connected) {
+ // See comments in InputMethodChangedHandler.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ LOG(ERROR) << "Not on UI thread";
+ return;
+ }
+
+ InputMethodLibraryImpl* input_method_library =
+ static_cast<InputMethodLibraryImpl*>(object);
+ input_method_library->ime_connected_ = connected;
+ if (connected) {
+ input_method_library->pending_config_requests_.clear();
+ input_method_library->pending_config_requests_.insert(
+ input_method_library->current_config_values_.begin(),
+ input_method_library->current_config_values_.end());
+ input_method_library->should_change_input_method_ = true;
+ input_method_library->FlushImeConfig();
+ } else {
+ // Stop attempting to resend config data, since it will continue to fail.
+ input_method_library->timer_.Stop(); // no-op if it's not running.
+ }
}
- return true;
-}
-bool InputMethodLibraryImpl::EnsureLoadedAndStarted() {
- return CrosLibrary::Get()->EnsureLoaded() &&
- EnsureStarted();
-}
+ bool EnsureStarted() {
+ if (!input_method_status_connection_) {
+ input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
+ this,
+ &InputMethodChangedHandler,
+ &RegisterPropertiesHandler,
+ &UpdatePropertyHandler,
+ &ConnectionChangeHandler);
+ }
+ return true;
+ }
-void InputMethodLibraryImpl::UpdateCurrentInputMethod(
- const chromeos::InputMethodDescriptor& new_input_method) {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- DLOG(INFO) << "UpdateCurrentInputMethod (Background thread)";
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- // NewRunnableMethod() copies |new_input_method| by value.
- NewRunnableMethod(
- this, &InputMethodLibraryImpl::UpdateCurrentInputMethod,
- new_input_method));
- return;
- }
-
- DLOG(INFO) << "UpdateCurrentInputMethod (UI thread)";
- // Change the keyboard layout to a preferred layout for the input method.
- CrosLibrary::Get()->GetKeyboardLibrary()->SetCurrentKeyboardLayoutByName(
- new_input_method.keyboard_layout);
-
- if (current_input_method_.id != new_input_method.id) {
- previous_input_method_ = current_input_method_;
- current_input_method_ = new_input_method;
- }
- FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
-}
+ bool EnsureLoadedAndStarted() {
+ return CrosLibrary::Get()->EnsureLoaded() &&
+ EnsureStarted();
+ }
+
+ void ChangeCurrentInputMethod(const InputMethodDescriptor& new_input_method) {
+ // Change the keyboard layout to a preferred layout for the input method.
+ CrosLibrary::Get()->GetKeyboardLibrary()->SetCurrentKeyboardLayoutByName(
+ new_input_method.keyboard_layout);
-void InputMethodLibraryImpl::RegisterProperties(
- const ImePropertyList& prop_list) {
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(
- this, &InputMethodLibraryImpl::RegisterProperties, prop_list));
- return;
+ if (current_input_method_.id != new_input_method.id) {
+ previous_input_method_ = current_input_method_;
+ current_input_method_ = new_input_method;
+ }
+ FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
}
- // |prop_list| might be empty. This means "clear all properties."
- current_ime_properties_ = prop_list;
- FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
-}
+ void RegisterProperties(const ImePropertyList& prop_list) {
+ // |prop_list| might be empty. This means "clear all properties."
+ current_ime_properties_ = prop_list;
+ FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
+ }
+
+ void StartInputMethodProcesses() {
+ should_launch_ime_ = true;
+ MaybeLaunchInputMethodProcesses();
+ }
+
+ void UpdateProperty(const ImePropertyList& prop_list) {
+ for (size_t i = 0; i < prop_list.size(); ++i) {
+ FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
+ }
+ FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
+ }
+
+ // Launches an input method procsess specified by the given command
+ // line. On success, returns true and stores the process ID in
+ // |process_id|. Otherwise, returns false, and the contents of
+ // |process_id| is untouched. OnImeShutdown will be called when the
+ // process terminates.
+ bool LaunchInputMethodProcess(const std::string& command_line,
+ int* process_id) {
+ GError *error = NULL;
+ gchar **argv = NULL;
+ gint argc = NULL;
+ // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so"
+ if (!g_shell_parse_argv(command_line.c_str(), &argc, &argv, &error)) {
+ LOG(ERROR) << "Could not parse command: " << error->message;
+ g_error_free(error);
+ return false;
+ }
+
+ int pid = 0;
+ const GSpawnFlags kFlags = G_SPAWN_DO_NOT_REAP_CHILD;
+ const gboolean result = g_spawn_async(NULL, argv, NULL,
+ kFlags, NULL, NULL,
+ &pid, &error);
+ g_strfreev(argv);
+ if (!result) {
+ LOG(ERROR) << "Could not launch: " << command_line << ": "
+ << error->message;
+ g_error_free(error);
+ return false;
+ }
+ g_child_watch_add(pid, reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
+ this);
+
+ *process_id = pid;
+ return true;
+ }
+
+ // Launches input method processes if these are not yet running.
+ void MaybeLaunchInputMethodProcesses() {
+ if (!should_launch_ime_) {
+ return;
+ }
+
+ if (ibus_daemon_process_id_ == 0) {
+ // TODO(zork): Send output to /var/log/ibus.log
+ const std::string ibus_daemon_command_line =
+ StringPrintf("%s --panel=disable --cache=none --restart --replace",
+ kIBusDaemonPath);
+ if (!LaunchInputMethodProcess(ibus_daemon_command_line,
+ &ibus_daemon_process_id_)) {
+ // On failure, we should not attempt to launch candidate_window.
+ return;
+ }
+ }
+
+ if (candidate_window_process_id_ == 0) {
+ // Pass the UI language info to candidate_window via --lang flag.
+ const std::string candidate_window_command_line =
+ StringPrintf("%s --lang=%s", kCandidateWindowPath,
+ g_browser_process->GetApplicationLocale().c_str());
+ if (!LaunchInputMethodProcess(candidate_window_command_line,
+ &candidate_window_process_id_)) {
+ // Return here just in case we add more code below.
+ return;
+ }
+ }
+ }
+
+ static void OnImeShutdown(int pid,
+ int status,
+ InputMethodLibraryImpl* library) {
+ g_spawn_close_pid(pid);
+ if (library->ibus_daemon_process_id_ == pid) {
+ library->ibus_daemon_process_id_ = 0;
+ } else if (library->candidate_window_process_id_ == pid) {
+ library->candidate_window_process_id_ = 0;
+ }
+
+ // Restart input method processes if needed.
+ library->MaybeLaunchInputMethodProcesses();
+ }
+
+ void StopInputMethodProcesses() {
+ should_launch_ime_ = false;
+ if (ibus_daemon_process_id_) {
+ const std::string xkb_engine_name =
+ chromeos::GetHardwareKeyboardLayoutName();
+ // We should not use chromeos::ChangeInputMethod() here since without the
+ // ibus-daemon process, ChangeCurrentInputMethod() callback function which
+ // actually changes the XKB layout will not be called.
+ CrosLibrary::Get()->GetKeyboardLibrary()->SetCurrentKeyboardLayoutByName(
+ chromeos::input_method::GetKeyboardLayoutName(xkb_engine_name));
+ kill(ibus_daemon_process_id_, SIGTERM);
+ ibus_daemon_process_id_ = 0;
+ }
+ if (candidate_window_process_id_) {
+ kill(candidate_window_process_id_, SIGTERM);
+ candidate_window_process_id_ = 0;
+ }
+ }
+
+ void SetDeferImeStartup(bool defer) {
+ LOG(INFO) << "Setting DeferImeStartup to " << defer;
+ defer_ime_startup_ = defer;
+ }
+
+ // NotificationObserver implementation:
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ // Stop the input processes on browser shutdown.
+ if (type.value == NotificationType::APP_EXITING) {
+ StopInputMethodProcesses();
+ }
+ }
+
+ // A reference to the language api, to allow callbacks when the input method
+ // status changes.
+ InputMethodStatusConnection* input_method_status_connection_;
+ ObserverList<Observer> observers_;
+
+ // The input method which was/is selected.
+ InputMethodDescriptor previous_input_method_;
+ InputMethodDescriptor current_input_method_;
+
+ // The input method properties which the current input method uses. The list
+ // might be empty when no input method is used.
+ ImePropertyList current_ime_properties_;
+
+ typedef std::pair<std::string, std::string> ConfigKeyType;
+ typedef std::map<ConfigKeyType, ImeConfigValue> InputMethodConfigRequests;
+ // SetImeConfig requests that are not yet completed.
+ // Use a map to queue config requests, so we only send the last request for
+ // the same config key (i.e. we'll discard ealier requests for the same
+ // config key). As we discard old requests for the same config key, the order
+ // of requests doesn't matter, so it's safe to use a map.
+ InputMethodConfigRequests pending_config_requests_;
+
+ // Values that have been set via SetImeConfig(). We keep a copy available to
+ // resend if the ime restarts and loses its state.
+ InputMethodConfigRequests current_config_values_;
+
+ // A timer for retrying to send |pendning_config_commands_| to the input
+ // method config daemon.
+ base::OneShotTimer<InputMethodLibraryImpl> timer_;
+
+ // This is used to register this object to APP_EXITING notification.
+ NotificationRegistrar notification_registrar_;
+
+ // True if we should launch the input method processes.
+ bool should_launch_ime_;
+ // True if the connection to the IBus daemon is alive.
+ bool ime_connected_;
+ // If true, we'll defer the startup until a non-default method is
+ // activated.
+ bool defer_ime_startup_;
+ // The ID of the current input method (ex. "mozc").
+ std::string current_input_method_id_;
+ // True if we should change the input method once the queue of the
+ // pending config requests becomes empty.
+ bool should_change_input_method_;
+
+ // The process id of the IBus daemon. 0 if it's not running. The process
+ // ID 0 is not used in Linux, hence it's safe to use 0 for this purpose.
+ int ibus_daemon_process_id_;
+ // The process id of the candidate window. 0 if it's not running.
+ int candidate_window_process_id_;
+ // The failure count of config flush attempts.
+ int failure_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryImpl);
+};
+
+InputMethodLibraryImpl::Observer::~Observer() {}
+
+class InputMethodLibraryStubImpl : public InputMethodLibrary {
+ public:
+ InputMethodLibraryStubImpl()
+ : previous_input_method_("", "", "", ""),
+ current_input_method_("", "", "", "") {
+ }
+
+ ~InputMethodLibraryStubImpl() {}
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+
+ InputMethodDescriptors* GetActiveInputMethods() {
+ return CreateRealisticInputMethodDescriptors();
+ }
+
+
+ size_t GetNumActiveInputMethods() {
+ scoped_ptr<InputMethodDescriptors> descriptors(
+ CreateRealisticInputMethodDescriptors());
+ return descriptors->size();
+ }
+
+ InputMethodDescriptors* GetSupportedInputMethods() {
+ return CreateRealisticInputMethodDescriptors();
+ }
+
+ void ChangeInputMethod(const std::string& input_method_id) {}
+ void SetImePropertyActivated(const std::string& key, bool activated) {}
-void InputMethodLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) {
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(
- this, &InputMethodLibraryImpl::UpdateProperty, prop_list));
- return;
+ bool InputMethodIsActivated(const std::string& input_method_id) {
+ return true;
}
- for (size_t i = 0; i < prop_list.size(); ++i) {
- FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
+ bool GetImeConfig(const char* section,
+ const char* config_name,
+ ImeConfigValue* out_value) {
+ return false;
}
- FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
+
+ bool SetImeConfig(const char* section,
+ const char* config_name,
+ const ImeConfigValue& value) {
+ return false;
+ }
+
+ virtual const InputMethodDescriptor& previous_input_method() const {
+ return previous_input_method_;
+ }
+
+ virtual const InputMethodDescriptor& current_input_method() const {
+ return current_input_method_;
+ }
+
+ virtual const ImePropertyList& current_ime_properties() const {
+ return current_ime_properties_;
+ }
+
+ virtual void StartInputMethodProcesses() {}
+ virtual void StopInputMethodProcesses() {}
+ virtual void SetDeferImeStartup(bool defer) {}
+
+ private:
+ // Creates realistic input method descriptors that can be used for
+ // testing Chrome OS version of chrome on regular Linux desktops.
+ InputMethodDescriptors* CreateRealisticInputMethodDescriptors() {
+ InputMethodDescriptors* descriptions = new InputMethodDescriptors;
+ // The list is created from output of gen_engines.py in libcros.
+ descriptions->push_back(InputMethodDescriptor(
+ "chewing", "Chewing", "us", "zh_TW"));
+ descriptions->push_back(InputMethodDescriptor(
+ "hangul", "Korean", "us", "ko"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:fa:isiri", "isiri (m17n)", "us", "fa"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:he:kbd", "kbd (m17n)", "us", "he"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:ar:kbd", "kbd (m17n)", "us", "ar"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:hi:itrans", "itrans (m17n)", "us", "hi"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:vi:vni", "vni (m17n)", "us", "vi"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:vi:viqr", "viqr (m17n)", "us", "vi"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:vi:tcvn", "tcvn (m17n)", "us", "vi"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:vi:telex", "telex (m17n)", "us", "vi"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:zh:cangjie", "cangjie (m17n)", "us", "zh"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:zh:quick", "quick (m17n)", "us", "zh"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:th:tis820", "tis820 (m17n)", "us", "th"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:th:kesmanee", "kesmanee (m17n)", "us", "th"));
+ descriptions->push_back(InputMethodDescriptor(
+ "m17n:th:pattachote", "pattachote (m17n)", "us", "th"));
+ descriptions->push_back(InputMethodDescriptor(
+ "mozc-jp", "Mozc (Japanese keyboard layout)", "jp", "ja"));
+ descriptions->push_back(InputMethodDescriptor(
+ "mozc", "Mozc (US keyboard layout)", "us", "ja"));
+ descriptions->push_back(InputMethodDescriptor(
+ "mozc-dv", "Mozc (US Dvorak keyboard layout)", "us(dvorak)", "ja"));
+ descriptions->push_back(InputMethodDescriptor(
+ "pinyin", "Pinyin", "us", "zh"));
+ descriptions->push_back(InputMethodDescriptor(
+ "bopomofo", "Bopomofo", "us", "zh"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:us::eng", "USA", "us", "eng"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:us:dvorak:eng", "USA - Dvorak", "us(dvorak)", "eng"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:be::ger", "Belgium", "be", "ger"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:be::nld", "Belgium", "be", "nld"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:be::fra", "Belgium", "be", "fra"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:br::por", "Brazil", "br", "por"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:bg::bul", "Bulgaria", "bg", "bul"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ca::fra", "Canada", "ca", "fra"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ca:eng:eng", "Canada - English", "ca(eng)", "eng"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:hr::scr", "Croatia", "hr", "scr"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:cz::cze", "Czechia", "cz", "cze"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:dk::dan", "Denmark", "dk", "dan"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:nl::nld", "Netherlands", "nl", "nld"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ee::est", "Estonia", "ee", "est"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:fi::fin", "Finland", "fi", "fin"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:fr::fra", "France", "fr", "fra"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:de::ger", "Germany", "de", "ger"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:gr::gre", "Greece", "gr", "gre"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:hu::hun", "Hungary", "hu", "hun"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:it::ita", "Italy", "it", "ita"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:jp::jpn", "Japan", "jp", "jpn"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:lt::lit", "Lithuania", "lt", "lit"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:lv::lav", "Latvia", "lv", "lav"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:no::nor", "Norway", "no", "nor"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:pl::pol", "Poland", "pl", "pol"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:pt::por", "Portugal", "pt", "por"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ro::rum", "Romania", "ro", "rum"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ru::rus", "Russia", "ru", "rus"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:rs::srp", "Serbia", "rs", "srp"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:si::slv", "Slovenia", "si", "slv"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:sk::slo", "Slovakia", "sk", "slo"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:es::spa", "Spain", "es", "spa"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:es:cat:cat",
+ "Spain - Catalan variant with middle-dot L", "es(cat)", "cat"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:se::swe", "Sweden", "se", "swe"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ch::ger", "Switzerland", "ch", "ger"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ch:fr:fra", "Switzerland - French", "ch(fr)", "fra"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:tr::tur", "Turkey", "tr", "tur"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:ua::ukr", "Ukraine", "ua", "ukr"));
+ descriptions->push_back(InputMethodDescriptor(
+ "xkb:gb:extd:eng", "United Kingdom - Extended - Winkeys", "gb(extd)",
+ "eng"));
+ return descriptions;
+ }
+
+ InputMethodDescriptor previous_input_method_;
+ InputMethodDescriptor current_input_method_;
+ ImePropertyList current_ime_properties_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryStubImpl);
+};
+
+// static
+InputMethodLibrary* InputMethodLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new InputMethodLibraryStubImpl();
+ else
+ return new InputMethodLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl);
diff --git a/chrome/browser/chromeos/cros/input_method_library.h b/chrome/browser/chromeos/cros/input_method_library.h
index e92b311..2ae4b85 100644
--- a/chrome/browser/chromeos/cros/input_method_library.h
+++ b/chrome/browser/chromeos/cros/input_method_library.h
@@ -4,8 +4,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_INPUT_METHOD_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_INPUT_METHOD_LIBRARY_H_
+#pragma once
-#include <map>
#include <string>
#include <utility>
@@ -18,18 +18,27 @@ namespace chromeos {
// This class handles the interaction with the ChromeOS language library APIs.
// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: InputMethodLibrary::Get()
+// library class like this:
+// chromeos::CrosLibrary::Get()->GetInputMethodLibrary()
class InputMethodLibrary {
public:
class Observer {
public:
virtual ~Observer() = 0;
+ // Called when the current input method is changed.
virtual void InputMethodChanged(InputMethodLibrary* obj) = 0;
+
+ // Called when input method properties (see chromeos_input_method.h
+ // for details) are changed.
virtual void ImePropertiesChanged(InputMethodLibrary* obj) = 0;
+
+ // Called when the active input methods are changed.
virtual void ActiveInputMethodsChanged(InputMethodLibrary* obj) = 0;
};
virtual ~InputMethodLibrary() {}
+ // Adds an observer to receive notifications of input method related
+ // changes as desribed in the Observer class above.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
@@ -76,124 +85,31 @@ class InputMethodLibrary {
// the request and returns false.
// You can specify |section| and |config_name| arguments in the same way
// as GetImeConfig() above.
+ // Notice: This function might call the Observer::ActiveInputMethodsChanged()
+ // callback function immediately, before returning from the SetImeConfig
+ // function. See also http://crosbug.com/5217.
virtual bool SetImeConfig(const char* section,
const char* config_name,
const ImeConfigValue& value) = 0;
+ // Sets the IME state to enabled, and launches its processes if needed.
+ virtual void StartInputMethodProcesses() = 0;
+
+ // Disables the IME, and kills the processes if they are running.
+ virtual void StopInputMethodProcesses() = 0;
+
+ // Controls whether the IME process is started when preload engines are
+ // specificed, or defered until a non-default method is activated.
+ virtual void SetDeferImeStartup(bool defer) = 0;
+
virtual const InputMethodDescriptor& previous_input_method() const = 0;
virtual const InputMethodDescriptor& current_input_method() const = 0;
virtual const ImePropertyList& current_ime_properties() const = 0;
-};
-// This class handles the interaction with the ChromeOS language library APIs.
-// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: InputMethodLibrary::Get()
-class InputMethodLibraryImpl : public InputMethodLibrary {
- public:
- InputMethodLibraryImpl();
- virtual ~InputMethodLibraryImpl();
-
- // InputMethodLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
- virtual InputMethodDescriptors* GetActiveInputMethods();
- virtual size_t GetNumActiveInputMethods();
- virtual InputMethodDescriptors* GetSupportedInputMethods();
- virtual void ChangeInputMethod(const std::string& input_method_id);
- virtual void SetImePropertyActivated(const std::string& key,
- bool activated);
- virtual bool InputMethodIsActivated(const std::string& input_method_id);
- virtual bool GetImeConfig(
- const char* section, const char* config_name, ImeConfigValue* out_value);
- virtual bool SetImeConfig(const char* section,
- const char* config_name,
- const ImeConfigValue& value);
-
- virtual const InputMethodDescriptor& previous_input_method() const {
- return previous_input_method_;
- }
- virtual const InputMethodDescriptor& current_input_method() const {
- return current_input_method_;
- }
-
- virtual const ImePropertyList& current_ime_properties() const {
- return current_ime_properties_;
- }
-
- private:
- // This method is called when there's a change in input method status.
- static void InputMethodChangedHandler(
- void* object, const InputMethodDescriptor& current_input_method);
-
- // This method is called when an input method sends "RegisterProperties"
- // signal.
- static void RegisterPropertiesHandler(
- void* object, const ImePropertyList& prop_list);
-
- // This method is called when an input method sends "UpdateProperty" signal.
- static void UpdatePropertyHandler(
- void* object, const ImePropertyList& prop_list);
-
- // This method is called when bus connects or disconnects.
- static void ConnectionChangeHandler(void* object, bool connected);
-
- // Ensures that the monitoring of input method changes is started. Starts
- // the monitoring if necessary. Returns true if the monitoring has been
- // successfully started.
- bool EnsureStarted();
-
- // Ensures that the cros library is loaded and the the monitoring is
- // started. Loads the cros library and starts the monitoring if
- // necessary. Returns true if the two conditions are both met.
- bool EnsureLoadedAndStarted();
-
- // Called by the handler to update the input method status.
- // This will notify all the Observers.
- void UpdateCurrentInputMethod(
- const InputMethodDescriptor& current_input_method);
-
- // Called by the handler to register input method properties.
- void RegisterProperties(const ImePropertyList& prop_list);
-
- // Called by the handler to update input method properties.
- void UpdateProperty(const ImePropertyList& prop_list);
-
- // Tries to send all pending SetImeConfig requests to the input method config
- // daemon.
- void FlushImeConfig();
-
- // A reference to the language api, to allow callbacks when the input method
- // status changes.
- InputMethodStatusConnection* input_method_status_connection_;
- ObserverList<Observer> observers_;
-
- // The input method which was/is selected.
- InputMethodDescriptor previous_input_method_;
- InputMethodDescriptor current_input_method_;
-
- // The input method properties which the current input method uses. The list
- // might be empty when no input method is used.
- ImePropertyList current_ime_properties_;
-
- typedef std::pair<std::string, std::string> ConfigKeyType;
- typedef std::map<ConfigKeyType, ImeConfigValue> InputMethodConfigRequests;
- // SetImeConfig requests that are not yet completed.
- // Use a map to queue config requests, so we only send the last request for
- // the same config key (i.e. we'll discard ealier requests for the same
- // config key). As we discard old requests for the same config key, the order
- // of requests doesn't matter, so it's safe to use a map.
- InputMethodConfigRequests pending_config_requests_;
-
- // Values that have been set via SetImeConfig(). We keep a copy available to
- // resend if the ime restarts and loses its state.
- InputMethodConfigRequests current_config_values_;
-
- // A timer for retrying to send |pendning_config_commands_| to the input
- // method config daemon.
- base::OneShotTimer<InputMethodLibraryImpl> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(InputMethodLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static InputMethodLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/keyboard_library.cc b/chrome/browser/chromeos/cros/keyboard_library.cc
index ff7a3b1..c7728c1 100644
--- a/chrome/browser/chromeos/cros/keyboard_library.cc
+++ b/chrome/browser/chromeos/cros/keyboard_library.cc
@@ -9,34 +9,140 @@
namespace chromeos {
-std::string KeyboardLibraryImpl::GetCurrentKeyboardLayoutName() const {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- return chromeos::GetCurrentKeyboardLayoutName();
+class KeyboardLibraryImpl : public KeyboardLibrary {
+ public:
+ KeyboardLibraryImpl() {}
+ virtual ~KeyboardLibraryImpl() {}
+
+ std::string GetHardwareKeyboardLayoutName() const {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::GetHardwareKeyboardLayoutName();
+ }
+ return "";
}
- return "";
-}
-bool KeyboardLibraryImpl::SetCurrentKeyboardLayoutByName(
- const std::string& layout_name) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- return chromeos::SetCurrentKeyboardLayoutByName(layout_name);
+ std::string GetCurrentKeyboardLayoutName() const {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::GetCurrentKeyboardLayoutName();
+ }
+ return "";
}
- return false;
-}
-bool KeyboardLibraryImpl::GetKeyboardLayoutPerWindow(
- bool* is_per_window) const {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- return chromeos::GetKeyboardLayoutPerWindow(is_per_window);
+ bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::SetCurrentKeyboardLayoutByName(layout_name);
+ }
+ return false;
}
- return false;
-}
-bool KeyboardLibraryImpl::SetKeyboardLayoutPerWindow(bool is_per_window) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- return chromeos::SetKeyboardLayoutPerWindow(is_per_window);
+ bool RemapModifierKeys(const ModifierMap& modifier_map) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::RemapModifierKeys(modifier_map);
+ }
+ return false;
+ }
+
+ bool GetKeyboardLayoutPerWindow(bool* is_per_window) const {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::GetKeyboardLayoutPerWindow(is_per_window);
+ }
+ return false;
+ }
+
+ bool SetKeyboardLayoutPerWindow(bool is_per_window) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::SetKeyboardLayoutPerWindow(is_per_window);
+ }
+ return false;
+ }
+
+ bool GetAutoRepeatEnabled(bool* enabled) const {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::GetAutoRepeatEnabled(enabled);
+ }
+ return false;
+ }
+
+ bool SetAutoRepeatEnabled(bool enabled) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::SetAutoRepeatEnabled(enabled);
+ }
+ return false;
+ }
+
+ bool GetAutoRepeatRate(AutoRepeatRate* out_rate) const {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::GetAutoRepeatRate(out_rate);
+ }
+ return false;
+ }
+
+ bool SetAutoRepeatRate(const AutoRepeatRate& rate) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ return chromeos::SetAutoRepeatRate(rate);
+ }
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeyboardLibraryImpl);
+};
+
+class KeyboardLibraryStubImpl : public KeyboardLibrary {
+ public:
+ KeyboardLibraryStubImpl() {}
+ virtual ~KeyboardLibraryStubImpl() {}
+
+ std::string GetHardwareKeyboardLayoutName() const {
+ return "xkb:us::eng";
}
- return false;
+
+ std::string GetCurrentKeyboardLayoutName() const {
+ return "";
+ }
+
+ bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) {
+ return false;
+ }
+
+ bool RemapModifierKeys(const ModifierMap& modifier_map) {
+ return false;
+ }
+
+ bool GetKeyboardLayoutPerWindow(bool* is_per_window) const {
+ return false;
+ }
+
+ bool SetKeyboardLayoutPerWindow(bool is_per_window) {
+ return false;
+ }
+
+ bool GetAutoRepeatEnabled(bool* enabled) const {
+ return false;
+ }
+
+ bool SetAutoRepeatEnabled(bool enabled) {
+ return false;
+ }
+
+ bool GetAutoRepeatRate(AutoRepeatRate* out_rate) const {
+ return false;
+ }
+
+ bool SetAutoRepeatRate(const AutoRepeatRate& rate) {
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeyboardLibraryStubImpl);
+};
+
+// static
+KeyboardLibrary* KeyboardLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new KeyboardLibraryStubImpl();
+ else
+ return new KeyboardLibraryImpl();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/keyboard_library.h b/chrome/browser/chromeos/cros/keyboard_library.h
index 17e1b42..b5f0deb 100644
--- a/chrome/browser/chromeos/cros/keyboard_library.h
+++ b/chrome/browser/chromeos/cros/keyboard_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_KEYBOARD_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_KEYBOARD_LIBRARY_H_
+#pragma once
#include "cros/chromeos_keyboard.h"
@@ -18,6 +19,9 @@ class KeyboardLibrary {
public:
virtual ~KeyboardLibrary() {}
+ // Returns the hardware layout name like "xkb:us::eng". On error, returns "".
+ virtual std::string GetHardwareKeyboardLayoutName() const = 0;
+
// Returns the current layout name like "us". On error, returns "".
virtual std::string GetCurrentKeyboardLayoutName() const = 0;
@@ -26,6 +30,9 @@ class KeyboardLibrary {
virtual bool SetCurrentKeyboardLayoutByName(
const std::string& layout_name) = 0;
+ // Remaps modifier keys. Returns true on success.
+ virtual bool RemapModifierKeys(const ModifierMap& modifier_map) = 0;
+
// Gets whehter we have separate keyboard layout per window, or not. The
// result is stored in |is_per_window|. Returns true on success.
virtual bool GetKeyboardLayoutPerWindow(bool* is_per_window) const = 0;
@@ -34,21 +41,25 @@ class KeyboardLibrary {
// is given, the same keyboard layout will be shared for all applications.
// Returns true on success.
virtual bool SetKeyboardLayoutPerWindow(bool is_per_window) = 0;
-};
-class KeyboardLibraryImpl : public KeyboardLibrary {
- public:
- KeyboardLibraryImpl() {}
- virtual ~KeyboardLibraryImpl() {}
+ // Gets the current auto-repeat mode of the keyboard. The result is stored in
+ // |enabled|. Returns true on success.
+ virtual bool GetAutoRepeatEnabled(bool* enabled) const = 0;
+
+ // Turns on and off the auto-repeat of the keyboard. Returns true on success.
+ virtual bool SetAutoRepeatEnabled(bool enabled) = 0;
+
+ // Gets the current auto-repeat rate of the keyboard. The result is stored in
+ // |out_rate|. Returns true on success.
+ virtual bool GetAutoRepeatRate(AutoRepeatRate* out_rate) const = 0;
- // KeyboardLibrary overrides.
- virtual std::string GetCurrentKeyboardLayoutName() const;
- virtual bool SetCurrentKeyboardLayoutByName(const std::string& layout_name);
- virtual bool GetKeyboardLayoutPerWindow(bool* is_per_window) const;
- virtual bool SetKeyboardLayoutPerWindow(bool is_per_window);
+ // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat
+ // interval in ms. Returns true on success.
+ virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(KeyboardLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static KeyboardLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/login_library.cc b/chrome/browser/chromeos/cros/login_library.cc
index efd8536..4b57d44 100644
--- a/chrome/browser/chromeos/cros/login_library.cc
+++ b/chrome/browser/chromeos/cros/login_library.cc
@@ -10,19 +10,227 @@
namespace chromeos {
-bool LoginLibraryImpl::EmitLoginPromptReady() {
- return chromeos::EmitLoginPromptReady();
-}
+class LoginLibraryImpl : public LoginLibrary {
+ public:
+ LoginLibraryImpl()
+ : set_owner_key_callback_(NULL),
+ whitelist_op_callback_(NULL),
+ property_op_callback_(NULL) {
+ if (CrosLibrary::Get()->EnsureLoaded())
+ Init();
+ }
+ virtual ~LoginLibraryImpl() {
+ if (session_connection_) {
+ chromeos::DisconnectSession(session_connection_);
+ }
+ }
-bool LoginLibraryImpl::StartSession(const std::string& user_email,
- const std::string& unique_id /* unused */) {
- // only pass unique_id through once we use it for something.
- return chromeos::StartSession(user_email.c_str(), "");
-}
+ bool EmitLoginPromptReady() {
+ return chromeos::EmitLoginPromptReady();
+ }
+
+ bool CheckWhitelist(const std::string& email,
+ std::vector<uint8>* OUT_signature) {
+ return chromeos::CheckWhitelist(email.c_str(), OUT_signature);
+ }
+
+ bool RetrieveProperty(const std::string& name,
+ std::string* OUT_value,
+ std::vector<uint8>* OUT_signature) {
+ return chromeos::RetrieveProperty(name.c_str(), OUT_value, OUT_signature);
+ }
+
+ bool SetOwnerKeyAsync(const std::vector<uint8>& public_key_der,
+ Delegate* callback) {
+ DCHECK(callback) << "must provide a callback to SetOwnerKeyAsync()";
+ if (set_owner_key_callback_)
+ return false;
+ set_owner_key_callback_ = callback;
+ return chromeos::SetOwnerKey(public_key_der);
+ }
+
+ bool StorePropertyAsync(const std::string& name,
+ const std::string& value,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ DCHECK(callback) << "must provide a callback to StorePropertyAsync()";
+ if (property_op_callback_)
+ return false;
+ property_op_callback_ = callback;
+ return chromeos::StoreProperty(name.c_str(), value.c_str(), signature);
+ }
+
+ bool UnwhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ DCHECK(callback) << "must provide a callback to UnwhitelistAsync()";
+ if (whitelist_op_callback_)
+ return false;
+ whitelist_op_callback_ = callback;
+ return chromeos::Unwhitelist(email.c_str(), signature);
+ }
+
+ bool WhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ DCHECK(callback) << "must provide a callback to WhitelistAsync()";
+ if (whitelist_op_callback_)
+ return false;
+ whitelist_op_callback_ = callback;
+ return chromeos::Whitelist(email.c_str(), signature);
+ }
+
+ bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) {
+ return chromeos::EnumerateWhitelisted(whitelisted);
+ }
+
+ bool StartSession(const std::string& user_email,
+ const std::string& unique_id /* unused */) {
+ // only pass unique_id through once we use it for something.
+ return chromeos::StartSession(user_email.c_str(), "");
+ }
+
+ bool StopSession(const std::string& unique_id /* unused */) {
+ // only pass unique_id through once we use it for something.
+ return chromeos::StopSession("");
+ }
+
+ bool RestartJob(int pid, const std::string& command_line) {
+ return chromeos::RestartJob(pid, command_line.c_str());
+ }
+
+ private:
+ static void Handler(void* object, const OwnershipEvent& event) {
+ LoginLibraryImpl* self = static_cast<LoginLibraryImpl*>(object);
+ switch (event) {
+ case SetKeySuccess:
+ self->CompleteSetOwnerKey(true);
+ break;
+ case SetKeyFailure:
+ self->CompleteSetOwnerKey(false);
+ break;
+ case WhitelistOpSuccess:
+ self->CompleteWhitelistOp(true);
+ break;
+ case WhitelistOpFailure:
+ self->CompleteWhitelistOp(false);
+ break;
+ case PropertyOpSuccess:
+ self->CompletePropertyOp(true);
+ break;
+ case PropertyOpFailure:
+ self->CompletePropertyOp(false);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ void Init() {
+ session_connection_ = chromeos::MonitorSession(&Handler, this);
+ }
+
+ void CompleteSetOwnerKey(bool result) {
+ CHECK(set_owner_key_callback_) << "CompleteSetOwnerKey() called without "
+ "a registered callback!";
+ set_owner_key_callback_->OnComplete(result);
+ set_owner_key_callback_ = NULL;
+ }
+
+ void CompleteWhitelistOp(bool result) {
+ CHECK(whitelist_op_callback_);
+ whitelist_op_callback_->OnComplete(result);
+ whitelist_op_callback_ = NULL;
+ }
+
+ void CompletePropertyOp(bool result) {
+ CHECK(property_op_callback_);
+ property_op_callback_->OnComplete(result);
+ property_op_callback_ = NULL;
+ }
+
+ chromeos::SessionConnection session_connection_;
+
+ Delegate* set_owner_key_callback_;
+ Delegate* whitelist_op_callback_;
+ Delegate* property_op_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoginLibraryImpl);
+};
+
+class LoginLibraryStubImpl : public LoginLibrary {
+ public:
+ LoginLibraryStubImpl() {}
+ virtual ~LoginLibraryStubImpl() {}
+
+ bool EmitLoginPromptReady() { return true; }
+ bool CheckWhitelist(const std::string& email,
+ std::vector<uint8>* OUT_signature) {
+ OUT_signature->assign(2, 0);
+ return true;
+ }
+ bool RetrieveProperty(const std::string& name,
+ std::string* OUT_value,
+ std::vector<uint8>* OUT_signature) {
+ OUT_value->assign("stub");
+ OUT_signature->assign(2, 0);
+ return true;
+ }
+ bool SetOwnerKeyAsync(const std::vector<uint8>& public_key_der,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+ bool StorePropertyAsync(const std::string& name,
+ const std::string& value,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+ bool UnwhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+ bool WhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(&DoStubCallback, callback));
+ return true;
+ }
+ bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) {
+ return true;
+ }
+ bool StartSession(const std::string& user_email,
+ const std::string& unique_id /* unused */) { return true; }
+ bool StopSession(const std::string& unique_id /* unused */) { return true; }
+ bool RestartJob(int pid, const std::string& command_line) { return true; }
+
+ private:
+ static void DoStubCallback(Delegate* callback) {
+ callback->OnComplete(true);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(LoginLibraryStubImpl);
+};
-bool LoginLibraryImpl::StopSession(const std::string& unique_id /* unused */) {
- // only pass unique_id through once we use it for something.
- return chromeos::StopSession("");
+// static
+LoginLibrary* LoginLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new LoginLibraryStubImpl();
+ else
+ return new LoginLibraryImpl();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/login_library.h b/chrome/browser/chromeos/cros/login_library.h
index 3e8936f..fc9b11a 100644
--- a/chrome/browser/chromeos/cros/login_library.h
+++ b/chrome/browser/chromeos/cros/login_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_LOGIN_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_LOGIN_LIBRARY_H_
+#pragma once
#include <string>
@@ -15,10 +16,72 @@ namespace chromeos {
// This interface defines the interaction with the ChromeOS login library APIs.
class LoginLibrary {
public:
+ class Delegate {
+ public:
+ virtual void OnComplete(bool value) = 0;
+ };
+
virtual ~LoginLibrary() {}
// Requests that the Upstart signal login-prompt-ready be emitted.
virtual bool EmitLoginPromptReady() = 0;
+ // Check whether or not |email| is present on the whitelist.
+ // If so, we return true and store the signature passed when |email| was
+ // whitelisted in |OUT_signature|.
+ // If not, we return false and don't touch the output parameter.
+ virtual bool CheckWhitelist(const std::string& email,
+ std::vector<uint8>* OUT_signature) = 0;
+
+ // Fetch the value associated with |name|, if its present.
+ // If so, we return true, store the info in |OUT_value|, and store the
+ // signature passed when the property was initially stored in |OUT_signature|.
+ // If not, we return false and don't touch the output parameters.
+ virtual bool RetrieveProperty(const std::string& name,
+ std::string* OUT_value,
+ std::vector<uint8>* OUT_signature) = 0;
+
+ // Attempts to asynchronously set the provided public key as the
+ // Owner's public key for this device. |public_key_der| should be a
+ // DER-encoded PKCS11 SubjectPublicKeyInfo structure.
+ // Returns true if the attempt was successfully started.
+ // callback->Run() will be called when the operation is complete.
+ virtual bool SetOwnerKeyAsync(const std::vector<uint8>& public_key_der,
+ Delegate* callback) = 0;
+
+ // Attempts to issue a signed async request to store |name|=|value|.
+ // |signature| must by a SHA1 with RSA encryption signature over the string
+ // "name=value" with the owner's private key.
+ // Returns true if the attempt was successfully started.
+ // callback->Run() will be called when the operation is complete.
+ virtual bool StorePropertyAsync(const std::string& name,
+ const std::string& value,
+ const std::vector<uint8>& signature,
+ Delegate* callback) = 0;
+
+ // Attempts to issue a signed async request to whitelist |email|.
+ // |signature| must by a SHA1 with RSA encryption signature over |email|
+ // with the owner's private key.
+ // Returns true if the attempt was successfully started.
+ // callback->Run() will be called when the operation is complete.
+ virtual bool WhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) = 0;
+
+ // Attempts to issue a signed async request to remove |email| from the
+ // whitelist of users allowed to log in to this machine.
+ // |signature| must by a SHA1 with RSA encryption signature over |email|
+ // with the owner's private key.
+ // Returns true if the attempt was successfully started.
+ // callback->Run() will be called when the operation is complete.
+ virtual bool UnwhitelistAsync(const std::string& email,
+ const std::vector<uint8>& signature,
+ Delegate* callback) = 0;
+
+ // Retrieves the user white list. Note the call is for display purpose only.
+ // To determine if an email is white listed, you MUST use CheckWhitelist.
+ // Returns true if the request is successfully dispatched.
+ virtual bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) = 0;
+
// Tells the session manager to start a logged-in session for the user
// |user_email|. |unique_id| is meant to be used when we have a non-human-
// readable unique identifier by which we distinguish users (to deal with
@@ -31,22 +94,13 @@ class LoginLibrary {
// This will tell the session manager to terminate the session for the user
// indicated by |unique_id|.
virtual bool StopSession(const std::string& unique_id /* unused */) = 0;
-};
-// This class handles the interaction with the ChromeOS login library APIs.
-class LoginLibraryImpl : public LoginLibrary {
- public:
- LoginLibraryImpl() {}
- virtual ~LoginLibraryImpl() {}
-
- // LoginLibrary overrides.
- virtual bool EmitLoginPromptReady();
- virtual bool StartSession(const std::string& user_email,
- const std::string& unique_id /* unused */);
- virtual bool StopSession(const std::string& unique_id /* unused */);
+ // Restarts the job with specified command line string.
+ virtual bool RestartJob(int pid, const std::string& command_line) = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(LoginLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static LoginLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/mock_cros_library.h b/chrome/browser/chromeos/cros/mock_cros_library.h
index f66cc67..19434fe 100644
--- a/chrome/browser/chromeos/cros/mock_cros_library.h
+++ b/chrome/browser/chromeos/cros/mock_cros_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_CROS_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_CROS_LIBRARY_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/cros/mock_cryptohome_library.h b/chrome/browser/chromeos/cros/mock_cryptohome_library.h
index 664f88a..c579418 100644
--- a/chrome/browser/chromeos/cros/mock_cryptohome_library.h
+++ b/chrome/browser/chromeos/cros/mock_cryptohome_library.h
@@ -4,30 +4,79 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_CRYPTOHOME_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_CRYPTOHOME_LIBRARY_H_
+#pragma once
#include <string>
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "testing/gmock/include/gmock/gmock.h"
+using ::testing::Invoke;
+using ::testing::WithArgs;
+using ::testing::_;
+
namespace chromeos {
class MockCryptohomeLibrary : public CryptohomeLibrary {
public:
- MockCryptohomeLibrary() {}
+ MockCryptohomeLibrary() {
+ ON_CALL(*this, AsyncCheckKey(_, _, _))
+ .WillByDefault(
+ WithArgs<2>(Invoke(this, &MockCryptohomeLibrary::DoCallback)));
+ ON_CALL(*this, AsyncMigrateKey(_, _, _, _))
+ .WillByDefault(
+ WithArgs<3>(Invoke(this, &MockCryptohomeLibrary::DoCallback)));
+ ON_CALL(*this, AsyncMount(_, _, _, _))
+ .WillByDefault(
+ WithArgs<3>(Invoke(this, &MockCryptohomeLibrary::DoCallback)));
+ ON_CALL(*this, AsyncMountForBwsi(_))
+ .WillByDefault(
+ WithArgs<0>(Invoke(this, &MockCryptohomeLibrary::DoCallback)));
+ ON_CALL(*this, AsyncRemove(_, _))
+ .WillByDefault(
+ WithArgs<1>(Invoke(this, &MockCryptohomeLibrary::DoCallback)));
+ }
virtual ~MockCryptohomeLibrary() {}
- MOCK_METHOD3(Mount, bool(const std::string& user_email,
- const std::string& passhash,
- int* error_code));
- MOCK_METHOD1(MountForBwsi, bool(int*));
MOCK_METHOD2(CheckKey, bool(const std::string& user_email,
const std::string& passhash));
+ MOCK_METHOD3(AsyncCheckKey, bool(const std::string& user_email,
+ const std::string& passhash,
+ Delegate* callback));
MOCK_METHOD3(MigrateKey, bool(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash));
+ MOCK_METHOD4(AsyncMigrateKey, bool(const std::string& user_email,
+ const std::string& old_hash,
+ const std::string& new_hash,
+ Delegate* callback));
+ MOCK_METHOD3(Mount, bool(const std::string& user_email,
+ const std::string& passhash,
+ int* error_code));
+ MOCK_METHOD4(AsyncMount, bool(const std::string& user_email,
+ const std::string& passhash,
+ const bool create_if_missing,
+ Delegate* callback));
+ MOCK_METHOD1(MountForBwsi, bool(int*));
+ MOCK_METHOD1(AsyncMountForBwsi, bool(Delegate* callback));
MOCK_METHOD1(Remove, bool(const std::string& user_email));
+ MOCK_METHOD2(AsyncRemove, bool(const std::string& user_email, Delegate* d));
MOCK_METHOD0(IsMounted, bool(void));
MOCK_METHOD0(GetSystemSalt, CryptohomeBlob(void));
+
+ void SetAsyncBehavior(bool outcome, int code) {
+ outcome_ = outcome;
+ code_ = code;
+ }
+
+ bool DoCallback(Delegate* d) {
+ d->OnComplete(outcome_, code_);
+ return true;
+ }
+
+ private:
+ bool outcome_;
+ int code_;
+ DISALLOW_COPY_AND_ASSIGN(MockCryptohomeLibrary);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/mock_input_method_library.h b/chrome/browser/chromeos/cros/mock_input_method_library.h
index ccd0387..4cbd1c8 100644
--- a/chrome/browser/chromeos/cros/mock_input_method_library.h
+++ b/chrome/browser/chromeos/cros/mock_input_method_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_INPUT_METHOD_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_INPUT_METHOD_LIBRARY_H_
+#pragma once
#include <string>
@@ -32,9 +33,11 @@ class MockInputMethodLibrary : public InputMethodLibrary {
MOCK_CONST_METHOD0(previous_input_method, const InputMethodDescriptor&(void));
MOCK_CONST_METHOD0(current_input_method, const InputMethodDescriptor&(void));
MOCK_CONST_METHOD0(current_ime_properties, const ImePropertyList&(void));
+ MOCK_METHOD0(StartInputMethodProcesses, void(void));
+ MOCK_METHOD0(StopInputMethodProcesses, void(void));
+ MOCK_METHOD1(SetDeferImeStartup, void(bool));
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CROS_MOCK_INPUT_METHOD_LIBRARY_H_
-
diff --git a/chrome/browser/chromeos/cros/mock_keyboard_library.h b/chrome/browser/chromeos/cros/mock_keyboard_library.h
index 67bcdce..f36d74f 100644
--- a/chrome/browser/chromeos/cros/mock_keyboard_library.h
+++ b/chrome/browser/chromeos/cros/mock_keyboard_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_KEYBOARD_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_KEYBOARD_LIBRARY_H_
+#pragma once
#include <string>
@@ -17,10 +18,16 @@ class MockKeyboardLibrary : public KeyboardLibrary {
MockKeyboardLibrary() {}
virtual ~MockKeyboardLibrary() {}
+ MOCK_CONST_METHOD0(GetHardwareKeyboardLayoutName, std::string(void));
MOCK_CONST_METHOD0(GetCurrentKeyboardLayoutName, std::string(void));
MOCK_METHOD1(SetCurrentKeyboardLayoutByName, bool(const std::string&));
+ MOCK_METHOD1(RemapModifierKeys, bool(const ModifierMap&));
MOCK_CONST_METHOD1(GetKeyboardLayoutPerWindow, bool(bool*));
MOCK_METHOD1(SetKeyboardLayoutPerWindow, bool(bool));
+ MOCK_CONST_METHOD1(GetAutoRepeatEnabled, bool(bool*));
+ MOCK_METHOD1(SetAutoRepeatEnabled, bool(bool));
+ MOCK_CONST_METHOD1(GetAutoRepeatRate, bool(AutoRepeatRate*));
+ MOCK_METHOD1(SetAutoRepeatRate, bool(const AutoRepeatRate&));
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/mock_library_loader.h b/chrome/browser/chromeos/cros/mock_library_loader.h
index 5863a54..1e4a440 100644
--- a/chrome/browser/chromeos/cros/mock_library_loader.h
+++ b/chrome/browser/chromeos/cros/mock_library_loader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_LIBRARY_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_LIBRARY_LOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/cros/mock_login_library.h b/chrome/browser/chromeos/cros/mock_login_library.h
index 51096bf..43a77b4 100644
--- a/chrome/browser/chromeos/cros/mock_login_library.h
+++ b/chrome/browser/chromeos/cros/mock_login_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_LOGIN_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_LOGIN_LIBRARY_H_
+#pragma once
#include <string>
@@ -16,13 +17,28 @@ class MockLoginLibrary : public LoginLibrary {
public:
MockLoginLibrary() {}
virtual ~MockLoginLibrary() {}
+ MOCK_METHOD2(CheckWhitelist, bool(const std::string&, std::vector<uint8>*));
MOCK_METHOD0(EmitLoginPromptReady, bool(void));
+ MOCK_METHOD1(EnumerateWhitelisted, bool(std::vector<std::string>*));
+ MOCK_METHOD3(RetrieveProperty, bool(const std::string&,
+ std::string*,
+ std::vector<uint8>*));
+ MOCK_METHOD2(SetOwnerKeyAsync, bool(const std::vector<uint8>&, Delegate*));
+ MOCK_METHOD4(StorePropertyAsync, bool(const std::string&,
+ const std::string&,
+ const std::vector<uint8>&,
+ Delegate*));
+ MOCK_METHOD3(UnwhitelistAsync, bool(const std::string&,
+ const std::vector<uint8>&,
+ Delegate*));
+ MOCK_METHOD3(WhitelistAsync, bool(const std::string&,
+ const std::vector<uint8>&,
+ Delegate*));
MOCK_METHOD2(StartSession, bool(const std::string&, const std::string&));
- MOCK_METHOD1(StartSession, bool(const std::string&));
MOCK_METHOD1(StopSession, bool(const std::string&));
+ MOCK_METHOD2(RestartJob, bool(int, const std::string&));
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CROS_MOCK_LOGIN_LIBRARY_H_
-
diff --git a/chrome/browser/chromeos/cros/mock_mount_library.h b/chrome/browser/chromeos/cros/mock_mount_library.h
index e0309ea..32a52c2 100644
--- a/chrome/browser/chromeos/cros/mock_mount_library.h
+++ b/chrome/browser/chromeos/cros/mock_mount_library.h
@@ -1,25 +1,22 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_MOUNT_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_MOUNT_LIBRARY_H_
+#pragma once
#include <string>
-#include <vector>
#include "base/observer_list.h"
#include "base/time.h"
-#include "cros/chromeos_mount.h"
#include "chrome/browser/chromeos/cros/mount_library.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "cros/chromeos_mount.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
-// This class handles the interaction with the ChromeOS mount library APIs.
-// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: MountLibrary::Get().
class MockMountLibrary : public MountLibrary {
public:
MockMountLibrary();
diff --git a/chrome/browser/chromeos/cros/mock_network_library.h b/chrome/browser/chromeos/cros/mock_network_library.h
index ee87358..823cd5b 100644
--- a/chrome/browser/chromeos/cros/mock_network_library.h
+++ b/chrome/browser/chromeos/cros/mock_network_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_NETWORK_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_NETWORK_LIBRARY_H_
+#pragma once
#include <string>
@@ -49,9 +50,6 @@ class MockNetworkLibrary : public NetworkLibrary {
MOCK_METHOD0(RequestWifiScan, void(void));
MOCK_METHOD0(UpdateSystemInfo, void(void));
MOCK_METHOD1(GetWifiAccessPoints, bool(WifiAccessPointVector*));
- MOCK_METHOD0(ConnectToPreferredNetworkIfAvailable, bool(void));
- MOCK_METHOD0(PreferredNetworkConnected, bool(void));
- MOCK_METHOD0(PreferredNetworkFailed, bool(void));
MOCK_METHOD4(ConnectToWifiNetwork, void(WifiNetwork,
const std::string&,
const std::string&,
@@ -65,7 +63,7 @@ class MockNetworkLibrary : public NetworkLibrary {
MOCK_METHOD1(DisconnectFromWirelessNetwork, void(const WirelessNetwork&));
MOCK_METHOD1(SaveCellularNetwork, void(const CellularNetwork&));
MOCK_METHOD1(SaveWifiNetwork, void(const WifiNetwork&));
- MOCK_METHOD1(ForgetWirelessNetwork, void(const WirelessNetwork&));
+ MOCK_METHOD1(ForgetWirelessNetwork, void(const std::string&));
MOCK_CONST_METHOD0(ethernet_available, bool(void));
MOCK_CONST_METHOD0(wifi_available, bool(void));
diff --git a/chrome/browser/chromeos/cros/mock_power_library.h b/chrome/browser/chromeos/cros/mock_power_library.h
index 4b57538..fae5521 100644
--- a/chrome/browser/chromeos/cros/mock_power_library.h
+++ b/chrome/browser/chromeos/cros/mock_power_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_POWER_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_POWER_LIBRARY_H_
+#pragma once
#include "chrome/browser/chromeos/cros/power_library.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/cros/mock_screen_lock_library.h b/chrome/browser/chromeos/cros/mock_screen_lock_library.h
index 9022ce6..9b1c01c 100644
--- a/chrome/browser/chromeos/cros/mock_screen_lock_library.h
+++ b/chrome/browser/chromeos/cros/mock_screen_lock_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_SCREEN_LOCK_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_SCREEN_LOCK_LIBRARY_H_
+#pragma once
#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/cros/mock_speech_synthesis_library.h b/chrome/browser/chromeos/cros/mock_speech_synthesis_library.h
index 08cf883..dcf1926 100644
--- a/chrome/browser/chromeos/cros/mock_speech_synthesis_library.h
+++ b/chrome/browser/chromeos/cros/mock_speech_synthesis_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_SPEECH_SYNTHESIS_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_SPEECH_SYNTHESIS_LIBRARY_H_
+#pragma once
#include "chrome/browser/chromeos/cros/speech_synthesis_library.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/cros/mock_synaptics_library.h b/chrome/browser/chromeos/cros/mock_synaptics_library.h
deleted file mode 100644
index be5efb0..0000000
--- a/chrome/browser/chromeos/cros/mock_synaptics_library.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYNAPTICS_LIBRARY_H_
-#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYNAPTICS_LIBRARY_H_
-
-#include "chrome/browser/chromeos/cros/synaptics_library.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace chromeos {
-
-class MockSynapticsLibrary : public SynapticsLibrary {
- public:
- MockSynapticsLibrary() {}
- virtual ~MockSynapticsLibrary() {}
- MOCK_METHOD2(SetBoolParameter, void(SynapticsParameter, bool));
- MOCK_METHOD2(SetRangeParameter, void(SynapticsParameter, int));
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYNAPTICS_LIBRARY_H_
-
diff --git a/chrome/browser/chromeos/cros/mock_system_library.h b/chrome/browser/chromeos/cros/mock_system_library.h
index bbb8006..a851238 100644
--- a/chrome/browser/chromeos/cros/mock_system_library.h
+++ b/chrome/browser/chromeos/cros/mock_system_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYSTEM_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYSTEM_LIBRARY_H_
+#pragma once
#include "chrome/browser/chromeos/cros/system_library.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -18,9 +19,9 @@ class MockSystemLibrary : public SystemLibrary {
MOCK_METHOD1(RemoveObserver, void(Observer*));
MOCK_METHOD0(GetTimezone, const icu::TimeZone&());
MOCK_METHOD1(SetTimezone, void(const icu::TimeZone*));
+ MOCK_METHOD2(GetMachineStatistic, bool(const std::string&, std::string*));
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CROS_MOCK_SYSTEM_LIBRARY_H_
-
diff --git a/chrome/browser/chromeos/cros/mock_update_library.h b/chrome/browser/chromeos/cros/mock_update_library.h
index 4e1e7f6..d4f14cb 100644
--- a/chrome/browser/chromeos/cros/mock_update_library.h
+++ b/chrome/browser/chromeos/cros/mock_update_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOCK_UPDATE_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOCK_UPDATE_LIBRARY_H_
+#pragma once
#include "base/observer_list.h"
#include "chrome/browser/chromeos/cros/update_library.h"
@@ -17,7 +18,8 @@ class MockUpdateLibrary : public UpdateLibrary {
virtual ~MockUpdateLibrary() {}
MOCK_METHOD1(AddObserver, void(Observer*)); // NOLINT
MOCK_METHOD1(RemoveObserver, void(Observer*)); // NOLINT
-
+ MOCK_METHOD0(CheckForUpdate, bool(void));
+ MOCK_METHOD0(RebootAfterUpdate, bool(void));
MOCK_CONST_METHOD0(status, const Status&(void));
private:
diff --git a/chrome/browser/chromeos/cros/mount_library.cc b/chrome/browser/chromeos/cros/mount_library.cc
index e99edf2..16cec4a 100644
--- a/chrome/browser/chromeos/cros/mount_library.cc
+++ b/chrome/browser/chromeos/cros/mount_library.cc
@@ -9,97 +9,140 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl);
-
namespace chromeos {
-void MountLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+class MountLibraryImpl : public MountLibrary {
+ public:
+ MountLibraryImpl() : mount_status_connection_(NULL) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ Init();
+ } else {
+ LOG(ERROR) << "Cros Library has not been loaded";
+ }
+ }
-void MountLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ ~MountLibraryImpl() {
+ if (mount_status_connection_) {
+ DisconnectMountStatus(mount_status_connection_);
+ }
+ }
-bool MountLibraryImpl::MountPath(const char* device_path) {
- return MountDevicePath(device_path);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void MountLibraryImpl::ParseDisks(const MountStatus& status) {
- disks_.clear();
- for (int i = 0; i < status.size; i++) {
- std::string path;
- std::string mountpath;
- std::string systempath;
- bool parent;
- bool hasmedia;
- if (status.disks[i].path != NULL) {
- path = status.disks[i].path;
- }
- if (status.disks[i].mountpath != NULL) {
- mountpath = status.disks[i].mountpath;
- }
- if (status.disks[i].systempath != NULL) {
- systempath = status.disks[i].systempath;
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
+
+ bool MountPath(const char* device_path) {
+ return MountDevicePath(device_path);
+ }
+
+ const DiskVector& disks() const { return disks_; }
+
+ private:
+ void ParseDisks(const MountStatus& status) {
+ disks_.clear();
+ for (int i = 0; i < status.size; i++) {
+ std::string path;
+ std::string mountpath;
+ std::string systempath;
+ bool parent;
+ bool hasmedia;
+ if (status.disks[i].path != NULL) {
+ path = status.disks[i].path;
+ }
+ if (status.disks[i].mountpath != NULL) {
+ mountpath = status.disks[i].mountpath;
+ }
+ if (status.disks[i].systempath != NULL) {
+ systempath = status.disks[i].systempath;
+ }
+ parent = status.disks[i].isparent;
+ hasmedia = status.disks[i].hasmedia;
+ disks_.push_back(Disk(path,
+ mountpath,
+ systempath,
+ parent,
+ hasmedia));
}
- parent = status.disks[i].isparent;
- hasmedia = status.disks[i].hasmedia;
- disks_.push_back(Disk(path,
- mountpath,
- systempath,
- parent,
- hasmedia));
}
-}
-MountLibraryImpl::MountLibraryImpl() : mount_status_connection_(NULL) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- Init();
- } else {
- LOG(ERROR) << "Cros Library has not been loaded";
+ static void MountStatusChangedHandler(void* object,
+ const MountStatus& status,
+ MountEventType evt,
+ const char* path) {
+ MountLibraryImpl* mount = static_cast<MountLibraryImpl*>(object);
+ std::string devicepath = path;
+ mount->ParseDisks(status);
+ mount->UpdateMountStatus(status, evt, devicepath);
}
-}
-MountLibraryImpl::~MountLibraryImpl() {
- if (mount_status_connection_) {
- DisconnectMountStatus(mount_status_connection_);
+ void Init() {
+ // Getting the monitor status so that the daemon starts up.
+ MountStatus* mount = RetrieveMountInformation();
+ if (!mount) {
+ LOG(ERROR) << "Failed to retrieve mount information";
+ return;
+ }
+ ParseDisks(*mount);
+ FreeMountStatus(mount);
+
+ mount_status_connection_ = MonitorMountStatus(
+ &MountStatusChangedHandler, this);
}
-}
-// static
-void MountLibraryImpl::MountStatusChangedHandler(void* object,
- const MountStatus& status,
- MountEventType evt,
- const char* path) {
- MountLibraryImpl* mount = static_cast<MountLibraryImpl*>(object);
- std::string devicepath = path;
- mount->ParseDisks(status);
- mount->UpdateMountStatus(status, evt, devicepath);
-}
+ void UpdateMountStatus(const MountStatus& status,
+ MountEventType evt,
+ const std::string& path) {
+ // Make sure we run on UI thread.
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
-void MountLibraryImpl::Init() {
- // Getting the monitor status so that the daemon starts up.
- MountStatus* mount = RetrieveMountInformation();
- if (!mount) {
- LOG(ERROR) << "Failed to retrieve mount information";
- return;
+ FOR_EACH_OBSERVER(
+ Observer, observers_, MountChanged(this, evt, path));
}
- ParseDisks(*mount);
- FreeMountStatus(mount);
+ ObserverList<Observer> observers_;
- mount_status_connection_ = MonitorMountStatus(
- &MountStatusChangedHandler, this);
-}
+ // A reference to the mount api, to allow callbacks when the mount
+ // status changes.
+ MountStatusConnection mount_status_connection_;
+
+ // The list of disks found.
+ DiskVector disks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl);
+};
-void MountLibraryImpl::UpdateMountStatus(const MountStatus& status,
- MountEventType evt,
- const std::string& path) {
- // Make sure we run on UI thread.
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+class MountLibraryStubImpl : public MountLibrary {
+ public:
+ MountLibraryStubImpl() {}
+ virtual ~MountLibraryStubImpl() {}
- FOR_EACH_OBSERVER(Observer, observers_, MountChanged(this, evt, path));
+ // MountLibrary overrides.
+ virtual void AddObserver(Observer* observer) {}
+ virtual void RemoveObserver(Observer* observer) {}
+ virtual const DiskVector& disks() const { return disks_; }
+ virtual bool MountPath(const char* device_path) { return false; }
+
+ private:
+ // The list of disks found.
+ DiskVector disks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl);
+};
+
+// static
+MountLibrary* MountLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new MountLibraryStubImpl();
+ else
+ return new MountLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl);
+
diff --git a/chrome/browser/chromeos/cros/mount_library.h b/chrome/browser/chromeos/cros/mount_library.h
index 3fd772a..f54ba53 100644
--- a/chrome/browser/chromeos/cros/mount_library.h
+++ b/chrome/browser/chromeos/cros/mount_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_MOUNT_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_MOUNT_LIBRARY_H_
+#pragma once
#include <string>
#include <vector>
@@ -17,7 +18,7 @@ namespace chromeos {
// This class handles the interaction with the ChromeOS mount library APIs.
// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: MountLibrary::Get().
+// library class like this: chromeos::CrosLibrary::Get()->GetMountLibrary()
class MountLibrary {
public:
// Used to house an instance of each found mount device.
@@ -58,51 +59,10 @@ class MountLibrary {
virtual void RemoveObserver(Observer* observer) = 0;
virtual const DiskVector& disks() const = 0;
virtual bool MountPath(const char* device_path) = 0;
-};
-
-// This class handles the interaction with the ChromeOS mount library APIs.
-// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: MountLibrary::Get().
-class MountLibraryImpl : public MountLibrary {
- public:
- MountLibraryImpl();
- virtual ~MountLibraryImpl();
-
- // MountLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
- virtual const DiskVector& disks() const { return disks_; }
- virtual bool MountPath(const char* device_path);
- private:
- void ParseDisks(const MountStatus& status);
-
- // This method is called when there's a change in mount status.
- // This method is called the UI Thread.
- static void MountStatusChangedHandler(void* object,
- const MountStatus& status,
- MountEventType evt,
- const char* path);
-
- // This methods starts the monitoring of mount changes.
- // It should be called on the UI Thread.
- void Init();
-
- // Called by the handler to update the mount status.
- // This will notify all the Observers.
- void UpdateMountStatus(const MountStatus& status,
- MountEventType evt,
- const std::string& path);
-
- ObserverList<Observer> observers_;
-
- // A reference to the mount api, to allow callbacks when the mount
- // status changes.
- MountStatusConnection mount_status_connection_;
-
- // The list of disks found.
- DiskVector disks_;
- DISALLOW_COPY_AND_ASSIGN(MountLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static MountLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index 7538111..2258a36 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -6,21 +6,14 @@
#include <algorithm>
+#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "net/url_request/url_request_job.h"
-
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::NetworkLibraryImpl);
namespace chromeos {
-static const std::string kGoogleWifi = "Google";
-static const std::string kGoogleAWifi = "Google-A";
-
// Helper function to wrap Html with <th> tag.
static std::string WrapWithTH(std::string text) {
return "<th>" + text + "</th>";
@@ -51,17 +44,18 @@ static std::string ToHtmlTableRow(Network* network) {
if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) {
WirelessNetwork* wireless = static_cast<WirelessNetwork*>(network);
str += WrapWithTD(wireless->name()) +
- WrapWithTD(IntToString(wireless->auto_connect())) +
- WrapWithTD(IntToString(wireless->strength()));
+ WrapWithTD(base::IntToString(wireless->auto_connect())) +
+ WrapWithTD(base::IntToString(wireless->strength()));
if (network->type() == TYPE_WIFI) {
WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
str += WrapWithTD(wifi->GetEncryptionString()) +
- WrapWithTD(wifi->passphrase()) + WrapWithTD(wifi->identity()) +
- WrapWithTD(wifi->cert_path());
+ WrapWithTD(std::string(wifi->passphrase().length(), '*')) +
+ WrapWithTD(wifi->identity()) + WrapWithTD(wifi->cert_path());
}
}
str += WrapWithTD(network->GetStateString()) +
- WrapWithTD(network->GetErrorString()) + WrapWithTD(network->ip_address());
+ WrapWithTD(network->failed() ? network->GetErrorString() : "") +
+ WrapWithTD(network->ip_address());
return str;
}
@@ -123,7 +117,7 @@ std::string Network::GetStateString() {
std::string Network::GetErrorString() {
switch (error_) {
case ERROR_UNKNOWN:
- break;
+ return "Unknown Error";
case ERROR_OUT_OF_RANGE:
return "Out Of Range";
case ERROR_PIN_MISSING:
@@ -132,6 +126,10 @@ std::string Network::GetErrorString() {
return "DHCP Failed";
case ERROR_CONNECT_FAILED:
return "Connect Failed";
+ case ERROR_BAD_PASSPHRASE:
+ return "Bad Passphrase";
+ case ERROR_BAD_WEPKEY:
+ return "Bad WEP Key";
}
return "";
}
@@ -144,6 +142,7 @@ void WirelessNetwork::Clear() {
name_.clear();
strength_ = 0;
auto_connect_ = false;
+ favorite_ = false;
}
void WirelessNetwork::ConfigureFromService(const ServiceInfo& service) {
@@ -151,17 +150,27 @@ void WirelessNetwork::ConfigureFromService(const ServiceInfo& service) {
name_ = service.name;
strength_ = service.strength;
auto_connect_ = service.auto_connect;
+ favorite_ = service.favorite;
}
////////////////////////////////////////////////////////////////////////////////
// CellularNetwork
+
+bool CellularNetwork::StartActivation() const {
+ // TODO(ers, jglasgow): Kick of device activation process.
+ return true;
+}
+
void CellularNetwork::Clear() {
WirelessNetwork::Clear();
}
void CellularNetwork::ConfigureFromService(const ServiceInfo& service) {
WirelessNetwork::ConfigureFromService(service);
+ activation_state_ = service.activation_state;
+ // TODO(ers): Set other cellular properties here once they get added
+ // to ServiceInfo.
}
////////////////////////////////////////////////////////////////////////////////
@@ -203,622 +212,786 @@ std::string WifiNetwork::GetEncryptionString() {
////////////////////////////////////////////////////////////////////////////////
// NetworkLibrary
-// static
-const int NetworkLibraryImpl::kNetworkTrafficeTimerSecs = 1;
-
-NetworkLibraryImpl::NetworkLibraryImpl()
- : traffic_type_(0),
- network_status_connection_(NULL),
- available_devices_(0),
- enabled_devices_(0),
- connected_devices_(0),
- offline_mode_(false) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- Init();
- }
- g_url_request_job_tracker.AddObserver(this);
-}
+class NetworkLibraryImpl : public NetworkLibrary {
+ public:
+ NetworkLibraryImpl()
+ : network_status_connection_(NULL),
+ available_devices_(0),
+ enabled_devices_(0),
+ connected_devices_(0),
+ offline_mode_(false) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ Init();
+ } else {
+ InitTestData();
+ }
+ }
-NetworkLibraryImpl::~NetworkLibraryImpl() {
- if (network_status_connection_) {
- DisconnectMonitorNetwork(network_status_connection_);
+ ~NetworkLibraryImpl() {
+ if (network_status_connection_) {
+ DisconnectMonitorNetwork(network_status_connection_);
+ }
}
- g_url_request_job_tracker.RemoveObserver(this);
-}
-////////////////////////////////////////////////////////////////////////////////
-// NetworkLibraryImpl, URLRequestJobTracker::JobObserver implementation:
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void NetworkLibraryImpl::OnJobAdded(URLRequestJob* job) {
- CheckNetworkTraffic(false);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-void NetworkLibraryImpl::OnJobRemoved(URLRequestJob* job) {
- CheckNetworkTraffic(false);
-}
+ virtual const EthernetNetwork& ethernet_network() const { return ethernet_; }
+ virtual bool ethernet_connecting() const { return ethernet_.connecting(); }
+ virtual bool ethernet_connected() const { return ethernet_.connected(); }
-void NetworkLibraryImpl::OnJobDone(URLRequestJob* job,
- const URLRequestStatus& status) {
- CheckNetworkTraffic(false);
-}
+ virtual const std::string& wifi_name() const { return wifi_.name(); }
+ virtual bool wifi_connecting() const { return wifi_.connecting(); }
+ virtual bool wifi_connected() const { return wifi_.connected(); }
+ virtual int wifi_strength() const { return wifi_.strength(); }
-void NetworkLibraryImpl::OnJobRedirect(URLRequestJob* job, const GURL& location,
- int status_code) {
- CheckNetworkTraffic(false);
-}
+ virtual const std::string& cellular_name() const { return cellular_.name(); }
+ virtual bool cellular_connecting() const { return cellular_.connecting(); }
+ virtual bool cellular_connected() const { return cellular_.connected(); }
+ virtual int cellular_strength() const { return cellular_.strength(); }
-void NetworkLibraryImpl::OnBytesRead(URLRequestJob* job, const char* buf,
- int byte_count) {
- CheckNetworkTraffic(true);
-}
+ bool Connected() const {
+ return ethernet_connected() || wifi_connected() || cellular_connected();
+ }
-void NetworkLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ bool Connecting() const {
+ return ethernet_connecting() || wifi_connecting() || cellular_connecting();
+ }
-void NetworkLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ const std::string& IPAddress() const {
+ // Returns highest priority IP address.
+ if (ethernet_connected())
+ return ethernet_.ip_address();
+ if (wifi_connected())
+ return wifi_.ip_address();
+ if (cellular_connected())
+ return cellular_.ip_address();
+ return ethernet_.ip_address();
+ }
-////////////////////////////////////////////////////////////////////////////////
+ virtual const WifiNetworkVector& wifi_networks() const {
+ return wifi_networks_;
+ }
-bool NetworkLibraryImpl::FindWifiNetworkByPath(
- const std::string& path, WifiNetwork* result) const {
- const WifiNetwork* wifi =
- GetWirelessNetworkByPath(wifi_networks_, path);
- if (wifi) {
- if (result)
- *result = *wifi;
- return true;
+ virtual const WifiNetworkVector& remembered_wifi_networks() const {
+ return remembered_wifi_networks_;
}
- return false;
-}
-bool NetworkLibraryImpl::FindCellularNetworkByPath(
- const std::string& path, CellularNetwork* result) const {
- const CellularNetwork* cellular =
- GetWirelessNetworkByPath(cellular_networks_, path);
- if (cellular) {
- if (result)
- *result = *cellular;
- return true;
+ virtual const CellularNetworkVector& cellular_networks() const {
+ return cellular_networks_;
}
- return false;
-}
-void NetworkLibraryImpl::RequestWifiScan() {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- RequestScan(TYPE_WIFI);
+ virtual const CellularNetworkVector& remembered_cellular_networks() const {
+ return remembered_cellular_networks_;
}
-}
-bool NetworkLibraryImpl::GetWifiAccessPoints(WifiAccessPointVector* result) {
- if (!CrosLibrary::Get()->EnsureLoaded())
- return false;
- DeviceNetworkList* network_list = GetDeviceNetworkList();
- if (network_list == NULL)
+ /////////////////////////////////////////////////////////////////////////////
+
+ bool FindWifiNetworkByPath(
+ const std::string& path, WifiNetwork* result) const {
+ const WifiNetwork* wifi =
+ GetWirelessNetworkByPath(wifi_networks_, path);
+ if (wifi) {
+ if (result)
+ *result = *wifi;
+ return true;
+ }
return false;
- result->clear();
- result->reserve(network_list->network_size);
- const base::Time now = base::Time::Now();
- for (size_t i = 0; i < network_list->network_size; ++i) {
- DCHECK(network_list->networks[i].address);
- DCHECK(network_list->networks[i].name);
- WifiAccessPoint ap;
- ap.mac_address = network_list->networks[i].address;
- ap.name = network_list->networks[i].name;
- ap.timestamp = now -
- base::TimeDelta::FromSeconds(network_list->networks[i].age_seconds);
- ap.signal_strength = network_list->networks[i].strength;
- ap.channel = network_list->networks[i].channel;
- result->push_back(ap);
- }
- FreeDeviceNetworkList(network_list);
- return true;
-}
+ }
-bool NetworkLibraryImpl::ConnectToPreferredNetworkIfAvailable() {
- // TODO(chocobo): Add the concept of preferred network to libcros.
- // So that we don't have to hard-code Google-A here.
- if (CrosLibrary::Get()->EnsureLoaded()) {
- LOG(INFO) << "Attempting to auto-connect to Google wifi.";
- // First force a refresh of the system info.
- UpdateSystemInfo();
+ bool FindCellularNetworkByPath(
+ const std::string& path, CellularNetwork* result) const {
+ const CellularNetwork* cellular =
+ GetWirelessNetworkByPath(cellular_networks_, path);
+ if (cellular) {
+ if (result)
+ *result = *cellular;
+ return true;
+ }
+ return false;
+ }
- // If ethernet is connected, then don't bother.
- if (ethernet_connected()) {
- LOG(INFO) << "Ethernet connected, so don't need Google wifi.";
- return false;
+ void RequestWifiScan() {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ RequestScan(TYPE_WIFI);
}
+ }
- WifiNetwork* wifi = GetPreferredNetwork();
- if (!wifi) {
- LOG(INFO) << "Google-A/Google wifi not found or set to not auto-connect.";
+ bool GetWifiAccessPoints(WifiAccessPointVector* result) {
+ if (!CrosLibrary::Get()->EnsureLoaded())
+ return false;
+ DeviceNetworkList* network_list = GetDeviceNetworkList();
+ if (network_list == NULL)
return false;
+ result->clear();
+ result->reserve(network_list->network_size);
+ const base::Time now = base::Time::Now();
+ for (size_t i = 0; i < network_list->network_size; ++i) {
+ DCHECK(network_list->networks[i].address);
+ DCHECK(network_list->networks[i].name);
+ WifiAccessPoint ap;
+ ap.mac_address = network_list->networks[i].address;
+ ap.name = network_list->networks[i].name;
+ ap.timestamp = now -
+ base::TimeDelta::FromSeconds(network_list->networks[i].age_seconds);
+ ap.signal_strength = network_list->networks[i].strength;
+ ap.channel = network_list->networks[i].channel;
+ result->push_back(ap);
}
+ FreeDeviceNetworkList(network_list);
+ return true;
+ }
- // Save the wifi path, so we know which one we want to auto-connect to.
- const std::string wifi_path = wifi->service_path();
-
- // It takes some time for the enterprise daemon to start up and populate the
- // certificate and identity. So we wait at most 3 seconds here. And every
- // 100ms, we refetch the system info and check the cert and identify on the
- // wifi. The enterprise daemon takes between 0.4 to 0.9 seconds to setup.
- bool setup = false;
- for (int i = 0; i < 30; i++) {
- // Update the system and refetch the network.
- UpdateSystemInfo();
- wifi = GetWirelessNetworkByPath(wifi_networks_, wifi_path);
- // See if identity and certpath are available.
- if (wifi && !wifi->identity().empty() && !wifi->cert_path().empty()) {
- LOG(INFO) << "Google wifi set up after " << (i*0.1) << " seconds.";
- setup = true;
- break;
+ void ConnectToWifiNetwork(WifiNetwork network,
+ const std::string& password,
+ const std::string& identity,
+ const std::string& certpath) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ if (ConnectToNetworkWithCertInfo(network.service_path().c_str(),
+ password.empty() ? NULL : password.c_str(),
+ identity.empty() ? NULL : identity.c_str(),
+ certpath.empty() ? NULL : certpath.c_str())) {
+ // Update local cache and notify listeners.
+ WifiNetwork* wifi = GetWirelessNetworkByPath(
+ wifi_networks_, network.service_path());
+ if (wifi) {
+ wifi->set_passphrase(password);
+ wifi->set_identity(identity);
+ wifi->set_cert_path(certpath);
+ wifi->set_connecting(true);
+ wifi_ = *wifi;
+ }
+ NotifyNetworkChanged();
}
- PlatformThread::Sleep(100);
}
+ }
- if (!setup) {
- LOG(INFO) << "Google wifi not set up after 3 seconds.";
- return false;
+ void ConnectToWifiNetwork(const std::string& ssid,
+ const std::string& password,
+ const std::string& identity,
+ const std::string& certpath,
+ bool auto_connect) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ // First create a service from hidden network.
+ ServiceInfo* service = GetWifiService(ssid.c_str(),
+ SECURITY_UNKNOWN);
+ if (service) {
+ // Set auto-connect.
+ SetAutoConnect(service->service_path, auto_connect);
+ // Now connect to that service.
+ ConnectToNetworkWithCertInfo(service->service_path,
+ password.empty() ? NULL : password.c_str(),
+ identity.empty() ? NULL : identity.c_str(),
+ certpath.empty() ? NULL : certpath.c_str());
+
+ // Clean up ServiceInfo object.
+ FreeServiceInfo(service);
+ } else {
+ LOG(WARNING) << "Cannot find hidden network: " << ssid;
+ // TODO(chocobo): Show error message.
+ }
}
+ }
- // Now that we have a setup Google wifi, we can connect to it.
- ConnectToNetwork(wifi_path.c_str(), NULL);
- return true;
+ void ConnectToCellularNetwork(CellularNetwork network) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ if (ConnectToNetwork(network.service_path().c_str(), NULL)) {
+ // Update local cache and notify listeners.
+ CellularNetwork* cellular = GetWirelessNetworkByPath(
+ cellular_networks_, network.service_path());
+ if (cellular) {
+ cellular->set_connecting(true);
+ cellular_ = *cellular;
+ }
+ NotifyNetworkChanged();
+ }
+ }
}
- return false;
-}
-bool NetworkLibraryImpl::PreferredNetworkConnected() {
- WifiNetwork* wifi = GetPreferredNetwork();
- return wifi && wifi->connected();
-}
+ void DisconnectFromWirelessNetwork(const WirelessNetwork& network) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ if (DisconnectFromNetwork(network.service_path().c_str())) {
+ // Update local cache and notify listeners.
+ if (network.type() == TYPE_WIFI) {
+ WifiNetwork* wifi = GetWirelessNetworkByPath(
+ wifi_networks_, network.service_path());
+ if (wifi) {
+ wifi->set_connected(false);
+ wifi_ = WifiNetwork();
+ }
+ } else if (network.type() == TYPE_CELLULAR) {
+ CellularNetwork* cellular = GetWirelessNetworkByPath(
+ cellular_networks_, network.service_path());
+ if (cellular) {
+ cellular->set_connected(false);
+ cellular_ = CellularNetwork();
+ }
+ }
+ NotifyNetworkChanged();
+ }
+ }
+ }
-bool NetworkLibraryImpl::PreferredNetworkFailed() {
- WifiNetwork* wifi = GetPreferredNetwork();
- return !wifi || wifi->failed();
-}
+ void SaveCellularNetwork(const CellularNetwork& network) {
+ // Update the wifi network in the local cache.
+ CellularNetwork* cellular = GetWirelessNetworkByPath(
+ cellular_networks_, network.service_path());
+ if (cellular)
+ *cellular = network;
-void NetworkLibraryImpl::ConnectToWifiNetwork(WifiNetwork network,
- const std::string& password,
- const std::string& identity,
- const std::string& certpath) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- ConnectToNetworkWithCertInfo(network.service_path().c_str(),
- password.empty() ? NULL : password.c_str(),
- identity.empty() ? NULL : identity.c_str(),
- certpath.empty() ? NULL : certpath.c_str());
+ // Update the cellular network with libcros.
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ SetAutoConnect(network.service_path().c_str(), network.auto_connect());
+ }
}
-}
-void NetworkLibraryImpl::ConnectToWifiNetwork(const std::string& ssid,
- const std::string& password,
- const std::string& identity,
- const std::string& certpath,
- bool auto_connect) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- // First create a service from hidden network.
- ServiceInfo* service = GetWifiService(ssid.c_str(),
- SECURITY_UNKNOWN);
- if (service) {
- // Set auto-connect.
- SetAutoConnect(service->service_path, auto_connect);
- // Now connect to that service.
- ConnectToNetworkWithCertInfo(service->service_path,
- password.empty() ? NULL : password.c_str(),
- identity.empty() ? NULL : identity.c_str(),
- certpath.empty() ? NULL : certpath.c_str());
-
- // Clean up ServiceInfo object.
- FreeServiceInfo(service);
- } else {
- LOG(WARNING) << "Cannot find hidden network: " << ssid;
- // TODO(chocobo): Show error message.
+ void SaveWifiNetwork(const WifiNetwork& network) {
+ // Update the wifi network in the local cache.
+ WifiNetwork* wifi = GetWirelessNetworkByPath(
+ wifi_networks_, network.service_path());
+ if (wifi)
+ *wifi = network;
+
+ // Update the wifi network with libcros.
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ SetPassphrase(
+ network.service_path().c_str(), network.passphrase().c_str());
+ SetIdentity(network.service_path().c_str(), network.identity().c_str());
+ SetCertPath(network.service_path().c_str(), network.cert_path().c_str());
+ SetAutoConnect(network.service_path().c_str(), network.auto_connect());
}
}
-}
-void NetworkLibraryImpl::ConnectToCellularNetwork(CellularNetwork network) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- ConnectToNetwork(network.service_path().c_str(), NULL);
+ void ForgetWirelessNetwork(const std::string& service_path) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ if (DeleteRememberedService(service_path.c_str())) {
+ // Update local cache and notify listeners.
+ std::remove_if(remembered_wifi_networks_.begin(),
+ remembered_wifi_networks_.end(),
+ WirelessNetwork::ServicePathEq(service_path));
+ std::remove_if(remembered_cellular_networks_.begin(),
+ remembered_cellular_networks_.end(),
+ WirelessNetwork::ServicePathEq(service_path));
+ NotifyNetworkChanged();
+ }
+ }
}
-}
-void NetworkLibraryImpl::DisconnectFromWirelessNetwork(
- const WirelessNetwork& network) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- DisconnectFromNetwork(network.service_path().c_str());
+ virtual bool ethernet_available() const {
+ return available_devices_ & (1 << TYPE_ETHERNET);
+ }
+ virtual bool wifi_available() const {
+ return available_devices_ & (1 << TYPE_WIFI);
+ }
+ virtual bool cellular_available() const {
+ return available_devices_ & (1 << TYPE_CELLULAR);
}
-}
-
-void NetworkLibraryImpl::SaveCellularNetwork(const CellularNetwork& network) {
- // Update the wifi network in the local cache.
- CellularNetwork* cellular = GetWirelessNetworkByPath(cellular_networks_,
- network.service_path());
- if (cellular)
- *cellular = network;
- // Update the cellular network with libcros.
- if (CrosLibrary::Get()->EnsureLoaded()) {
- SetAutoConnect(network.service_path().c_str(), network.auto_connect());
+ virtual bool ethernet_enabled() const {
+ return enabled_devices_ & (1 << TYPE_ETHERNET);
+ }
+ virtual bool wifi_enabled() const {
+ return enabled_devices_ & (1 << TYPE_WIFI);
+ }
+ virtual bool cellular_enabled() const {
+ return enabled_devices_ & (1 << TYPE_CELLULAR);
}
-}
-void NetworkLibraryImpl::SaveWifiNetwork(const WifiNetwork& network) {
- // Update the wifi network in the local cache.
- WifiNetwork* wifi = GetWirelessNetworkByPath(wifi_networks_,
- network.service_path());
- if (wifi)
- *wifi = network;
+ virtual bool offline_mode() const { return offline_mode_; }
- // Update the wifi network with libcros.
- if (CrosLibrary::Get()->EnsureLoaded()) {
- SetPassphrase(network.service_path().c_str(), network.passphrase().c_str());
- SetIdentity(network.service_path().c_str(), network.identity().c_str());
- SetCertPath(network.service_path().c_str(), network.cert_path().c_str());
- SetAutoConnect(network.service_path().c_str(), network.auto_connect());
+ void EnableEthernetNetworkDevice(bool enable) {
+ EnableNetworkDeviceType(TYPE_ETHERNET, enable);
}
-}
-void NetworkLibraryImpl::ForgetWirelessNetwork(const WirelessNetwork& network) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- DeleteRememberedService(network.service_path().c_str());
+ void EnableWifiNetworkDevice(bool enable) {
+ EnableNetworkDeviceType(TYPE_WIFI, enable);
}
-}
-
-void NetworkLibraryImpl::EnableEthernetNetworkDevice(bool enable) {
- EnableNetworkDeviceType(TYPE_ETHERNET, enable);
-}
-
-void NetworkLibraryImpl::EnableWifiNetworkDevice(bool enable) {
- EnableNetworkDeviceType(TYPE_WIFI, enable);
-}
-void NetworkLibraryImpl::EnableCellularNetworkDevice(bool enable) {
- EnableNetworkDeviceType(TYPE_CELLULAR, enable);
-}
+ void EnableCellularNetworkDevice(bool enable) {
+ EnableNetworkDeviceType(TYPE_CELLULAR, enable);
+ }
-void NetworkLibraryImpl::EnableOfflineMode(bool enable) {
- if (!CrosLibrary::Get()->EnsureLoaded())
- return;
+ void EnableOfflineMode(bool enable) {
+ if (!CrosLibrary::Get()->EnsureLoaded())
+ return;
- // If network device is already enabled/disabled, then don't do anything.
- if (enable && offline_mode_) {
- LOG(INFO) << "Trying to enable offline mode when it's already enabled. ";
- return;
- }
- if (!enable && !offline_mode_) {
- LOG(INFO) << "Trying to disable offline mode when it's already disabled. ";
- return;
- }
+ // If network device is already enabled/disabled, then don't do anything.
+ if (enable && offline_mode_) {
+ LOG(INFO) << "Trying to enable offline mode when it's already enabled. ";
+ return;
+ }
+ if (!enable && !offline_mode_) {
+ LOG(INFO) <<
+ "Trying to disable offline mode when it's already disabled. ";
+ return;
+ }
- if (SetOfflineMode(enable)) {
- offline_mode_ = enable;
+ if (SetOfflineMode(enable)) {
+ offline_mode_ = enable;
+ }
}
-}
-NetworkIPConfigVector NetworkLibraryImpl::GetIPConfigs(
- const std::string& device_path) {
- NetworkIPConfigVector ipconfig_vector;
- if (!device_path.empty()) {
- IPConfigStatus* ipconfig_status = ListIPConfigs(device_path.c_str());
- if (ipconfig_status) {
- for (int i = 0; i < ipconfig_status->size; i++) {
- IPConfig ipconfig = ipconfig_status->ips[i];
- ipconfig_vector.push_back(
- NetworkIPConfig(device_path, ipconfig.type, ipconfig.address,
- ipconfig.netmask, ipconfig.gateway,
- ipconfig.name_servers));
+ NetworkIPConfigVector GetIPConfigs(const std::string& device_path) {
+ NetworkIPConfigVector ipconfig_vector;
+ if (!device_path.empty()) {
+ IPConfigStatus* ipconfig_status = ListIPConfigs(device_path.c_str());
+ if (ipconfig_status) {
+ for (int i = 0; i < ipconfig_status->size; i++) {
+ IPConfig ipconfig = ipconfig_status->ips[i];
+ ipconfig_vector.push_back(
+ NetworkIPConfig(device_path, ipconfig.type, ipconfig.address,
+ ipconfig.netmask, ipconfig.gateway,
+ ipconfig.name_servers));
+ }
+ FreeIPConfigStatus(ipconfig_status);
+ // Sort the list of ip configs by type.
+ std::sort(ipconfig_vector.begin(), ipconfig_vector.end());
}
- FreeIPConfigStatus(ipconfig_status);
- // Sort the list of ip configs by type.
- std::sort(ipconfig_vector.begin(), ipconfig_vector.end());
}
- }
- return ipconfig_vector;
-}
+ return ipconfig_vector;
+ }
+
+ std::string GetHtmlInfo(int refresh) {
+ std::string output;
+ output.append("<html><head><title>About Network</title>");
+ if (refresh > 0)
+ output.append("<meta http-equiv=\"refresh\" content=\"" +
+ base::IntToString(refresh) + "\"/>");
+ output.append("</head><body>");
+ if (refresh > 0) {
+ output.append("(Auto-refreshing page every " +
+ base::IntToString(refresh) + "s)");
+ } else {
+ output.append("(To auto-refresh this page: about:network/&lt;secs&gt;)");
+ }
-std::string NetworkLibraryImpl::GetHtmlInfo(int refresh) {
- std::string output;
- output.append("<html><head><title>About Network</title>");
- if (refresh > 0)
- output.append("<meta http-equiv=\"refresh\" content=\"" +
- IntToString(refresh) + "\"/>");
- output.append("</head><body>");
- if (refresh > 0)
- output.append("(Auto-refreshing page every " + IntToString(refresh) + "s)");
- else
- output.append("(To auto-refresh this page: about:network/&lt;secs&gt;)");
+ output.append("<h3>Ethernet:</h3><table border=1>");
+ if (ethernet_enabled()) {
+ output.append("<tr>" + ToHtmlTableHeader(&ethernet_) + "</tr>");
+ output.append("<tr>" + ToHtmlTableRow(&ethernet_) + "</tr>");
+ }
- output.append("<h3>Ethernet:</h3><table border=1>");
- output.append("<tr>" + ToHtmlTableHeader(&ethernet_) + "</tr>");
- output.append("<tr>" + ToHtmlTableRow(&ethernet_) + "</tr>");
+ output.append("</table><h3>Wifi:</h3><table border=1>");
+ for (size_t i = 0; i < wifi_networks_.size(); ++i) {
+ if (i == 0)
+ output.append("<tr>" + ToHtmlTableHeader(&wifi_networks_[i]) + "</tr>");
+ output.append("<tr>" + ToHtmlTableRow(&wifi_networks_[i]) + "</tr>");
+ }
- output.append("</table><h3>Wifi:</h3><table border=1>");
- for (size_t i = 0; i < wifi_networks_.size(); ++i) {
- if (i == 0)
- output.append("<tr>" + ToHtmlTableHeader(&wifi_networks_[i]) + "</tr>");
- output.append("<tr>" + ToHtmlTableRow(&wifi_networks_[i]) + "</tr>");
- }
+ output.append("</table><h3>Cellular:</h3><table border=1>");
+ for (size_t i = 0; i < cellular_networks_.size(); ++i) {
+ if (i == 0)
+ output.append("<tr>" + ToHtmlTableHeader(&cellular_networks_[i]) +
+ "</tr>");
+ output.append("<tr>" + ToHtmlTableRow(&cellular_networks_[i]) + "</tr>");
+ }
- output.append("</table><h3>Cellular:</h3><table border=1>");
- for (size_t i = 0; i < cellular_networks_.size(); ++i) {
- if (i == 0)
- output.append("<tr>" + ToHtmlTableHeader(&cellular_networks_[i]) +
+ output.append("</table><h3>Remembered Wifi:</h3><table border=1>");
+ for (size_t i = 0; i < remembered_wifi_networks_.size(); ++i) {
+ if (i == 0)
+ output.append(
+ "<tr>" + ToHtmlTableHeader(&remembered_wifi_networks_[i]) +
+ "</tr>");
+ output.append("<tr>" + ToHtmlTableRow(&remembered_wifi_networks_[i]) +
"</tr>");
- output.append("<tr>" + ToHtmlTableRow(&cellular_networks_[i]) + "</tr>");
- }
+ }
- output.append("</table><h3>Remembered Wifi:</h3><table border=1>");
- for (size_t i = 0; i < remembered_wifi_networks_.size(); ++i) {
- if (i == 0)
- output.append("<tr>" + ToHtmlTableHeader(&remembered_wifi_networks_[i]) +
+ output.append("</table><h3>Remembered Cellular:</h3><table border=1>");
+ for (size_t i = 0; i < remembered_cellular_networks_.size(); ++i) {
+ if (i == 0)
+ output.append("<tr>" +
+ ToHtmlTableHeader(&remembered_cellular_networks_[i]) + "</tr>");
+ output.append("<tr>" + ToHtmlTableRow(&remembered_cellular_networks_[i]) +
"</tr>");
- output.append("<tr>" + ToHtmlTableRow(&remembered_wifi_networks_[i]) +
- "</tr>");
- }
+ }
- output.append("</table><h3>Remembered Cellular:</h3><table border=1>");
- for (size_t i = 0; i < remembered_cellular_networks_.size(); ++i) {
- if (i == 0)
- output.append("<tr>" +
- ToHtmlTableHeader(&remembered_cellular_networks_[i]) + "</tr>");
- output.append("<tr>" + ToHtmlTableRow(&remembered_cellular_networks_[i]) +
- "</tr>");
+ output.append("</table></body></html>");
+ return output;
}
- output.append("</table></body></html>");
- return output;
-}
-
-// static
-void NetworkLibraryImpl::NetworkStatusChangedHandler(void* object) {
- NetworkLibraryImpl* network = static_cast<NetworkLibraryImpl*>(object);
- DCHECK(network);
- network->UpdateNetworkStatus();
-}
+ private:
+ static void NetworkStatusChangedHandler(void* object) {
+ NetworkLibraryImpl* network = static_cast<NetworkLibraryImpl*>(object);
+ DCHECK(network);
+ network->UpdateNetworkStatus();
+ }
-// static
-void NetworkLibraryImpl::ParseSystem(SystemInfo* system,
- EthernetNetwork* ethernet,
- WifiNetworkVector* wifi_networks,
- CellularNetworkVector* cellular_networks,
- WifiNetworkVector* remembered_wifi_networks,
- CellularNetworkVector* remembered_cellular_networks) {
- DLOG(INFO) << "ParseSystem:";
- ethernet->Clear();
- for (int i = 0; i < system->service_size; i++) {
- const ServiceInfo& service = system->services[i];
- DLOG(INFO) << " (" << service.type <<
- ") " << service.name <<
- " mode=" << service.mode <<
- " state=" << service.state <<
- " sec=" << service.security <<
- " req=" << service.passphrase_required <<
- " pass=" << service.passphrase <<
- " id=" << service.identity <<
- " certpath=" << service.cert_path <<
- " str=" << service.strength <<
- " fav=" << service.favorite <<
- " auto=" << service.auto_connect <<
- " error=" << service.error;
- // Once a connected ethernet service is found, disregard other ethernet
- // services that are also found
- if (service.type == TYPE_ETHERNET && !(ethernet->connected()))
- ethernet->ConfigureFromService(service);
- else if (service.type == TYPE_WIFI)
- wifi_networks->push_back(WifiNetwork(service));
- else if (service.type == TYPE_CELLULAR)
- cellular_networks->push_back(CellularNetwork(service));
- }
- DLOG(INFO) << "Remembered networks:";
- for (int i = 0; i < system->remembered_service_size; i++) {
- const ServiceInfo& service = system->remembered_services[i];
- // Only serices marked as auto_connect are considered remembered networks.
- // TODO(chocobo): Don't add to remembered service if currently available.
- if (service.auto_connect) {
+ static void ParseSystem(SystemInfo* system,
+ EthernetNetwork* ethernet,
+ WifiNetworkVector* wifi_networks,
+ CellularNetworkVector* cellular_networks,
+ WifiNetworkVector* remembered_wifi_networks,
+ CellularNetworkVector* remembered_cellular_networks) {
+ DLOG(INFO) << "ParseSystem:";
+ ethernet->Clear();
+ for (int i = 0; i < system->service_size; i++) {
+ const ServiceInfo service = *system->GetServiceInfo(i);
DLOG(INFO) << " (" << service.type <<
") " << service.name <<
" mode=" << service.mode <<
+ " state=" << service.state <<
" sec=" << service.security <<
+ " req=" << service.passphrase_required <<
" pass=" << service.passphrase <<
" id=" << service.identity <<
" certpath=" << service.cert_path <<
- " auto=" << service.auto_connect;
- if (service.type == TYPE_WIFI)
- remembered_wifi_networks->push_back(WifiNetwork(service));
+ " str=" << service.strength <<
+ " fav=" << service.favorite <<
+ " auto=" << service.auto_connect <<
+ " error=" << service.error;
+ // Once a connected ethernet service is found, disregard other ethernet
+ // services that are also found
+ if (service.type == TYPE_ETHERNET && !(ethernet->connected()))
+ ethernet->ConfigureFromService(service);
+ else if (service.type == TYPE_WIFI)
+ wifi_networks->push_back(WifiNetwork(service));
else if (service.type == TYPE_CELLULAR)
- remembered_cellular_networks->push_back(CellularNetwork(service));
+ cellular_networks->push_back(CellularNetwork(service));
+ }
+ DLOG(INFO) << "Remembered networks:";
+ for (int i = 0; i < system->remembered_service_size; i++) {
+ const ServiceInfo& service = *system->GetRememberedServiceInfo(i);
+ // Only serices marked as auto_connect are considered remembered networks.
+ // TODO(chocobo): Don't add to remembered service if currently available.
+ if (service.auto_connect) {
+ DLOG(INFO) << " (" << service.type <<
+ ") " << service.name <<
+ " mode=" << service.mode <<
+ " sec=" << service.security <<
+ " pass=" << service.passphrase <<
+ " id=" << service.identity <<
+ " certpath=" << service.cert_path <<
+ " auto=" << service.auto_connect;
+ if (service.type == TYPE_WIFI)
+ remembered_wifi_networks->push_back(WifiNetwork(service));
+ else if (service.type == TYPE_CELLULAR)
+ remembered_cellular_networks->push_back(CellularNetwork(service));
+ }
}
}
-}
-
-void NetworkLibraryImpl::Init() {
- // First, get the currently available networks. This data is cached
- // on the connman side, so the call should be quick.
- LOG(INFO) << "Getting initial CrOS network info.";
- UpdateSystemInfo();
- LOG(INFO) << "Registering for network status updates.";
- // Now, register to receive updates on network status.
- network_status_connection_ = MonitorNetwork(&NetworkStatusChangedHandler,
- this);
-}
+ void Init() {
+ // First, get the currently available networks. This data is cached
+ // on the connman side, so the call should be quick.
+ LOG(INFO) << "Getting initial CrOS network info.";
+ UpdateSystemInfo();
-void NetworkLibraryImpl::UpdateSystemInfo() {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- UpdateNetworkStatus();
+ LOG(INFO) << "Registering for network status updates.";
+ // Now, register to receive updates on network status.
+ network_status_connection_ = MonitorNetwork(&NetworkStatusChangedHandler,
+ this);
+ }
+
+ void InitTestData() {
+ ethernet_.Clear();
+ ethernet_.set_connected(true);
+
+ wifi_networks_.clear();
+ WifiNetwork wifi1 = WifiNetwork();
+ wifi1.set_service_path("fw1");
+ wifi1.set_name("Fake Wifi 1");
+ wifi1.set_strength(90);
+ wifi1.set_connected(false);
+ wifi1.set_encryption(SECURITY_NONE);
+ wifi_networks_.push_back(wifi1);
+
+ WifiNetwork wifi2 = WifiNetwork();
+ wifi2.set_service_path("fw2");
+ wifi2.set_name("Fake Wifi 2");
+ wifi2.set_strength(70);
+ wifi2.set_connected(true);
+ wifi2.set_encryption(SECURITY_WEP);
+ wifi_networks_.push_back(wifi2);
+
+ WifiNetwork wifi3 = WifiNetwork();
+ wifi3.set_service_path("fw3");
+ wifi3.set_name("Fake Wifi 3");
+ wifi3.set_strength(50);
+ wifi3.set_connected(false);
+ wifi3.set_encryption(SECURITY_WEP);
+ wifi_networks_.push_back(wifi3);
+
+ wifi_ = wifi2;
+
+ cellular_networks_.clear();
+
+ cellular_networks_.clear();
+ CellularNetwork cellular1 = CellularNetwork();
+ cellular1.set_service_path("fc1");
+ cellular1.set_name("Fake Cellular 1");
+ cellular1.set_strength(90);
+ cellular1.set_connected(false);
+ cellular_networks_.push_back(cellular1);
+
+ CellularNetwork cellular2 = CellularNetwork();
+ cellular2.set_service_path("fc2");
+ cellular2.set_name("Fake Cellular 2");
+ cellular2.set_strength(70);
+ cellular2.set_connected(true);
+ cellular_networks_.push_back(cellular2);
+
+ CellularNetwork cellular3 = CellularNetwork();
+ cellular3.set_service_path("fc3");
+ cellular3.set_name("Fake Cellular 3");
+ cellular3.set_strength(50);
+ cellular3.set_connected(false);
+ cellular_networks_.push_back(cellular3);
+
+ cellular_ = cellular2;
+
+ remembered_wifi_networks_.clear();
+ remembered_wifi_networks_.push_back(wifi2);
+
+ remembered_cellular_networks_.clear();
+ remembered_cellular_networks_.push_back(cellular2);
+
+ int devices = (1 << TYPE_ETHERNET) | (1 << TYPE_WIFI) |
+ (1 << TYPE_CELLULAR);
+ available_devices_ = devices;
+ enabled_devices_ = devices;
+ connected_devices_ = devices;
+ offline_mode_ = false;
+ }
+
+ void UpdateSystemInfo() {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ UpdateNetworkStatus();
+ }
}
-}
-
-WifiNetwork* NetworkLibraryImpl::GetPreferredNetwork() {
- // First look for Google-A then look for Google.
- // Only care if set to auto-connect.
- WifiNetwork* wifi = GetWifiNetworkByName(kGoogleAWifi);
- // If wifi found and set to not auto-connect, then ignore it.
- if (wifi && !wifi->auto_connect())
- wifi = NULL;
-
- if (!wifi) {
- wifi = GetWifiNetworkByName(kGoogleWifi);
- // If wifi found and set to not auto-connect, then ignore it.
- if (wifi && !wifi->auto_connect())
- wifi = NULL;
- }
- return wifi;
-}
-WifiNetwork* NetworkLibraryImpl::GetWifiNetworkByName(const std::string& name) {
- for (size_t i = 0; i < wifi_networks_.size(); ++i) {
- if (wifi_networks_[i].name().compare(name) == 0) {
- return &wifi_networks_[i];
+ WifiNetwork* GetWifiNetworkByName(const std::string& name) {
+ for (size_t i = 0; i < wifi_networks_.size(); ++i) {
+ if (wifi_networks_[i].name().compare(name) == 0) {
+ return &wifi_networks_[i];
+ }
}
+ return NULL;
}
- return NULL;
-}
-
-template<typename T> T* NetworkLibraryImpl::GetWirelessNetworkByPath(
- std::vector<T>& networks, const std::string& path) {
- typedef typename std::vector<T>::iterator iter_t;
- iter_t iter = std::find_if(networks.begin(), networks.end(),
- WirelessNetwork::ServicePathEq(path));
- return (iter != networks.end()) ? &(*iter) : NULL;
-}
-// const version
-template<typename T> const T* NetworkLibraryImpl::GetWirelessNetworkByPath(
- const std::vector<T>& networks, const std::string& path) const {
- typedef typename std::vector<T>::const_iterator iter_t;
- iter_t iter = std::find_if(networks.begin(), networks.end(),
- WirelessNetwork::ServicePathEq(path));
- return (iter != networks.end()) ? &(*iter) : NULL;
-}
-
-void NetworkLibraryImpl::EnableNetworkDeviceType(ConnectionType device,
- bool enable) {
- if (!CrosLibrary::Get()->EnsureLoaded())
- return;
-
- // If network device is already enabled/disabled, then don't do anything.
- if (enable && (enabled_devices_ & (1 << device))) {
- LOG(WARNING) << "Trying to enable a device that's already enabled: "
- << device;
- return;
+ template<typename T> T* GetWirelessNetworkByPath(
+ std::vector<T>& networks, const std::string& path) {
+ typedef typename std::vector<T>::iterator iter_t;
+ iter_t iter = std::find_if(networks.begin(), networks.end(),
+ WirelessNetwork::ServicePathEq(path));
+ return (iter != networks.end()) ? &(*iter) : NULL;
}
- if (!enable && !(enabled_devices_ & (1 << device))) {
- LOG(WARNING) << "Trying to disable a device that's already disabled: "
- << device;
- return;
- }
-
- EnableNetworkDevice(device, enable);
-}
-void NetworkLibraryImpl::UpdateNetworkStatus() {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this,
- &NetworkLibraryImpl::UpdateNetworkStatus));
- return;
+ // const version
+ template<typename T> const T* GetWirelessNetworkByPath(
+ const std::vector<T>& networks, const std::string& path) const {
+ typedef typename std::vector<T>::const_iterator iter_t;
+ iter_t iter = std::find_if(networks.begin(), networks.end(),
+ WirelessNetwork::ServicePathEq(path));
+ return (iter != networks.end()) ? &(*iter) : NULL;
}
- SystemInfo* system = GetSystemInfo();
- if (!system)
- return;
-
- wifi_networks_.clear();
- cellular_networks_.clear();
- remembered_wifi_networks_.clear();
- remembered_cellular_networks_.clear();
- ParseSystem(system, &ethernet_, &wifi_networks_, &cellular_networks_,
- &remembered_wifi_networks_, &remembered_cellular_networks_);
+ void EnableNetworkDeviceType(ConnectionType device, bool enable) {
+ if (!CrosLibrary::Get()->EnsureLoaded())
+ return;
- wifi_ = WifiNetwork();
- for (size_t i = 0; i < wifi_networks_.size(); i++) {
- if (wifi_networks_[i].connecting_or_connected()) {
- wifi_ = wifi_networks_[i];
- break; // There is only one connected or connecting wifi network.
+ // If network device is already enabled/disabled, then don't do anything.
+ if (enable && (enabled_devices_ & (1 << device))) {
+ LOG(WARNING) << "Trying to enable a device that's already enabled: "
+ << device;
+ return;
}
- }
- cellular_ = CellularNetwork();
- for (size_t i = 0; i < cellular_networks_.size(); i++) {
- if (cellular_networks_[i].connecting_or_connected()) {
- cellular_ = cellular_networks_[i];
- break; // There is only one connected or connecting cellular network.
+ if (!enable && !(enabled_devices_ & (1 << device))) {
+ LOG(WARNING) << "Trying to disable a device that's already disabled: "
+ << device;
+ return;
}
+
+ EnableNetworkDevice(device, enable);
}
- available_devices_ = system->available_technologies;
- enabled_devices_ = system->enabled_technologies;
- connected_devices_ = system->connected_technologies;
- offline_mode_ = system->offline_mode;
+ void NotifyNetworkChanged() {
+ FOR_EACH_OBSERVER(Observer, observers_, NetworkChanged(this));
+ }
- FOR_EACH_OBSERVER(Observer, observers_, NetworkChanged(this));
- FreeSystemInfo(system);
-}
+ void UpdateNetworkStatus() {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &NetworkLibraryImpl::UpdateNetworkStatus));
+ return;
+ }
-void NetworkLibraryImpl::CheckNetworkTraffic(bool download) {
- // If we already have a pending upload and download notification, then
- // shortcut and return.
- if (traffic_type_ == (Observer::TRAFFIC_DOWNLOAD | Observer::TRAFFIC_UPLOAD))
- return;
- // Figure out if we are uploading and/or downloading. We are downloading
- // if download == true. We are uploading if we have upload progress.
- if (download)
- traffic_type_ |= Observer::TRAFFIC_DOWNLOAD;
- if ((traffic_type_ & Observer::TRAFFIC_UPLOAD) == 0) {
- URLRequestJobTracker::JobIterator it;
- for (it = g_url_request_job_tracker.begin();
- it != g_url_request_job_tracker.end();
- ++it) {
- URLRequestJob* job = *it;
- if (job->GetUploadProgress() > 0) {
- traffic_type_ |= Observer::TRAFFIC_UPLOAD;
- break;
+ SystemInfo* system = GetSystemInfo();
+ if (!system)
+ return;
+
+ wifi_networks_.clear();
+ cellular_networks_.clear();
+ remembered_wifi_networks_.clear();
+ remembered_cellular_networks_.clear();
+ ParseSystem(system, &ethernet_, &wifi_networks_, &cellular_networks_,
+ &remembered_wifi_networks_, &remembered_cellular_networks_);
+
+ wifi_ = WifiNetwork();
+ for (size_t i = 0; i < wifi_networks_.size(); i++) {
+ if (wifi_networks_[i].connecting_or_connected()) {
+ wifi_ = wifi_networks_[i];
+ break; // There is only one connected or connecting wifi network.
+ }
+ }
+ cellular_ = CellularNetwork();
+ for (size_t i = 0; i < cellular_networks_.size(); i++) {
+ if (cellular_networks_[i].connecting_or_connected()) {
+ cellular_ = cellular_networks_[i];
+ break; // There is only one connected or connecting cellular network.
}
}
- }
- // If we have new traffic data to send out and the timer is not currently
- // running, then start a new timer.
- if (traffic_type_ && !timer_.IsRunning()) {
- timer_.Start(base::TimeDelta::FromSeconds(kNetworkTrafficeTimerSecs), this,
- &NetworkLibraryImpl::NetworkTrafficTimerFired);
- }
-}
-void NetworkLibraryImpl:: NetworkTrafficTimerFired() {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &NetworkLibraryImpl::NotifyNetworkTraffic,
- traffic_type_));
- // Reset traffic type so that we don't send the same data next time.
- traffic_type_ = 0;
-}
+ available_devices_ = system->available_technologies;
+ enabled_devices_ = system->enabled_technologies;
+ connected_devices_ = system->connected_technologies;
+ offline_mode_ = system->offline_mode;
-void NetworkLibraryImpl::NotifyNetworkTraffic(int traffic_type) {
- FOR_EACH_OBSERVER(Observer, observers_, NetworkTraffic(this, traffic_type));
-}
+ NotifyNetworkChanged();
+ FreeSystemInfo(system);
+ }
-bool NetworkLibraryImpl::Connected() const {
- return ethernet_connected() || wifi_connected() || cellular_connected();
-}
+ ObserverList<Observer> observers_;
-bool NetworkLibraryImpl::Connecting() const {
- return ethernet_connecting() || wifi_connecting() || cellular_connecting();
-}
+ // The network status connection for monitoring network status changes.
+ MonitorNetworkConnection network_status_connection_;
-const std::string& NetworkLibraryImpl::IPAddress() const {
- // Returns highest priority IP address.
- if (ethernet_connected())
- return ethernet_.ip_address();
- if (wifi_connected())
- return wifi_.ip_address();
- if (cellular_connected())
- return cellular_.ip_address();
- return ethernet_.ip_address();
+ // The ethernet network.
+ EthernetNetwork ethernet_;
+
+ // The list of available wifi networks.
+ WifiNetworkVector wifi_networks_;
+
+ // The current connected (or connecting) wifi network.
+ WifiNetwork wifi_;
+
+ // The remembered wifi networks.
+ WifiNetworkVector remembered_wifi_networks_;
+
+ // The list of available cellular networks.
+ CellularNetworkVector cellular_networks_;
+
+ // The current connected (or connecting) cellular network.
+ CellularNetwork cellular_;
+
+ // The remembered cellular networks.
+ CellularNetworkVector remembered_cellular_networks_;
+
+ // The current available network devices. Bitwise flag of ConnectionTypes.
+ int available_devices_;
+
+ // The current enabled network devices. Bitwise flag of ConnectionTypes.
+ int enabled_devices_;
+
+ // The current connected network devices. Bitwise flag of ConnectionTypes.
+ int connected_devices_;
+
+ bool offline_mode_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkLibraryImpl);
+};
+
+class NetworkLibraryStubImpl : public NetworkLibrary {
+ public:
+ NetworkLibraryStubImpl() : ip_address_("1.1.1.1") {}
+ ~NetworkLibraryStubImpl() {}
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+ virtual const EthernetNetwork& ethernet_network() const {
+ return ethernet_;
+ }
+ virtual bool ethernet_connecting() const { return false; }
+ virtual bool ethernet_connected() const { return true; }
+ virtual const std::string& wifi_name() const { return EmptyString(); }
+ virtual bool wifi_connecting() const { return false; }
+ virtual bool wifi_connected() const { return false; }
+ virtual int wifi_strength() const { return 0; }
+
+ virtual const std::string& cellular_name() const { return EmptyString(); }
+ virtual bool cellular_connecting() const { return false; }
+ virtual bool cellular_connected() const { return false; }
+ virtual int cellular_strength() const { return false; }
+
+ bool Connected() const { return true; }
+ bool Connecting() const { return false; }
+ const std::string& IPAddress() const { return ip_address_; }
+ virtual const WifiNetworkVector& wifi_networks() const {
+ return wifi_networks_;
+ }
+ virtual const WifiNetworkVector& remembered_wifi_networks() const {
+ return wifi_networks_;
+ }
+ virtual const CellularNetworkVector& cellular_networks() const {
+ return cellular_networks_;
+ }
+ virtual const CellularNetworkVector& remembered_cellular_networks() const {
+ return cellular_networks_;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ bool FindWifiNetworkByPath(
+ const std::string& path, WifiNetwork* result) const { return false; }
+ bool FindCellularNetworkByPath(
+ const std::string& path, CellularNetwork* result) const { return false; }
+ void RequestWifiScan() {}
+ bool GetWifiAccessPoints(WifiAccessPointVector* result) { return false; }
+
+ void ConnectToWifiNetwork(WifiNetwork network,
+ const std::string& password,
+ const std::string& identity,
+ const std::string& certpath) {}
+ void ConnectToWifiNetwork(const std::string& ssid,
+ const std::string& password,
+ const std::string& identity,
+ const std::string& certpath,
+ bool auto_connect) {}
+ void ConnectToCellularNetwork(CellularNetwork network) {}
+ void DisconnectFromWirelessNetwork(const WirelessNetwork& network) {}
+ void SaveCellularNetwork(const CellularNetwork& network) {}
+ void SaveWifiNetwork(const WifiNetwork& network) {}
+ void ForgetWirelessNetwork(const std::string& service_path) {}
+ virtual bool ethernet_available() const { return true; }
+ virtual bool wifi_available() const { return false; }
+ virtual bool cellular_available() const { return false; }
+ virtual bool ethernet_enabled() const { return true; }
+ virtual bool wifi_enabled() const { return false; }
+ virtual bool cellular_enabled() const { return false; }
+ virtual bool offline_mode() const { return false; }
+ void EnableEthernetNetworkDevice(bool enable) {}
+ void EnableWifiNetworkDevice(bool enable) {}
+ void EnableCellularNetworkDevice(bool enable) {}
+ void EnableOfflineMode(bool enable) {}
+ NetworkIPConfigVector GetIPConfigs(const std::string& device_path) {
+ return NetworkIPConfigVector();
+ }
+ std::string GetHtmlInfo(int refresh) { return std::string(); }
+ void UpdateSystemInfo() {}
+
+ private:
+ std::string ip_address_;
+ EthernetNetwork ethernet_;
+ WifiNetworkVector wifi_networks_;
+ CellularNetworkVector cellular_networks_;
+};
+
+// static
+NetworkLibrary* NetworkLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new NetworkLibraryStubImpl();
+ else
+ return new NetworkLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::NetworkLibraryImpl);
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index 9521a41..c10cc01 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_NETWORK_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_NETWORK_LIBRARY_H_
+#pragma once
#include <string>
#include <vector>
@@ -11,9 +12,7 @@
#include "base/observer_list.h"
#include "base/platform_thread.h"
#include "base/singleton.h"
-#include "base/string16.h"
#include "base/timer.h"
-#include "net/url_request/url_request_job_tracker.h"
#include "cros/chromeos_network.h"
namespace chromeos {
@@ -31,6 +30,8 @@ class Network {
bool failed() const { return state_ == STATE_FAILURE; }
ConnectionError error() const { return error_; }
+ void set_service_path(const std::string& service_path) {
+ service_path_ = service_path; }
void set_connecting(bool connecting) { state_ = (connecting ?
STATE_ASSOCIATION : STATE_IDLE); }
void set_connected(bool connected) { state_ = (connected ?
@@ -89,9 +90,12 @@ class WirelessNetwork : public Network {
const std::string& name() const { return name_; }
int strength() const { return strength_; }
bool auto_connect() const { return auto_connect_; }
+ bool favorite() const { return favorite_; }
void set_name(const std::string& name) { name_ = name; }
+ void set_strength(int strength) { strength_ = strength; }
void set_auto_connect(bool auto_connect) { auto_connect_ = auto_connect; }
+ void set_favorite(bool favorite) { favorite_ = favorite; }
// Network overrides.
virtual void Clear();
@@ -101,11 +105,13 @@ class WirelessNetwork : public Network {
WirelessNetwork()
: Network(),
strength_(0),
- auto_connect_(false) {}
+ auto_connect_(false),
+ favorite_(false) {}
std::string name_;
int strength_;
bool auto_connect_;
+ bool favorite_;
};
class CellularNetwork : public WirelessNetwork {
@@ -115,10 +121,29 @@ class CellularNetwork : public WirelessNetwork {
: WirelessNetwork() {
ConfigureFromService(service);
}
+ // Starts device activation process. Returns false if the device state does
+ // not permit activation.
+ bool StartActivation() const;
+ const ActivationState activation_state() const { return activation_state_; }
+ const std::string& payment_url() const { return payment_url_; }
+ const std::string& meid() const { return meid_; }
+ const std::string& imei() const { return imei_; }
+ const std::string& imsi() const { return imsi_; }
+ const std::string& esn() const { return esn_; }
+ const std::string& mdn() const { return mdn_; }
// WirelessNetwork overrides.
virtual void Clear();
virtual void ConfigureFromService(const ServiceInfo& service);
+
+ protected:
+ ActivationState activation_state_;
+ std::string payment_url_;
+ std::string meid_;
+ std::string imei_;
+ std::string imsi_;
+ std::string esn_;
+ std::string mdn_;
};
class WifiNetwork : public WirelessNetwork {
@@ -221,22 +246,15 @@ struct NetworkIPConfig {
};
typedef std::vector<NetworkIPConfig> NetworkIPConfigVector;
+// This class handles the interaction with the ChromeOS network library APIs.
+// Classes can add themselves as observers. Users can get an instance of the
+// library like this: chromeos::CrosLibrary::Get()->GetNetworkLibrary()
class NetworkLibrary {
public:
class Observer {
public:
- // A bitfield mask for traffic types.
- enum TrafficTypes {
- TRAFFIC_DOWNLOAD = 0x1,
- TRAFFIC_UPLOAD = 0x2,
- } TrafficTypeMasks;
-
// Called when the network has changed. (wifi networks, and ethernet)
virtual void NetworkChanged(NetworkLibrary* obj) = 0;
-
- // Called when network traffic has been detected.
- // Takes a bitfield of TrafficTypeMasks.
- virtual void NetworkTraffic(NetworkLibrary* obj, int traffic_type) = 0;
};
virtual ~NetworkLibrary() {}
@@ -301,18 +319,6 @@ class NetworkLibrary {
// Force an update of the system info.
virtual void UpdateSystemInfo() = 0;
- // Attempt to connect to the preferred network if available and it is set up.
- // This call will return true if connection is started.
- // If the preferred network is not available or not setup, returns false.
- // Note: For dogfood purposes, we hardcode the preferred network to Google-A.
- virtual bool ConnectToPreferredNetworkIfAvailable() = 0;
-
- // Returns true if we are currently connected to the preferred network.
- virtual bool PreferredNetworkConnected() = 0;
-
- // Returns true if we failed to connect to the preferred network.
- virtual bool PreferredNetworkFailed() = 0;
-
// Connect to the specified wireless network with password.
virtual void ConnectToWifiNetwork(WifiNetwork network,
const std::string& password,
@@ -338,7 +344,7 @@ class NetworkLibrary {
virtual void SaveWifiNetwork(const WifiNetwork& network) = 0;
// Forget the passed in wireless (either cellular or wifi) network.
- virtual void ForgetWirelessNetwork(const WirelessNetwork& network) = 0;
+ virtual void ForgetWirelessNetwork(const std::string& service_path) = 0;
virtual bool ethernet_available() const = 0;
virtual bool wifi_available() const = 0;
@@ -369,229 +375,10 @@ class NetworkLibrary {
// Fetches debug network info for display in about:network.
// The page will have a meta refresh of |refresh| seconds if |refresh| > 0.
virtual std::string GetHtmlInfo(int refresh) = 0;
-};
-
-// This class handles the interaction with the ChromeOS network library APIs.
-// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: NetworkLibrary::Get()
-class NetworkLibraryImpl : public NetworkLibrary,
- public URLRequestJobTracker::JobObserver {
- public:
- NetworkLibraryImpl();
- virtual ~NetworkLibraryImpl();
-
- // URLRequestJobTracker::JobObserver methods (called on the IO thread):
- virtual void OnJobAdded(URLRequestJob* job);
- virtual void OnJobRemoved(URLRequestJob* job);
- virtual void OnJobDone(URLRequestJob* job, const URLRequestStatus& status);
- virtual void OnJobRedirect(URLRequestJob* job, const GURL& location,
- int status_code);
- virtual void OnBytesRead(URLRequestJob* job, const char* buf, int byte_count);
-
- // NetworkLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- virtual const EthernetNetwork& ethernet_network() const { return ethernet_; }
- virtual bool ethernet_connecting() const { return ethernet_.connecting(); }
- virtual bool ethernet_connected() const { return ethernet_.connected(); }
-
- virtual const std::string& wifi_name() const { return wifi_.name(); }
- virtual bool wifi_connecting() const { return wifi_.connecting(); }
- virtual bool wifi_connected() const { return wifi_.connected(); }
- virtual int wifi_strength() const { return wifi_.strength(); }
-
- virtual const std::string& cellular_name() const { return cellular_.name(); }
- virtual bool cellular_connecting() const { return cellular_.connecting(); }
- virtual bool cellular_connected() const { return cellular_.connected(); }
- virtual int cellular_strength() const { return cellular_.strength(); }
-
- virtual bool Connected() const;
- virtual bool Connecting() const;
- virtual const std::string& IPAddress() const;
-
- virtual const WifiNetworkVector& wifi_networks() const {
- return wifi_networks_;
- }
-
- virtual const WifiNetworkVector& remembered_wifi_networks() const {
- return remembered_wifi_networks_;
- }
-
- virtual const CellularNetworkVector& cellular_networks() const {
- return cellular_networks_;
- }
-
- virtual const CellularNetworkVector& remembered_cellular_networks() const {
- return remembered_cellular_networks_;
- }
-
- virtual bool FindWifiNetworkByPath(const std::string& path,
- WifiNetwork* network) const;
- virtual bool FindCellularNetworkByPath(const std::string& path,
- CellularNetwork* network) const;
-
- virtual void RequestWifiScan();
- virtual bool GetWifiAccessPoints(WifiAccessPointVector* result);
- virtual bool ConnectToPreferredNetworkIfAvailable();
- virtual bool PreferredNetworkConnected();
- virtual bool PreferredNetworkFailed();
- virtual void ConnectToWifiNetwork(WifiNetwork network,
- const std::string& password,
- const std::string& identity,
- const std::string& certpath);
- virtual void ConnectToWifiNetwork(const std::string& ssid,
- const std::string& password,
- const std::string& identity,
- const std::string& certpath,
- bool auto_connect);
- virtual void ConnectToCellularNetwork(CellularNetwork network);
- virtual void DisconnectFromWirelessNetwork(const WirelessNetwork& network);
- virtual void SaveCellularNetwork(const CellularNetwork& network);
- virtual void SaveWifiNetwork(const WifiNetwork& network);
- virtual void ForgetWirelessNetwork(const WirelessNetwork& network);
-
- virtual bool ethernet_available() const {
- return available_devices_ & (1 << TYPE_ETHERNET);
- }
- virtual bool wifi_available() const {
- return available_devices_ & (1 << TYPE_WIFI);
- }
- virtual bool cellular_available() const {
- return available_devices_ & (1 << TYPE_CELLULAR);
- }
-
- virtual bool ethernet_enabled() const {
- return enabled_devices_ & (1 << TYPE_ETHERNET);
- }
- virtual bool wifi_enabled() const {
- return enabled_devices_ & (1 << TYPE_WIFI);
- }
- virtual bool cellular_enabled() const {
- return enabled_devices_ & (1 << TYPE_CELLULAR);
- }
-
- virtual bool offline_mode() const { return offline_mode_; }
-
- virtual void EnableEthernetNetworkDevice(bool enable);
- virtual void EnableWifiNetworkDevice(bool enable);
- virtual void EnableCellularNetworkDevice(bool enable);
- virtual void EnableOfflineMode(bool enable);
- virtual NetworkIPConfigVector GetIPConfigs(const std::string& device_path);
- virtual std::string GetHtmlInfo(int refresh);
-
- virtual void UpdateSystemInfo();
-
- private:
-
- // This method is called when there's a change in network status.
- // This method is called on a background thread.
- static void NetworkStatusChangedHandler(void* object);
-
- // This parses SystemInfo into:
- // - an EthernetNetwork
- // - a WifiNetworkVector of wifi networks
- // - a CellularNetworkVector of cellular networks.
- // - a WifiNetworkVector of remembered wifi networks
- // - a CellularNetworkVector of remembered cellular networks.
- static void ParseSystem(SystemInfo* system,
- EthernetNetwork* ethernet,
- WifiNetworkVector* wifi_networks,
- CellularNetworkVector* ceullular_networks,
- WifiNetworkVector* remembered_wifi_networks,
- CellularNetworkVector* remembered_ceullular_networks);
-
- // This methods loads the initial list of networks on startup and starts the
- // monitoring of network changes.
- void Init();
-
- // Returns the preferred wifi network.
- WifiNetwork* GetPreferredNetwork();
-
- // Gets the WifiNetwork with the given name. Returns NULL if not found.
- // Only used by GetPreferredNetwork() to lookup "Google" and "GoogleA" (hack)
- WifiNetwork* GetWifiNetworkByName(const std::string& name);
-
- // Gets the WirelessNetwork (WifiNetwork or CellularNetwork) by path
- template<typename T>
- T* GetWirelessNetworkByPath(std::vector<T>& networks,
- const std::string& path);
- template<typename T>
- const T* GetWirelessNetworkByPath(const std::vector<T>& networks,
- const std::string& path) const;
-
- // Enables/disables the specified network device.
- void EnableNetworkDeviceType(ConnectionType device, bool enable);
-
- // Update the cached network status.
- // This will notify all the Observers.
- void UpdateNetworkStatus();
-
- // Checks network traffic to see if there is any uploading.
- // If there is download traffic, then true is passed in for download.
- // If there is network traffic then start timer that invokes
- // NetworkTrafficTimerFired.
- void CheckNetworkTraffic(bool download);
-
- // Called when the timer fires and we need to send out NetworkTraffic
- // notifications.
- void NetworkTrafficTimerFired();
-
- // This is a helper method to notify the observers on the UI thread.
- void NotifyNetworkTraffic(int traffic_type);
-
- // This will notify all obeservers on the UI thread.
- void NotifyObservers();
-
- ObserverList<Observer> observers_;
-
- // The amount of time to wait between each NetworkTraffic notifications.
- static const int kNetworkTrafficeTimerSecs;
-
- // Timer for sending NetworkTraffic notification every
- // kNetworkTrafficeTimerSecs seconds.
- base::OneShotTimer<NetworkLibraryImpl> timer_;
-
- // The current traffic type that will be sent out for the next NetworkTraffic
- // notification. This is a bitfield of TrafficTypeMasks.
- int traffic_type_;
-
- // The network status connection for monitoring network status changes.
- MonitorNetworkConnection network_status_connection_;
-
- // The ethernet network.
- EthernetNetwork ethernet_;
-
- // The list of available wifi networks.
- WifiNetworkVector wifi_networks_;
-
- // The current connected (or connecting) wifi network.
- WifiNetwork wifi_;
-
- // The remembered wifi networks.
- WifiNetworkVector remembered_wifi_networks_;
-
- // The list of available cellular networks.
- CellularNetworkVector cellular_networks_;
-
- // The current connected (or connecting) cellular network.
- CellularNetwork cellular_;
-
- // The remembered cellular networks.
- CellularNetworkVector remembered_cellular_networks_;
-
- // The current available network devices. Bitwise flag of ConnectionTypes.
- int available_devices_;
-
- // The current enabled network devices. Bitwise flag of ConnectionTypes.
- int enabled_devices_;
-
- // The current connected network devices. Bitwise flag of ConnectionTypes.
- int connected_devices_;
-
- bool offline_mode_;
- DISALLOW_COPY_AND_ASSIGN(NetworkLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static NetworkLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/power_library.cc b/chrome/browser/chromeos/cros/power_library.cc
index 42978aa..220cd4e 100644
--- a/chrome/browser/chromeos/cros/power_library.cc
+++ b/chrome/browser/chromeos/cros/power_library.cc
@@ -9,87 +9,129 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::PowerLibraryImpl);
-
namespace chromeos {
-PowerLibraryImpl::PowerLibraryImpl()
- : power_status_connection_(NULL),
- status_(chromeos::PowerStatus()) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- Init();
+class PowerLibraryImpl : public PowerLibrary {
+ public:
+ PowerLibraryImpl()
+ : power_status_connection_(NULL),
+ status_(chromeos::PowerStatus()) {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ Init();
+ }
}
-}
-PowerLibraryImpl::~PowerLibraryImpl() {
- if (power_status_connection_) {
- chromeos::DisconnectPowerStatus(power_status_connection_);
+ ~PowerLibraryImpl() {
+ if (power_status_connection_) {
+ chromeos::DisconnectPowerStatus(power_status_connection_);
+ }
}
-}
-void PowerLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void PowerLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-bool PowerLibraryImpl::line_power_on() const {
- return status_.line_power_on;
-}
+ bool line_power_on() const {
+ return status_.line_power_on;
+ }
-bool PowerLibraryImpl::battery_is_present() const {
- return status_.battery_is_present;
-}
+ bool battery_is_present() const {
+ return status_.battery_is_present;
+ }
-bool PowerLibraryImpl::battery_fully_charged() const {
- return status_.battery_state == chromeos::BATTERY_STATE_FULLY_CHARGED;
-}
+ bool battery_fully_charged() const {
+ return status_.battery_state == chromeos::BATTERY_STATE_FULLY_CHARGED;
+ }
-double PowerLibraryImpl::battery_percentage() const {
- return status_.battery_percentage;
-}
+ double battery_percentage() const {
+ return status_.battery_percentage;
+ }
-base::TimeDelta PowerLibraryImpl::battery_time_to_empty() const {
- return base::TimeDelta::FromSeconds(status_.battery_time_to_empty);
-}
+ base::TimeDelta battery_time_to_empty() const {
+ return base::TimeDelta::FromSeconds(status_.battery_time_to_empty);
+ }
-base::TimeDelta PowerLibraryImpl::battery_time_to_full() const {
- return base::TimeDelta::FromSeconds(status_.battery_time_to_full);
-}
+ base::TimeDelta battery_time_to_full() const {
+ return base::TimeDelta::FromSeconds(status_.battery_time_to_full);
+ }
-// static
-void PowerLibraryImpl::PowerStatusChangedHandler(void* object,
- const chromeos::PowerStatus& status) {
- PowerLibraryImpl* power = static_cast<PowerLibraryImpl*>(object);
- power->UpdatePowerStatus(status);
-}
+ private:
+ static void PowerStatusChangedHandler(void* object,
+ const chromeos::PowerStatus& status) {
+ PowerLibraryImpl* power = static_cast<PowerLibraryImpl*>(object);
+ power->UpdatePowerStatus(status);
+ }
-void PowerLibraryImpl::Init() {
- power_status_connection_ = chromeos::MonitorPowerStatus(
- &PowerStatusChangedHandler, this);
-}
+ void Init() {
+ power_status_connection_ = chromeos::MonitorPowerStatus(
+ &PowerStatusChangedHandler, this);
+ }
-void PowerLibraryImpl::UpdatePowerStatus(const chromeos::PowerStatus& status) {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &PowerLibraryImpl::UpdatePowerStatus, status));
- return;
+ void UpdatePowerStatus(const chromeos::PowerStatus& status) {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &PowerLibraryImpl::UpdatePowerStatus, status));
+ return;
+ }
+
+ DLOG(INFO) << "Power" <<
+ " lpo=" << status.line_power_on <<
+ " sta=" << status.battery_state <<
+ " per=" << status.battery_percentage <<
+ " tte=" << status.battery_time_to_empty <<
+ " ttf=" << status.battery_time_to_full;
+ status_ = status;
+ FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(this));
}
- DLOG(INFO) << "Power" <<
- " lpo=" << status.line_power_on <<
- " sta=" << status.battery_state <<
- " per=" << status.battery_percentage <<
- " tte=" << status.battery_time_to_empty <<
- " ttf=" << status.battery_time_to_full;
- status_ = status;
- FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(this));
+ ObserverList<Observer> observers_;
+
+ // A reference to the battery power api, to allow callbacks when the battery
+ // status changes.
+ chromeos::PowerStatusConnection power_status_connection_;
+
+ // The latest power status.
+ chromeos::PowerStatus status_;
+
+ DISALLOW_COPY_AND_ASSIGN(PowerLibraryImpl);
+};
+
+class PowerLibraryStubImpl : public PowerLibrary {
+ public:
+ PowerLibraryStubImpl() {}
+ ~PowerLibraryStubImpl() {}
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+ bool line_power_on() const { return false; }
+ bool battery_is_present() const { return false; }
+ bool battery_fully_charged() const { return false; }
+ double battery_percentage() const { return false; }
+ base::TimeDelta battery_time_to_empty() const {
+ return base::TimeDelta::FromSeconds(0);
+ }
+ base::TimeDelta battery_time_to_full() const {
+ return base::TimeDelta::FromSeconds(0);
+ }
+};
+
+// static
+PowerLibrary* PowerLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new PowerLibraryStubImpl();
+ else
+ return new PowerLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::PowerLibraryImpl);
+
diff --git a/chrome/browser/chromeos/cros/power_library.h b/chrome/browser/chromeos/cros/power_library.h
index 76ab81a..10e6df4 100644
--- a/chrome/browser/chromeos/cros/power_library.h
+++ b/chrome/browser/chromeos/cros/power_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_POWER_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_POWER_LIBRARY_H_
+#pragma once
#include "base/observer_list.h"
#include "base/singleton.h"
@@ -14,7 +15,7 @@ namespace chromeos {
// This interface defines interaction with the ChromeOS power library APIs.
// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: PowerLibrary::Get()
+// library class like this: chromeos::CrosLibrary::Get()->GetPowerLibrary()
class PowerLibrary {
public:
class Observer {
@@ -41,63 +42,10 @@ class PowerLibrary {
// The amount of time until battery is full.
virtual base::TimeDelta battery_time_to_full() const = 0;
-};
-
-
-// This class handles the interaction with the ChromeOS power library APIs.
-// Classes can add themselves as observers. Users can get an instance of this
-// library class like this: PowerLibrary::Get()
-class PowerLibraryImpl : public PowerLibrary {
- public:
- PowerLibraryImpl();
- virtual ~PowerLibraryImpl();
-
- // PowerLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- // Whether or not the line power is connected.
- virtual bool line_power_on() const;
-
- // Whether or not the battery is fully charged..
- virtual bool battery_fully_charged() const;
-
- // The percentage (0-100) of remaining battery.
- virtual double battery_percentage() const;
-
- // Whether there is a battery present.
- virtual bool battery_is_present() const;
-
- // The amount of time until battery is empty.
- virtual base::TimeDelta battery_time_to_empty() const;
-
- // The amount of time until battery is full.
- virtual base::TimeDelta battery_time_to_full() const;
-
- private:
-
- // This method is called when there's a change in power status.
- // This method is called on a background thread.
- static void PowerStatusChangedHandler(void* object,
- const chromeos::PowerStatus& status);
-
- // This methods starts the monitoring of power changes.
- void Init();
-
- // Called by the handler to update the power status.
- // This will notify all the Observers.
- void UpdatePowerStatus(const chromeos::PowerStatus& status);
-
- ObserverList<Observer> observers_;
-
- // A reference to the battery power api, to allow callbacks when the battery
- // status changes.
- chromeos::PowerStatusConnection power_status_connection_;
-
- // The latest power status.
- chromeos::PowerStatus status_;
- DISALLOW_COPY_AND_ASSIGN(PowerLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static PowerLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/screen_lock_library.cc b/chrome/browser/chromeos/cros/screen_lock_library.cc
index 731ec43..0115683 100644
--- a/chrome/browser/chromeos/cros/screen_lock_library.cc
+++ b/chrome/browser/chromeos/cros/screen_lock_library.cc
@@ -9,135 +9,170 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::ScreenLockLibraryImpl);
-
namespace chromeos {
-ScreenLockLibraryImpl::ScreenLockLibraryImpl() {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- Init();
+// This class handles the interaction with the ChromeOS screen lock APIs.
+class ScreenLockLibraryImpl : public ScreenLockLibrary {
+ public:
+ ScreenLockLibraryImpl() {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ Init();
+ }
}
-}
-ScreenLockLibraryImpl::~ScreenLockLibraryImpl() {
- if (screen_lock_connection_) {
- chromeos::DisconnectScreenLock(screen_lock_connection_);
+ ~ScreenLockLibraryImpl() {
+ if (screen_lock_connection_) {
+ chromeos::DisconnectScreenLock(screen_lock_connection_);
+ }
}
-}
-void ScreenLockLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void ScreenLockLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-void ScreenLockLibraryImpl::NotifyScreenLockRequested() {
- // Make sure we run on IO thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &ScreenLockLibraryImpl::NotifyScreenLockRequested));
- return;
+ void NotifyScreenLockRequested() {
+ // Make sure we run on IO thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ScreenLockLibraryImpl::NotifyScreenLockRequested));
+ return;
+ }
+ chromeos::NotifyScreenLockRequested();
}
- chromeos::NotifyScreenLockRequested();
-}
-void ScreenLockLibraryImpl::NotifyScreenLockCompleted() {
- // Make sure we run on IO thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &ScreenLockLibraryImpl::NotifyScreenLockCompleted));
- return;
+ void NotifyScreenLockCompleted() {
+ // Make sure we run on IO thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ScreenLockLibraryImpl::NotifyScreenLockCompleted));
+ return;
+ }
+ chromeos::NotifyScreenLockCompleted();
}
- chromeos::NotifyScreenLockCompleted();
-}
-void ScreenLockLibraryImpl::NotifyScreenUnlockRequested() {
- // Make sure we run on IO thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &ScreenLockLibraryImpl::NotifyScreenUnlockRequested));
- return;
+ void NotifyScreenUnlockRequested() {
+ // Make sure we run on IO thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ScreenLockLibraryImpl::NotifyScreenUnlockRequested));
+ return;
+ }
+ chromeos::NotifyScreenUnlockRequested();
}
- chromeos::NotifyScreenUnlockRequested();
-}
-void ScreenLockLibraryImpl::NotifyScreenUnlockCompleted() {
- // Make sure we run on IO thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &ScreenLockLibraryImpl::NotifyScreenUnlockCompleted));
- return;
+ void NotifyScreenUnlockCompleted() {
+ // Make sure we run on IO thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ScreenLockLibraryImpl::NotifyScreenUnlockCompleted));
+ return;
+ }
+ chromeos::NotifyScreenUnlockCompleted();
}
- chromeos::NotifyScreenUnlockCompleted();
-}
-void ScreenLockLibraryImpl::Init() {
- screen_lock_connection_ = chromeos::MonitorScreenLock(
- &ScreenLockedHandler, this);
-}
+ private:
+ void Init() {
+ screen_lock_connection_ = chromeos::MonitorScreenLock(
+ &ScreenLockedHandler, this);
+ }
-void ScreenLockLibraryImpl::LockScreen() {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &ScreenLockLibraryImpl::LockScreen));
- return;
+ void LockScreen() {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &ScreenLockLibraryImpl::LockScreen));
+ return;
+ }
+ FOR_EACH_OBSERVER(Observer, observers_, LockScreen(this));
}
- FOR_EACH_OBSERVER(Observer, observers_, LockScreen(this));
-}
-void ScreenLockLibraryImpl::UnlockScreen() {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &ScreenLockLibraryImpl::UnlockScreen));
- return;
+ void UnlockScreen() {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &ScreenLockLibraryImpl::UnlockScreen));
+ return;
+ }
+ FOR_EACH_OBSERVER(Observer, observers_, UnlockScreen(this));
}
- FOR_EACH_OBSERVER(Observer, observers_, UnlockScreen(this));
-}
-void ScreenLockLibraryImpl::UnlockScreenFailed() {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &ScreenLockLibraryImpl::UnlockScreenFailed));
- return;
+ void UnlockScreenFailed() {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &ScreenLockLibraryImpl::UnlockScreenFailed));
+ return;
+ }
+ FOR_EACH_OBSERVER(Observer, observers_, UnlockScreenFailed(this));
}
- FOR_EACH_OBSERVER(Observer, observers_, UnlockScreenFailed(this));
-}
-// static
-void ScreenLockLibraryImpl::ScreenLockedHandler(void* object,
- ScreenLockEvent event) {
- ScreenLockLibraryImpl* self = static_cast<ScreenLockLibraryImpl*>(object);
- switch (event) {
- case chromeos::LockScreen:
- self->LockScreen();
- break;
- case chromeos::UnlockScreen:
- self->UnlockScreen();
- break;
- case chromeos::UnlockScreenFailed:
- self->UnlockScreenFailed();
- break;
- default:
- NOTREACHED();
+ static void ScreenLockedHandler(void* object, ScreenLockEvent event) {
+ ScreenLockLibraryImpl* self = static_cast<ScreenLockLibraryImpl*>(object);
+ switch (event) {
+ case chromeos::LockScreen:
+ self->LockScreen();
+ break;
+ case chromeos::UnlockScreen:
+ self->UnlockScreen();
+ break;
+ case chromeos::UnlockScreenFailed:
+ self->UnlockScreenFailed();
+ break;
+ default:
+ NOTREACHED();
+ }
}
+
+ ObserverList<Observer> observers_;
+
+ // A reference to the screen lock api
+ chromeos::ScreenLockConnection screen_lock_connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenLockLibraryImpl);
+};
+
+class ScreenLockLibraryStubImpl : public ScreenLockLibrary {
+ public:
+ ScreenLockLibraryStubImpl() {}
+ ~ScreenLockLibraryStubImpl() {}
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+ void NotifyScreenLockRequested() {}
+ void NotifyScreenLockCompleted() {}
+ void NotifyScreenUnlockRequested() {}
+ void NotifyScreenUnlockCompleted() {}
+};
+
+// static
+ScreenLockLibrary* ScreenLockLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new ScreenLockLibraryStubImpl();
+ else
+ return new ScreenLockLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::ScreenLockLibraryImpl);
+
diff --git a/chrome/browser/chromeos/cros/screen_lock_library.h b/chrome/browser/chromeos/cros/screen_lock_library.h
index 829d156..251c6f4 100644
--- a/chrome/browser/chromeos/cros/screen_lock_library.h
+++ b/chrome/browser/chromeos/cros/screen_lock_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SCREEN_LOCK_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SCREEN_LOCK_LIBRARY_H_
+#pragma once
#include "base/observer_list.h"
#include "cros/chromeos_screen_lock.h"
@@ -34,48 +35,10 @@ class ScreenLockLibrary {
virtual void NotifyScreenUnlockRequested() = 0;
// Notifies PowerManager that screen is unlocked.
virtual void NotifyScreenUnlockCompleted() = 0;
-};
-
-// This class handles the interaction with the ChromeOS screen lock APIs.
-class ScreenLockLibraryImpl : public ScreenLockLibrary {
- public:
- ScreenLockLibraryImpl();
- virtual ~ScreenLockLibraryImpl();
-
- // ScreenLockLibrary implementations:
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
- virtual void NotifyScreenLockRequested();
- virtual void NotifyScreenLockCompleted();
- virtual void NotifyScreenUnlockRequested();
- virtual void NotifyScreenUnlockCompleted();
-
- private:
- // This method is called when PowerManager requests to lock the screen.
- // This method is called on a background thread.
- static void ScreenLockedHandler(void* object, ScreenLockEvent event);
-
- // This methods starts the monitoring of screen lock request.
- void Init();
-
- // Called by the handler to notify the screen lock request from
- // SessionManager.
- void LockScreen();
-
- // Called by the handler to notify the screen unlock request from
- // SessionManager.
- void UnlockScreen();
-
- // Called by the handler to notify the screen unlock request has been
- // failed.
- void UnlockScreenFailed();
-
- ObserverList<Observer> observers_;
-
- // A reference to the screen lock api
- chromeos::ScreenLockConnection screen_lock_connection_;
- DISALLOW_COPY_AND_ASSIGN(ScreenLockLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static ScreenLockLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/speech_synthesis_library.cc b/chrome/browser/chromeos/cros/speech_synthesis_library.cc
index 10194ee..0325c1f 100644
--- a/chrome/browser/chromeos/cros/speech_synthesis_library.cc
+++ b/chrome/browser/chromeos/cros/speech_synthesis_library.cc
@@ -11,24 +11,55 @@
namespace chromeos {
-bool SpeechSynthesisLibraryImpl::Speak(const char* text) {
- return chromeos::Speak(text);
-}
+class SpeechSynthesisLibraryImpl : public SpeechSynthesisLibrary {
+ public:
+ SpeechSynthesisLibraryImpl() {}
+ virtual ~SpeechSynthesisLibraryImpl() {}
-bool SpeechSynthesisLibraryImpl::SetSpeakProperties(const char* props) {
- return chromeos::SetSpeakProperties(props);
-}
+ bool Speak(const char* text) {
+ return chromeos::Speak(text);
+ }
-bool SpeechSynthesisLibraryImpl::StopSpeaking() {
- return chromeos::StopSpeaking();
-}
+ bool SetSpeakProperties(const char* props) {
+ return chromeos::SetSpeakProperties(props);
+ }
-bool SpeechSynthesisLibraryImpl::IsSpeaking() {
- return chromeos::IsSpeaking();
-}
+ bool StopSpeaking() {
+ return chromeos::StopSpeaking();
+ }
+
+ bool IsSpeaking() {
+ return chromeos::IsSpeaking();
+ }
+
+ void InitTts(InitStatusCallback callback) {
+ chromeos::InitTts(callback);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SpeechSynthesisLibraryImpl);
+};
+
+class SpeechSynthesisLibraryStubImpl : public SpeechSynthesisLibrary {
+ public:
+ SpeechSynthesisLibraryStubImpl() {}
+ virtual ~SpeechSynthesisLibraryStubImpl() {}
+ bool Speak(const char* text) { return true; }
+ bool SetSpeakProperties(const char* props) { return true; }
+ bool StopSpeaking() { return true; }
+ bool IsSpeaking() { return false; }
+ void InitTts(InitStatusCallback callback) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SpeechSynthesisLibraryStubImpl);
+};
-void SpeechSynthesisLibraryImpl::InitTts(InitStatusCallback callback) {
- chromeos::InitTts(callback);
+// static
+SpeechSynthesisLibrary* SpeechSynthesisLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new SpeechSynthesisLibraryStubImpl();
+ else
+ return new SpeechSynthesisLibraryImpl();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/speech_synthesis_library.h b/chrome/browser/chromeos/cros/speech_synthesis_library.h
index 10f2c11..5ba97d1 100644
--- a/chrome/browser/chromeos/cros/speech_synthesis_library.h
+++ b/chrome/browser/chromeos/cros/speech_synthesis_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SPEECH_SYNTHESIS_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SPEECH_SYNTHESIS_LIBRARY_H_
+#pragma once
#include "base/singleton.h"
@@ -26,23 +27,10 @@ class SpeechSynthesisLibrary {
// Starts the speech synthesis service and indicates through a callback if
// it started successfully.
virtual void InitTts(InitStatusCallback) = 0;
-};
-// This class handles the interaction with the ChromeOS login library APIs.
-class SpeechSynthesisLibraryImpl : public SpeechSynthesisLibrary {
- public:
- SpeechSynthesisLibraryImpl() {}
- virtual ~SpeechSynthesisLibraryImpl() {}
-
- // SpeechSynthesisLibrary overrides.
- virtual bool Speak(const char* text);
- virtual bool SetSpeakProperties(const char* props);
- virtual bool StopSpeaking();
- virtual bool IsSpeaking();
- virtual void InitTts(InitStatusCallback);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpeechSynthesisLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static SpeechSynthesisLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/synaptics_library.cc b/chrome/browser/chromeos/cros/synaptics_library.cc
deleted file mode 100644
index 462be76..0000000
--- a/chrome/browser/chromeos/cros/synaptics_library.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2009 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/chromeos/cros/synaptics_library.h"
-
-#include "base/message_loop.h"
-#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-
-namespace chromeos {
-
-void SynapticsLibraryImpl::SetBoolParameter(SynapticsParameter param,
- bool value) {
- SetParameter(param, value ? 1 : 0);
-}
-
-void SynapticsLibraryImpl::SetRangeParameter(SynapticsParameter param,
- int value) {
- if (value < 1)
- value = 1;
- if (value > 10)
- value = 10;
- SetParameter(param, value);
-}
-
-void SynapticsLibraryImpl::SetParameter(SynapticsParameter param, int value) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- // This calls SetSynapticsParameter in the cros library which is
- // potentially time consuming. So we run this on the FILE thread.
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(&SetSynapticsParameter, param, value));
- }
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/synaptics_library.h b/chrome/browser/chromeos/cros/synaptics_library.h
deleted file mode 100644
index 3dfd69f..0000000
--- a/chrome/browser/chromeos/cros/synaptics_library.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2009 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_CROS_SYNAPTICS_LIBRARY_H_
-#define CHROME_BROWSER_CHROMEOS_CROS_SYNAPTICS_LIBRARY_H_
-
-#include "base/singleton.h"
-#include "cros/chromeos_synaptics.h"
-
-namespace chromeos {
-
-// This interface defines interaction with the ChromeOS synaptics library APIs.
-// Users can get an instance of this library class like this:
-// SynapticsLibrary::Get()
-// For a list of SynapticsPrameters, see chromeos_synaptics.h
-// in third_party/cros or /usr/include/cros
-class SynapticsLibrary {
- public:
- virtual ~SynapticsLibrary() {}
- // Sets a boolean parameter. The actual call will be run on the FILE thread.
- virtual void SetBoolParameter(SynapticsParameter param, bool value) = 0;
-
- // Sets a range parameter. The actual call will be run on the FILE thread.
- // Value should be between 1 and 10 inclusive.
- virtual void SetRangeParameter(SynapticsParameter param, int value) = 0;
-};
-
-
-// This class handles the interaction with the ChromeOS synaptics library APIs.
-// Users can get an instance of this library class like this:
-// SynapticsLibrary::Get()
-// For a list of SynapticsPrameters, see chromeos_synaptics.h
-// in third_party/cros or /usr/include/cros
-class SynapticsLibraryImpl : public SynapticsLibrary {
- public:
- SynapticsLibraryImpl() {}
- virtual ~SynapticsLibraryImpl() {}
-
- // SynapticsLibrary overrides.
- virtual void SetBoolParameter(SynapticsParameter param, bool value);
- virtual void SetRangeParameter(SynapticsParameter param, int value);
-
- private:
-
- // This helper methods calls into the libcros library to set the parameter.
- // This call is run on the FILE thread.
- void SetParameter(SynapticsParameter param, int value);
-
- DISALLOW_COPY_AND_ASSIGN(SynapticsLibraryImpl);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_CROS_SYNAPTICS_LIBRARY_H_
diff --git a/chrome/browser/chromeos/cros/syslogs_library.cc b/chrome/browser/chromeos/cros/syslogs_library.cc
index 365e9fe..9fed176 100644
--- a/chrome/browser/chromeos/cros/syslogs_library.cc
+++ b/chrome/browser/chromeos/cros/syslogs_library.cc
@@ -10,11 +10,74 @@
namespace chromeos {
-LogDictionaryType* SyslogsLibraryImpl::GetSyslogs(FilePath* tmpfilename) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- return chromeos::GetSystemLogs(tmpfilename);
+class SyslogsLibraryImpl : public SyslogsLibrary {
+ public:
+ SyslogsLibraryImpl() {}
+ virtual ~SyslogsLibraryImpl() {}
+
+ virtual Handle RequestSyslogs(FilePath* tmpfilename,
+ CancelableRequestConsumerBase* consumer,
+ ReadCompleteCallback* callback) {
+ // Register the callback request.
+ scoped_refptr<CancelableRequest<ReadCompleteCallback> > request(
+ new CancelableRequest<ReadCompleteCallback>(callback));
+ AddRequest(request, consumer);
+
+ // Schedule a task on the FILE thread which will then trigger a request
+ // callback on the calling thread (e.g. UI) when complete.
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this, &SyslogsLibraryImpl::ReadSyslogs, request, tmpfilename));
+
+ return request->handle();
+ }
+
+ private:
+ // Called from FILE thread.
+ void ReadSyslogs(
+ scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
+ FilePath* tmpfilename) {
+ if (request->canceled())
+ return;
+
+ LogDictionaryType* logs = NULL;
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ logs = chromeos::GetSystemLogs(tmpfilename);
+ }
+
+ // Will call the callback on the calling thread.
+ request->ForwardResult(Tuple1<LogDictionaryType*>(logs));
}
- return NULL;
+
+ DISALLOW_COPY_AND_ASSIGN(SyslogsLibraryImpl);
+};
+
+class SyslogsLibraryStubImpl : public SyslogsLibrary {
+ public:
+ SyslogsLibraryStubImpl() {}
+ virtual ~SyslogsLibraryStubImpl() {}
+
+ virtual Handle RequestSyslogs(FilePath* tmpfilename,
+ CancelableRequestConsumerBase* consumer,
+ ReadCompleteCallback* callback) {
+ if (callback)
+ callback->Run(Tuple1<LogDictionaryType*>(NULL));
+
+ return 0;
+ }
+};
+
+// static
+SyslogsLibrary* SyslogsLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new SyslogsLibraryStubImpl();
+ else
+ return new SyslogsLibraryImpl();
}
} // namespace chromeos
+
+// Allows InvokeLater without adding refcounting. SyslogsLibraryImpl is a
+// Singleton and won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::SyslogsLibraryImpl);
diff --git a/chrome/browser/chromeos/cros/syslogs_library.h b/chrome/browser/chromeos/cros/syslogs_library.h
index e29824c..56a07f7 100644
--- a/chrome/browser/chromeos/cros/syslogs_library.h
+++ b/chrome/browser/chromeos/cros/syslogs_library.h
@@ -4,33 +4,36 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SYSLOGS_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SYSLOGS_LIBRARY_H_
+#pragma once
#include "base/singleton.h"
+#include "chrome/browser/cancelable_request.h"
#include "cros/chromeos_syslogs.h"
+class CancelableRequestConsumerBase;
+
namespace chromeos {
// This interface defines interaction with the ChromeOS syslogs APIs.
-class SyslogsLibrary {
+class SyslogsLibrary : public CancelableRequestProvider {
public:
+ typedef Callback1<LogDictionaryType*>::Type ReadCompleteCallback;
+
SyslogsLibrary() {}
virtual ~SyslogsLibrary() {}
- // System logs gathered for userfeedback
- virtual LogDictionaryType* GetSyslogs(FilePath* tmpfilename) = 0;
-};
-
-
-// This class handles the interaction with the ChromeOS syslogs APIs.
-class SyslogsLibraryImpl : public SyslogsLibrary {
- public:
- SyslogsLibraryImpl() {}
- virtual ~SyslogsLibraryImpl() {}
-
- virtual LogDictionaryType* GetSyslogs(FilePath* tmpfilename);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SyslogsLibraryImpl);
+ // Request system logs. Read happens on the FILE thread and callback is
+ // called on the thread this is called from (via ForwardResult).
+ // Logs are owned by callback function (use delete when done with them).
+ // Returns the request handle. Call CancelRequest(Handle) to cancel
+ // the request before the callback gets called.
+ virtual Handle RequestSyslogs(FilePath* tmpfilename,
+ CancelableRequestConsumerBase* consumer,
+ ReadCompleteCallback* callback) = 0;
+
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static SyslogsLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/system_library.cc b/chrome/browser/chromeos/cros/system_library.cc
index 7f528d1..b14e38e 100644
--- a/chrome/browser/chromeos/cros/system_library.cc
+++ b/chrome/browser/chromeos/cros/system_library.cc
@@ -4,52 +4,129 @@
#include "chrome/browser/chromeos/cros/system_library.h"
+#include <map>
+
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
namespace chromeos {
-SystemLibraryImpl::SystemLibraryImpl() {
- std::string id = "US/Pacific";
- if (CrosLibrary::Get()->EnsureLoaded()) {
- std::string timezone_id = chromeos::GetTimezoneID();
- if (timezone_id.empty()) {
- LOG(ERROR) << "Got an empty string for timezone, default to " << id;
- } else {
- id = timezone_id;
+class SystemLibraryImpl : public SystemLibrary {
+ public:
+ typedef std::map<std::string, std::string> StringMap;
+
+ SystemLibraryImpl() {
+ // Get Statistics
+ UpdateMachineStatistics();
+ // Get Timezone
+ std::string id = "US/Pacific";
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ std::string timezone_id = chromeos::GetTimezoneID();
+ if (timezone_id.empty()) {
+ LOG(ERROR) << "Got an empty string for timezone, default to " << id;
+ } else {
+ id = timezone_id;
+ }
}
+ icu::TimeZone* timezone =
+ icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id));
+ timezone_.reset(timezone);
+ icu::TimeZone::setDefault(*timezone);
+ LOG(INFO) << "Timezone is " << id;
}
- icu::TimeZone* timezone =
- icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id));
- timezone_.reset(timezone);
- icu::TimeZone::setDefault(*timezone);
- LOG(INFO) << "Timezone is " << id;
-}
-void SystemLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void SystemLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-const icu::TimeZone& SystemLibraryImpl::GetTimezone() {
- return *timezone_.get();
-}
+ const icu::TimeZone& GetTimezone() {
+ return *timezone_.get();
+ }
+
+ void SetTimezone(const icu::TimeZone* timezone) {
+ timezone_.reset(timezone->clone());
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ icu::UnicodeString unicode;
+ timezone->getID(unicode);
+ std::string id;
+ UTF16ToUTF8(unicode.getBuffer(), unicode.length(), &id);
+ LOG(INFO) << "Setting timezone to " << id;
+ chromeos::SetTimezoneID(id);
+ }
+ icu::TimeZone::setDefault(*timezone);
+ FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(*timezone));
+ }
+
+ bool GetMachineStatistic(const std::string& name, std::string* result) {
+ StringMap::iterator iter = machine_info_.find(name);
+ if (iter != machine_info_.end()) {
+ *result = iter->second;
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ void UpdateMachineStatistics() {
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ chromeos::MachineInfo* machine_info = chromeos::GetMachineInfo();
+ if (!machine_info) {
+ LOG(ERROR) << "Error calling chromeos::GetMachineInfo().";
+ return;
+ }
+ // Get Name Value pairs.
+ for (int i = 0; i<machine_info->name_value_size; ++i) {
+ const chromeos::MachineInfo::NVPair& nv = machine_info->name_values[i];
+ machine_info_[nv.name] = nv.value;
+ }
+ chromeos::FreeMachineInfo(machine_info);
+ }
+ }
+
+ scoped_ptr<icu::TimeZone> timezone_;
+ ObserverList<Observer> observers_;
+ StringMap machine_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemLibraryImpl);
+};
+
+class SystemLibraryStubImpl : public SystemLibrary {
+ public:
+ SystemLibraryStubImpl() {
+ std::string id = "US/Pacific";
+ icu::TimeZone* timezone =
+ icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id));
+ timezone_.reset(timezone);
+ }
+ ~SystemLibraryStubImpl() {}
+
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+ const icu::TimeZone& GetTimezone() {
+ return *timezone_.get();
+ }
+ void SetTimezone(const icu::TimeZone* timezone) {}
+
+ bool GetMachineStatistic(const std::string& name, std::string* result) {
+ *result = "Stub Statistic:" + name;
+ return true;
+ }
+
+ private:
+ scoped_ptr<icu::TimeZone> timezone_;
+ DISALLOW_COPY_AND_ASSIGN(SystemLibraryStubImpl);
+};
-void SystemLibraryImpl::SetTimezone(const icu::TimeZone* timezone) {
- timezone_.reset(timezone->clone());
- if (CrosLibrary::Get()->EnsureLoaded()) {
- icu::UnicodeString unicode;
- timezone->getID(unicode);
- std::string id;
- UTF16ToUTF8(unicode.getBuffer(), unicode.length(), &id);
- LOG(INFO) << "Setting timezone to " << id;
- chromeos::SetTimezoneID(id);
- }
- icu::TimeZone::setDefault(*timezone);
- FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(*timezone));
+// static
+SystemLibrary* SystemLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new SystemLibraryStubImpl();
+ else
+ return new SystemLibraryImpl();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/system_library.h b/chrome/browser/chromeos/cros/system_library.h
index b33eb3d..9cf6640 100644
--- a/chrome/browser/chromeos/cros/system_library.h
+++ b/chrome/browser/chromeos/cros/system_library.h
@@ -4,9 +4,9 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SYSTEM_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SYSTEM_LIBRARY_H_
+#pragma once
#include "base/observer_list.h"
-#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "cros/chromeos_system.h"
#include "unicode/timezone.h"
@@ -32,26 +32,15 @@ class SystemLibrary {
// Sets the current timezone. |timezone| must be non-null.
virtual void SetTimezone(const icu::TimeZone* timezone) = 0;
-};
-
-// This class handles the interaction with the ChromeOS syslogs APIs.
-class SystemLibraryImpl : public SystemLibrary {
- public:
- SystemLibraryImpl();
- virtual ~SystemLibraryImpl() {}
-
- // NetworkLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- virtual const icu::TimeZone& GetTimezone();
- virtual void SetTimezone(const icu::TimeZone*);
- private:
- scoped_ptr<icu::TimeZone> timezone_;
- ObserverList<Observer> observers_;
+ // Retrieve the named machine statistic (e.g. "hardware_class").
+ // This does not update the statistcs (i.e. does not call into libcros).
+ virtual bool GetMachineStatistic(const std::string& name,
+ std::string* result) = 0;
- DISALLOW_COPY_AND_ASSIGN(SystemLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static SystemLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros/update_library.cc b/chrome/browser/chromeos/cros/update_library.cc
index 0ea5f2c..26a11ef 100644
--- a/chrome/browser/chromeos/cros/update_library.cc
+++ b/chrome/browser/chromeos/cros/update_library.cc
@@ -9,60 +9,114 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-// Allows InvokeLater without adding refcounting. This class is a Singleton and
-// won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::UpdateLibraryImpl);
-
namespace chromeos {
-UpdateLibraryImpl::UpdateLibraryImpl()
+class UpdateLibraryImpl : public UpdateLibrary {
+ public:
+ UpdateLibraryImpl()
: status_connection_(NULL) {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- Init();
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ Init();
+ }
}
-}
-UpdateLibraryImpl::~UpdateLibraryImpl() {
- if (status_connection_) {
- DisconnectUpdateProgress(status_connection_);
+ ~UpdateLibraryImpl() {
+ if (status_connection_) {
+ DisconnectUpdateProgress(status_connection_);
+ }
}
-}
-void UpdateLibraryImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
-void UpdateLibraryImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
-const UpdateLibrary::Status& UpdateLibraryImpl::status() const {
- return status_;
-}
+ bool CheckForUpdate() {
+ if (!CrosLibrary::Get()->EnsureLoaded())
+ return false;
-// static
-void UpdateLibraryImpl::ChangedHandler(void* object,
- const UpdateProgress& status) {
- UpdateLibraryImpl* power = static_cast<UpdateLibraryImpl*>(object);
- power->UpdateStatus(Status(status));
-}
+ return InitiateUpdateCheck();
+ }
-void UpdateLibraryImpl::Init() {
- status_connection_ = MonitorUpdateStatus(&ChangedHandler, this);
-}
+ bool RebootAfterUpdate() {
+ if (!CrosLibrary::Get()->EnsureLoaded())
+ return false;
+
+ return RebootIfUpdated();
+ }
+
+ const UpdateLibrary::Status& status() const {
+ return status_;
+ }
-void UpdateLibraryImpl::UpdateStatus(const Status& status) {
- // Make sure we run on UI thread.
- if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &UpdateLibraryImpl::UpdateStatus, status));
- return;
+ private:
+ static void ChangedHandler(void* object,
+ const UpdateProgress& status) {
+ UpdateLibraryImpl* updater = static_cast<UpdateLibraryImpl*>(object);
+ updater->UpdateStatus(Status(status));
}
- status_ = status;
- FOR_EACH_OBSERVER(Observer, observers_, Changed(this));
+ void Init() {
+ status_connection_ = MonitorUpdateStatus(&ChangedHandler, this);
+ }
+
+ void UpdateStatus(const Status& status) {
+ // Make sure we run on UI thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &UpdateLibraryImpl::UpdateStatus, status));
+ return;
+ }
+
+ status_ = status;
+ FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(this));
+ }
+
+ ObserverList<Observer> observers_;
+
+ // A reference to the update api, to allow callbacks when the update
+ // status changes.
+ UpdateStatusConnection status_connection_;
+
+ // The latest power status.
+ Status status_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateLibraryImpl);
+};
+
+class UpdateLibraryStubImpl : public UpdateLibrary {
+ public:
+ UpdateLibraryStubImpl() {}
+ ~UpdateLibraryStubImpl() {}
+ void AddObserver(Observer* observer) {}
+ void RemoveObserver(Observer* observer) {}
+ bool CheckForUpdate() { return false; }
+ bool RebootAfterUpdate() { return false; }
+ const UpdateLibrary::Status& status() const {
+ return status_;
+ }
+
+ private:
+ Status status_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateLibraryStubImpl);
+};
+
+// static
+UpdateLibrary* UpdateLibrary::GetImpl(bool stub) {
+ if (stub)
+ return new UpdateLibraryStubImpl();
+ else
+ return new UpdateLibraryImpl();
}
} // namespace chromeos
+// Allows InvokeLater without adding refcounting. This class is a Singleton and
+// won't be deleted until it's last InvokeLater is run.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::UpdateLibraryImpl);
+
diff --git a/chrome/browser/chromeos/cros/update_library.h b/chrome/browser/chromeos/cros/update_library.h
index c57e7bd..7b95815 100644
--- a/chrome/browser/chromeos/cros/update_library.h
+++ b/chrome/browser/chromeos/cros/update_library.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_UPDATE_LIBRARY_H_
#define CHROME_BROWSER_CHROMEOS_CROS_UPDATE_LIBRARY_H_
+#pragma once
#include <string>
@@ -52,50 +53,26 @@ class UpdateLibrary {
class Observer {
public:
virtual ~Observer() { }
- virtual void Changed(UpdateLibrary* obj) = 0;
+ virtual void UpdateStatusChanged(UpdateLibrary* library) = 0;
};
+// static UpdateLibrary* GetStubImplementation();
+
virtual ~UpdateLibrary() {}
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
- virtual const Status& status() const = 0;
-};
-
-class UpdateLibraryImpl : public UpdateLibrary {
- public:
- UpdateLibraryImpl();
- virtual ~UpdateLibraryImpl();
-
- // UpdateLibrary overrides.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- virtual const Status& status() const;
+ // Initiates update check and returns true if check was initiated.
+ virtual bool CheckForUpdate() = 0;
- private:
+ // Reboots if update has been performed.
+ virtual bool RebootAfterUpdate() = 0;
- // This method is called when there's a change in status.
- // This method is called on a background thread.
- static void ChangedHandler(void* object, const UpdateProgress& status);
-
- // This methods starts the monitoring of power changes.
- void Init();
-
- // Called by the handler to update the power status.
- // This will notify all the Observers.
- void UpdateStatus(const Status& status);
-
- ObserverList<Observer> observers_;
-
- // A reference to the update api, to allow callbacks when the update
- // status changes.
- UpdateStatusConnection status_connection_;
-
- // The latest power status.
- Status status_;
+ virtual const Status& status() const = 0;
- DISALLOW_COPY_AND_ASSIGN(UpdateLibraryImpl);
+ // Factory function, creates a new instance and returns ownership.
+ // For normal usage, access the singleton via CrosLibrary::Get().
+ static UpdateLibrary* GetImpl(bool stub);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros_settings.cc b/chrome/browser/chromeos/cros_settings.cc
index 852ad9d..a0e1297 100644
--- a/chrome/browser/chromeos/cros_settings.cc
+++ b/chrome/browser/chromeos/cros_settings.cc
@@ -6,38 +6,63 @@
#include "base/singleton.h"
#include "base/string_util.h"
-#include "chrome/browser/chromeos/mock_cros_settings.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/cros_settings_provider.h"
+#include "chrome/browser/chromeos/cros_settings_provider_user.h"
+#include "chrome/common/notification_service.h"
namespace chromeos {
CrosSettings* CrosSettings::Get() {
// TODO(xiyaun): Use real stuff when underlying libcros is ready.
- return Singleton<MockCrosSettings>::get();
+ return Singleton<CrosSettings>::get();
}
-bool CrosSettings::IsCrosSettings(const std::wstring& path) {
- return StartsWith(path, kCrosSettingsPrefix, true);
+bool CrosSettings::IsCrosSettings(const std::string& path) {
+ return StartsWithASCII(path, kCrosSettingsPrefix, true);
}
-void CrosSettings::SetBoolean(const std::wstring& path, bool in_value) {
+void CrosSettings::FireObservers(const char* path) {
+ DCHECK(CalledOnValidThread());
+ std::string path_str(path);
+ SettingsObserverMap::iterator observer_iterator =
+ settings_observers_.find(path_str);
+ if (observer_iterator == settings_observers_.end())
+ return;
+
+ NotificationObserverList::Iterator it(*(observer_iterator->second));
+ NotificationObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ observer->Observe(NotificationType::SYSTEM_SETTING_CHANGED,
+ Source<CrosSettings>(this),
+ Details<std::string>(&path_str));
+ }
+}
+
+void CrosSettings::SetBoolean(const std::string& path, bool in_value) {
+ DCHECK(CalledOnValidThread());
Set(path, Value::CreateBooleanValue(in_value));
}
-void CrosSettings::SetInteger(const std::wstring& path, int in_value) {
+void CrosSettings::SetInteger(const std::string& path, int in_value) {
+ DCHECK(CalledOnValidThread());
Set(path, Value::CreateIntegerValue(in_value));
}
-void CrosSettings::SetReal(const std::wstring& path, double in_value) {
+void CrosSettings::SetReal(const std::string& path, double in_value) {
+ DCHECK(CalledOnValidThread());
Set(path, Value::CreateRealValue(in_value));
}
-void CrosSettings::SetString(const std::wstring& path,
+void CrosSettings::SetString(const std::string& path,
const std::string& in_value) {
+ DCHECK(CalledOnValidThread());
Set(path, Value::CreateStringValue(in_value));
}
-bool CrosSettings::GetBoolean(const std::wstring& path,
+bool CrosSettings::GetBoolean(const std::string& path,
bool* bool_value) const {
+ DCHECK(CalledOnValidThread());
Value* value;
if (!Get(path, &value))
return false;
@@ -45,8 +70,105 @@ bool CrosSettings::GetBoolean(const std::wstring& path,
return value->GetAsBoolean(bool_value);
}
-bool CrosSettings::GetInteger(const std::wstring& path,
+bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) {
+ DCHECK(CalledOnValidThread());
+ providers_.push_back(provider);
+ return true;
+}
+
+bool CrosSettings::RemoveSettingsProvider(CrosSettingsProvider* provider) {
+ DCHECK(CalledOnValidThread());
+ std::vector<CrosSettingsProvider*>::iterator it =
+ std::find(providers_.begin(), providers_.end(), provider);
+ if (it != providers_.end()) {
+ providers_.erase(it);
+ return true;
+ }
+ return false;
+}
+
+void CrosSettings::AddSettingsObserver(const char* path,
+ NotificationObserver* obs) {
+ DCHECK(path);
+ DCHECK(obs);
+ DCHECK(CalledOnValidThread());
+
+ if (!GetProvider(std::string(path))) {
+ NOTREACHED() << "Trying to add an observer for an unregistered setting: "
+ << path;
+ return;
+ }
+
+ // Get the settings observer list associated with the path.
+ NotificationObserverList* observer_list = NULL;
+ SettingsObserverMap::iterator observer_iterator =
+ settings_observers_.find(path);
+ if (observer_iterator == settings_observers_.end()) {
+ observer_list = new NotificationObserverList;
+ settings_observers_[path] = observer_list;
+ } else {
+ observer_list = observer_iterator->second;
+ }
+
+ // Verify that this observer doesn't already exist.
+ NotificationObserverList::Iterator it(*observer_list);
+ NotificationObserver* existing_obs;
+ while ((existing_obs = it.GetNext()) != NULL) {
+ DCHECK(existing_obs != obs) << path << " observer already registered";
+ if (existing_obs == obs)
+ return;
+ }
+
+ // Ok, safe to add the pref observer.
+ observer_list->AddObserver(obs);
+}
+
+void CrosSettings::RemoveSettingsObserver(const char* path,
+ NotificationObserver* obs) {
+ DCHECK(CalledOnValidThread());
+
+ SettingsObserverMap::iterator observer_iterator =
+ settings_observers_.find(path);
+ if (observer_iterator == settings_observers_.end()) {
+ return;
+ }
+
+ NotificationObserverList* observer_list = observer_iterator->second;
+ observer_list->RemoveObserver(obs);
+}
+
+CrosSettingsProvider* CrosSettings::GetProvider(
+ const std::string& path) const {
+ for (size_t i = 0; i < providers_.size(); ++i) {
+ if (providers_[i]->HandlesSetting(path)){
+ return providers_[i];
+ }
+ }
+ return NULL;
+}
+
+void CrosSettings::Set(const std::string& path, Value* in_value) {
+ DCHECK(CalledOnValidThread());
+ CrosSettingsProvider* provider;
+ provider = GetProvider(path);
+ if (provider) {
+ provider->Set(path, in_value);
+ }
+}
+
+bool CrosSettings::Get(const std::string& path, Value** out_value) const {
+ DCHECK(CalledOnValidThread());
+ CrosSettingsProvider* provider;
+ provider = GetProvider(path);
+ if (provider) {
+ return provider->Get(path, out_value);
+ }
+ return false;
+}
+
+bool CrosSettings::GetInteger(const std::string& path,
int* out_value) const {
+ DCHECK(CalledOnValidThread());
Value* value;
if (!Get(path, &value))
return false;
@@ -54,8 +176,9 @@ bool CrosSettings::GetInteger(const std::wstring& path,
return value->GetAsInteger(out_value);
}
-bool CrosSettings::GetReal(const std::wstring& path,
+bool CrosSettings::GetReal(const std::string& path,
double* out_value) const {
+ DCHECK(CalledOnValidThread());
Value* value;
if (!Get(path, &value))
return false;
@@ -63,8 +186,9 @@ bool CrosSettings::GetReal(const std::wstring& path,
return value->GetAsReal(out_value);
}
-bool CrosSettings::GetString(const std::wstring& path,
+bool CrosSettings::GetString(const std::string& path,
std::string* out_value) const {
+ DCHECK(CalledOnValidThread());
Value* value;
if (!Get(path, &value))
return false;
@@ -72,4 +196,11 @@ bool CrosSettings::GetString(const std::wstring& path,
return value->GetAsString(out_value);
}
+CrosSettings::CrosSettings() {
+}
+
+CrosSettings::~CrosSettings() {
+ DCHECK(!providers_.size());
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros_settings.h b/chrome/browser/chromeos/cros_settings.h
index cfe4ec8..226ec08 100644
--- a/chrome/browser/chromeos/cros_settings.h
+++ b/chrome/browser/chromeos/cros_settings.h
@@ -4,45 +4,85 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_H_
+#pragma once
#include <string>
-#include "base/values.h"
+#include <vector>
+#include "base/hash_tables.h"
+#include "base/non_thread_safe.h"
+#include "base/observer_list.h"
+#include "base/singleton.h"
#include "chrome/browser/chromeos/cros_settings_names.h"
+#include "chrome/common/notification_observer.h"
+
+class Value;
namespace chromeos {
+class CrosSettingsProvider;
+
// A class manages per-device/global settings.
-class CrosSettings {
+class CrosSettings : public NonThreadSafe {
public:
// Class factory.
static CrosSettings* Get();
// Helper function to test if given path is a value cros settings name.
- static bool IsCrosSettings(const std::wstring& path);
+ static bool IsCrosSettings(const std::string& path);
// Sets |in_value| to given |path| in cros settings.
// Note that this takes ownership of |in_value|.
- virtual void Set(const std::wstring& path, Value* in_value) = 0;
+ void Set(const std::string& path, Value* in_value);
+
+ // Fires system setting change notification.
+ void FireObservers(const char* path);
// Gets settings value of given |path| to |out_value|.
- // Note that |out_value| is still owned by this class.
- virtual bool Get(const std::wstring& path, Value** out_value) const = 0;
+ // Note that the caller owns |out_value| returned.
+ bool Get(const std::string& path, Value** out_value) const;
// Convenience forms of Set(). These methods will replace any existing
// value at that path, even if it has a different type.
- void SetBoolean(const std::wstring& path, bool in_value);
- void SetInteger(const std::wstring& path, int in_value);
- void SetReal(const std::wstring& path, double in_value);
- void SetString(const std::wstring& path, const std::string& in_value);
+ void SetBoolean(const std::string& path, bool in_value);
+ void SetInteger(const std::string& path, int in_value);
+ void SetReal(const std::string& path, double in_value);
+ void SetString(const std::string& path, const std::string& in_value);
// These are convenience forms of Get(). The value will be retrieved
// and the return value will be true if the path is valid and the value at
// the end of the path can be returned in the form specified.
- bool GetBoolean(const std::wstring& path, bool* out_value) const;
- bool GetInteger(const std::wstring& path, int* out_value) const;
- bool GetReal(const std::wstring& path, double* out_value) const;
- bool GetString(const std::wstring& path, std::string* out_value) const;
+ bool GetBoolean(const std::string& path, bool* out_value) const;
+ bool GetInteger(const std::string& path, int* out_value) const;
+ bool GetReal(const std::string& path, double* out_value) const;
+ bool GetString(const std::string& path, std::string* out_value) const;
+
+ // adding/removing of providers
+ bool AddSettingsProvider(CrosSettingsProvider* provider);
+ bool RemoveSettingsProvider(CrosSettingsProvider* provider);
+
+ // If the pref at the given path changes, we call the observer's Observe
+ // method with PREF_CHANGED.
+ void AddSettingsObserver(const char* path, NotificationObserver* obs);
+ void RemoveSettingsObserver(const char* path, NotificationObserver* obs);
+
+ private:
+ // List of ChromeOS system settings providers.
+ std::vector<CrosSettingsProvider*> providers_;
+
+ // A map from settings names to a list of observers. Observers get fired in
+ // the order they are added.
+ typedef ObserverList<NotificationObserver> NotificationObserverList;
+ typedef base::hash_map<std::string, NotificationObserverList*>
+ SettingsObserverMap;
+ SettingsObserverMap settings_observers_;
+
+ CrosSettings();
+ ~CrosSettings();
+ CrosSettingsProvider* GetProvider(const std::string& path) const;
+ friend struct DefaultSingletonTraits<CrosSettings>;
+
+ DISALLOW_COPY_AND_ASSIGN(CrosSettings);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros_settings_names.cc b/chrome/browser/chromeos/cros_settings_names.cc
index 84fbf7e..1624726 100644
--- a/chrome/browser/chromeos/cros_settings_names.cc
+++ b/chrome/browser/chromeos/cros_settings_names.cc
@@ -6,10 +6,13 @@
namespace chromeos {
-const wchar_t kCrosSettingsPrefix[] = L"cros.";
+const char kCrosSettingsPrefix[] = "cros.";
-const wchar_t kAccountsPrefAllowBWSI[] = L"cros.accounts.allowBWSI";
-const wchar_t kAccountsPrefAllowGuest[] = L"cros.accounts.allowGuest";
-const wchar_t kAccountsPrefUsers[] = L"cros.accounts.users";
+const char kAccountsPrefAllowBWSI[] = "cros.accounts.allowBWSI";
+const char kAccountsPrefAllowGuest[] = "cros.accounts.allowGuest";
+const char kAccountsPrefShowUserNamesOnSignIn[]
+ = "cros.accounts.showUserNamesOnSignIn";
+const char kAccountsPrefUsers[] = "cros.accounts.users";
+const char kSystemTimezone[] = "cros.system.timezone";
} // namespace chromeos
diff --git a/chrome/browser/chromeos/cros_settings_names.h b/chrome/browser/chromeos/cros_settings_names.h
index ce99258..6f2bb5a 100644
--- a/chrome/browser/chromeos/cros_settings_names.h
+++ b/chrome/browser/chromeos/cros_settings_names.h
@@ -4,15 +4,18 @@
#ifndef CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_NAMES_H_
#define CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_NAMES_H_
+#pragma once
namespace chromeos {
-extern const wchar_t kCrosSettingsPrefix[];
+extern const char kCrosSettingsPrefix[];
-extern const wchar_t kAccountsPrefAllowBWSI[];
-extern const wchar_t kAccountsPrefAllowGuest[];
-extern const wchar_t kAccountsPrefUsers[];
+extern const char kAccountsPrefAllowBWSI[];
+extern const char kAccountsPrefAllowGuest[];
+extern const char kAccountsPrefShowUserNamesOnSignIn[];
+extern const char kAccountsPrefUsers[];
+extern const char kSystemTimezone[];
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_NAMES_H_
diff --git a/chrome/browser/chromeos/customization_document.cc b/chrome/browser/chromeos/customization_document.cc
index 19410ec..b9a4f34 100644
--- a/chrome/browser/chromeos/customization_document.cc
+++ b/chrome/browser/chromeos/customization_document.cc
@@ -6,33 +6,32 @@
#include <string>
-#include "base/file_path.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
-#include "base/string_util.h"
+#include "base/string_number_conversions.h"
#include "base/values.h"
// Manifest attributes names.
namespace {
-const wchar_t kVersionAttr[] = L"version";
-const wchar_t kProductSkuAttr[] = L"product_sku";
-const wchar_t kInitialLocaleAttr[] = L"initial_locale";
-const wchar_t kInitialTimezoneAttr[] = L"initial_timezone";
-const wchar_t kBackgroundColorAttr[] = L"background_color";
-const wchar_t kRegistrationUrlAttr[] = L"registration_url";
-const wchar_t kSetupContentAttr[] = L"setup_content";
-const wchar_t kContentLocaleAttr[] = L"content_locale";
-const wchar_t kHelpPageAttr[] = L"help_page";
-const wchar_t kEulaPageAttr[] = L"eula_page";
-const wchar_t kAppMenuAttr[] = L"app_menu";
-const wchar_t kInitialStartPageAttr[] = L"initial_start_page";
-const wchar_t kSectionTitleAttr[] = L"section_title";
-const wchar_t kWebAppsAttr[] = L"web_apps";
-const wchar_t kSupportPageAttr[] = L"support_page";
-const wchar_t kExtensionsAttr[] = L"extensions";
+const char kVersionAttr[] = "version";
+const char kProductSkuAttr[] = "product_sku";
+const char kInitialLocaleAttr[] = "initial_locale";
+const char kInitialTimezoneAttr[] = "initial_timezone";
+const char kBackgroundColorAttr[] = "background_color";
+const char kRegistrationUrlAttr[] = "registration_url";
+const char kSetupContentAttr[] = "setup_content";
+const char kContentLocaleAttr[] = "content_locale";
+const char kHelpPageAttr[] = "help_page";
+const char kEulaPageAttr[] = "eula_page";
+const char kAppMenuAttr[] = "app_menu";
+const char kInitialStartPageAttr[] = "initial_start_page";
+const char kSectionTitleAttr[] = "section_title";
+const char kWebAppsAttr[] = "web_apps";
+const char kSupportPageAttr[] = "support_page";
+const char kExtensionsAttr[] = "extensions";
const char kAcceptedManifestVersion[] = "1.0";
@@ -72,6 +71,16 @@ bool CustomizationDocument::ParseFromJsonValue(const DictionaryValue* root) {
// StartupCustomizationDocument implementation.
+bool StartupCustomizationDocument::LoadManifestFromFile(
+ const FilePath& manifest_path) {
+ if (CustomizationDocument::LoadManifestFromFile(manifest_path)) {
+ manifest_path_ = manifest_path;
+ return true;
+ } else {
+ return false;
+ }
+}
+
bool StartupCustomizationDocument::ParseFromJsonValue(
const DictionaryValue* root) {
if (!CustomizationDocument::ParseFromJsonValue(root))
@@ -93,8 +102,9 @@ bool StartupCustomizationDocument::ParseFromJsonValue(
root->GetString(kBackgroundColorAttr, &background_color_string);
if (!background_color_string.empty()) {
if (background_color_string[0] == '#') {
- background_color_ = static_cast<SkColor>(
- 0xff000000 | HexStringToInt(background_color_string.substr(1)));
+ int background_int;
+ base::HexStringToInt(background_color_string.substr(1), &background_int);
+ background_color_ = static_cast<SkColor>(0xff000000 | background_int);
} else {
// Literal color constants are not supported yet.
return false;
@@ -128,14 +138,14 @@ bool StartupCustomizationDocument::ParseFromJsonValue(
return true;
}
-const StartupCustomizationDocument::SetupContent*
- StartupCustomizationDocument::GetSetupContent(
- const std::string& locale) const {
+FilePath StartupCustomizationDocument::GetSetupPagePath(
+ const std::string& locale, std::string SetupContent::* page_path) const {
SetupContentMap::const_iterator content_iter = setup_content_.find(locale);
if (content_iter != setup_content_.end()) {
- return &content_iter->second;
+ return manifest_path_.DirName().Append(content_iter->second.*page_path);
+ } else {
+ return FilePath();
}
- return NULL;
}
// ServicesCustomizationDocument implementation.
diff --git a/chrome/browser/chromeos/customization_document.h b/chrome/browser/chromeos/customization_document.h
index 169adb9..ffdd74f 100644
--- a/chrome/browser/chromeos/customization_document.h
+++ b/chrome/browser/chromeos/customization_document.h
@@ -4,18 +4,18 @@
#ifndef CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_DOCUMENT_H_
#define CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_DOCUMENT_H_
+#pragma once
#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
+#include "base/file_path.h"
#include "third_party/skia/include/core/SkColor.h"
class DictionaryValue;
class ListValue;
-class FilePath;
namespace chromeos {
@@ -35,6 +35,7 @@ class CustomizationDocument {
// Parses manifest's attributes from the JSON dictionary value.
virtual bool ParseFromJsonValue(const DictionaryValue* root);
+ private:
// Manifest version string.
std::string version_;
@@ -45,6 +46,20 @@ class CustomizationDocument {
class StartupCustomizationDocument : public CustomizationDocument {
public:
+ StartupCustomizationDocument() {}
+
+ virtual bool LoadManifestFromFile(const FilePath& manifest_path);
+
+ const std::string& product_sku() const { return product_sku_; }
+ const std::string& initial_locale() const { return initial_locale_; }
+ const std::string& initial_timezone() const { return initial_timezone_; }
+ SkColor background_color() const { return background_color_; }
+ const std::string& registration_url() const { return registration_url_; }
+
+ FilePath GetHelpPagePath(const std::string& locale) const;
+ FilePath GetEULAPagePath(const std::string& locale) const;
+
+ private:
struct SetupContent {
SetupContent() {}
SetupContent(const std::string& help_page_path,
@@ -60,18 +75,9 @@ class StartupCustomizationDocument : public CustomizationDocument {
typedef std::map<std::string, SetupContent> SetupContentMap;
- StartupCustomizationDocument() {}
-
- const std::string& product_sku() const { return product_sku_; }
- const std::string& initial_locale() const { return initial_locale_; }
- const std::string& initial_timezone() const { return initial_timezone_; }
- SkColor background_color() const { return background_color_; }
- const std::string& registration_url() const { return registration_url_; }
-
- const SetupContent* GetSetupContent(const std::string& locale) const;
-
- protected:
virtual bool ParseFromJsonValue(const DictionaryValue* root);
+ FilePath GetSetupPagePath(const std::string& locale,
+ std::string SetupContent::* page_path) const;
// Product SKU.
std::string product_sku_;
@@ -91,9 +97,21 @@ class StartupCustomizationDocument : public CustomizationDocument {
// Setup content for different locales.
SetupContentMap setup_content_;
+ // Copy of manifest full path.
+ FilePath manifest_path_;
+
DISALLOW_COPY_AND_ASSIGN(StartupCustomizationDocument);
};
+inline FilePath StartupCustomizationDocument::GetHelpPagePath(
+ const std::string& locale) const {
+ return GetSetupPagePath(locale, &SetupContent::help_page_path);
+}
+inline FilePath StartupCustomizationDocument::GetEULAPagePath(
+ const std::string& locale) const {
+ return GetSetupPagePath(locale, &SetupContent::eula_page_path);
+}
+
// OEM services customization document class.
class ServicesCustomizationDocument : public CustomizationDocument {
@@ -114,7 +132,7 @@ class ServicesCustomizationDocument : public CustomizationDocument {
const StringList& web_apps() const { return web_apps_; }
const StringList& extensions() const { return extensions_; }
- protected:
+ private:
virtual bool ParseFromJsonValue(const DictionaryValue* root);
bool ParseStringListFromJsonValue(const ListValue* list_value,
diff --git a/chrome/browser/chromeos/customization_document_unittest.cc b/chrome/browser/chromeos/customization_document_unittest.cc
index 41c2cee..a19e63a 100644
--- a/chrome/browser/chromeos/customization_document_unittest.cc
+++ b/chrome/browser/chromeos/customization_document_unittest.cc
@@ -104,13 +104,13 @@ TEST_F(StartupCustomizationDocumentTest, LoadGoodManifestFromString) {
EXPECT_EQ(customization_.background_color(),
SkColorSetRGB(0x88, 0x00, 0x88));
EXPECT_EQ(customization_.registration_url(), "http://www.google.com");
- EXPECT_EQ(customization_.GetSetupContent("en_US")->help_page_path,
+ EXPECT_EQ(customization_.GetHelpPagePath("en_US").value(),
"setup_content/en_US/help.html");
- EXPECT_EQ(customization_.GetSetupContent("en_US")->eula_page_path,
+ EXPECT_EQ(customization_.GetEULAPagePath("en_US").value(),
"setup_content/en_US/eula.html");
- EXPECT_EQ(customization_.GetSetupContent("ru")->help_page_path,
+ EXPECT_EQ(customization_.GetHelpPagePath("ru").value(),
"setup_content/ru/help.html");
- EXPECT_EQ(customization_.GetSetupContent("ru")->eula_page_path,
+ EXPECT_EQ(customization_.GetEULAPagePath("ru").value(),
"setup_content/ru/eula.html");
}
diff --git a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
index 9ca1730..249419a 100644
--- a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc
@@ -7,40 +7,73 @@
#include "app/l10n_util.h"
#include "base/json/json_reader.h"
#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/chromeos/cros_settings_provider_user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "grit/generated_resources.h"
namespace chromeos {
-AccountsOptionsHandler::AccountsOptionsHandler() {
+AccountsOptionsHandler::AccountsOptionsHandler()
+ : CrosOptionsPageUIHandler(new UserCrosSettingsProvider()) {
}
AccountsOptionsHandler::~AccountsOptionsHandler() {
}
+void AccountsOptionsHandler::RegisterMessages() {
+ DCHECK(dom_ui_);
+ dom_ui_->RegisterMessageCallback("whitelistUser",
+ NewCallback(this, &AccountsOptionsHandler::WhitelistUser));
+ dom_ui_->RegisterMessageCallback("unwhitelistUser",
+ NewCallback(this, &AccountsOptionsHandler::UnwhitelistUser));
+}
+
void AccountsOptionsHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
- localized_strings->SetString(L"accountsPage", l10n_util::GetString(
+ localized_strings->SetString("accountsPage", l10n_util::GetStringUTF16(
IDS_OPTIONS_ACCOUNTS_TAB_LABEL));
- localized_strings->SetString(L"allow_BWSI", l10n_util::GetString(
+ localized_strings->SetString("allow_BWSI", l10n_util::GetStringUTF16(
IDS_OPTIONS_ACCOUNTS_ALLOW_BWSI_DESCRIPTION));
- localized_strings->SetString(L"allow_guest",l10n_util::GetString(
+ localized_strings->SetString("allow_guest",l10n_util::GetStringUTF16(
IDS_OPTIONS_ACCOUNTS_ALLOW_GUEST_DESCRIPTION));
- localized_strings->SetString(L"user_list_title",l10n_util::GetString(
- IDS_OPTIONS_ACCOUNTS_USER_LIST_TITLE));
- localized_strings->SetString(L"add_user",l10n_util::GetString(
- IDS_OPTIONS_ACCOUNTS_ADD_USER));
- localized_strings->SetString(L"remove_user",l10n_util::GetString(
- IDS_OPTIONS_ACCOUNTS_REMOVE_USER));
- localized_strings->SetString(L"add_user_email",l10n_util::GetString(
- IDS_OPTIONS_ACCOUNTS_EMAIL_LABEL));
-
- localized_strings->SetString(L"ok_label",l10n_util::GetString(
- IDS_OK));
- localized_strings->SetString(L"cancel_label",l10n_util::GetString(
- IDS_CANCEL));
+ localized_strings->SetString("show_user_on_signin",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_SHOW_USER_NAMES_ON_SINGIN_DESCRIPTION));
+ localized_strings->SetString("username_edit_hint",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_USERNAME_EDIT_HINT));
+ localized_strings->SetString("username_format",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_USERNAME_FORMAT));
+ localized_strings->SetString("add_users",l10n_util::GetStringUTF16(
+ IDS_OPTIONS_ACCOUNTS_ADD_USERS));
+
+ localized_strings->SetString("current_user_is_owner",
+ UserManager::Get()->current_user_is_owner() ?
+ ASCIIToUTF16("true") : ASCIIToUTF16("false"));
+}
+
+UserCrosSettingsProvider* AccountsOptionsHandler::users_settings() const {
+ return static_cast<UserCrosSettingsProvider*>(settings_provider_.get());
+}
+
+void AccountsOptionsHandler::WhitelistUser(const ListValue* args) {
+ std::string email;
+ if (!args->GetString(0, &email)) {
+ return;
+ }
+
+ users_settings()->WhitelistUser(email);
+}
+
+void AccountsOptionsHandler::UnwhitelistUser(const ListValue* args) {
+ std::string email;
+ if (!args->GetString(0, &email)) {
+ return;
+ }
+
+ users_settings()->UnwhitelistUser(email);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/accounts_options_handler.h b/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
index 0de8000..a43ec50 100644
--- a/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/accounts_options_handler.h
@@ -4,21 +4,33 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_ACCOUNTS_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_ACCOUNTS_OPTIONS_HANDLER_H_
+#pragma once
-#include "chrome/browser/dom_ui/options_ui.h"
+#include "chrome/browser/chromeos/dom_ui/cros_options_page_ui_handler.h"
namespace chromeos {
+class UserCrosSettingsProvider;
+
// ChromeOS accounts options page handler.
-class AccountsOptionsHandler : public OptionsPageUIHandler {
+class AccountsOptionsHandler : public CrosOptionsPageUIHandler {
public:
AccountsOptionsHandler();
virtual ~AccountsOptionsHandler();
+ // DOMMessageHandler implementation.
+ virtual void RegisterMessages();
+
// OptionsUIHandler implementation:
virtual void GetLocalizedValues(DictionaryValue* localized_strings);
private:
+ UserCrosSettingsProvider* users_settings() const;
+
+ // Javascript callbacks to whitelist/unwhitelist user.
+ void WhitelistUser(const ListValue* args);
+ void UnwhitelistUser(const ListValue* args);
+
DISALLOW_COPY_AND_ASSIGN(AccountsOptionsHandler);
};
diff --git a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
index 889a85d..d76e33d 100644
--- a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.cc
@@ -5,33 +5,42 @@
#include "chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h"
#include "base/json/json_reader.h"
-#include "base/string_util.h"
+#include "base/string_number_conversions.h"
#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/common/notification_service.h"
namespace chromeos {
-Value* CoreChromeOSOptionsHandler::FetchPref(const std::wstring& pref_name) {
+CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler()
+ : handling_change_(false) {
+}
+
+Value* CoreChromeOSOptionsHandler::FetchPref(const std::string& pref_name) {
if (!CrosSettings::IsCrosSettings(pref_name))
return ::CoreOptionsHandler::FetchPref(pref_name);
Value* pref_value = NULL;
CrosSettings::Get()->Get(pref_name, &pref_value);
- return pref_value ? pref_value->DeepCopy() : Value::CreateNullValue();
+ return pref_value ? pref_value : Value::CreateNullValue();
}
-void CoreChromeOSOptionsHandler::ObservePref(const std::wstring& pref_name) {
+void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
if (!CrosSettings::IsCrosSettings(pref_name))
return ::CoreOptionsHandler::ObservePref(pref_name);
// TODO(xiyuan): Change this when CrosSettings supports observers.
+ CrosSettings::Get()->AddSettingsObserver(pref_name.c_str(), this);
}
-void CoreChromeOSOptionsHandler::SetPref(const std::wstring& pref_name,
+void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
Value::ValueType pref_type,
- const std::string& value_string) {
+ const std::string& value_string,
+ const std::string& metric) {
if (!CrosSettings::IsCrosSettings(pref_name))
- return ::CoreOptionsHandler::SetPref(pref_name, pref_type, value_string);
-
+ return ::CoreOptionsHandler::SetPref(pref_name, pref_type, value_string,
+ metric);
+ handling_change_ = true;
CrosSettings* cros_settings = CrosSettings::Get();
switch (pref_type) {
case Value::TYPE_BOOLEAN:
@@ -39,7 +48,7 @@ void CoreChromeOSOptionsHandler::SetPref(const std::wstring& pref_name,
break;
case Value::TYPE_INTEGER:
int int_value;
- if (StringToInt(value_string, &int_value))
+ if (base::StringToInt(value_string, &int_value))
cros_settings->SetInteger(pref_name, int_value);
break;
case Value::TYPE_STRING:
@@ -55,6 +64,54 @@ void CoreChromeOSOptionsHandler::SetPref(const std::wstring& pref_name,
break;
}
}
+ handling_change_ = false;
+
+ ProcessUserMetric(pref_type, value_string, metric);
+}
+
+void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
+ // Unregister this instance from observing prefs of chrome os settings.
+ if (CrosSettings::IsCrosSettings(path))
+ CrosSettings::Get()->RemoveSettingsObserver(path.c_str(), this);
+ else // Call base class to handle regular preferences.
+ ::CoreOptionsHandler::StopObservingPref(path);
+}
+
+void CoreChromeOSOptionsHandler::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ // Ignore the notification if this instance had caused it.
+ if (handling_change_)
+ return;
+ if (type == NotificationType::SYSTEM_SETTING_CHANGED) {
+ NotifySettingsChanged(Details<std::string>(details).ptr());
+ return;
+ }
+ ::CoreOptionsHandler::Observe(type, source, details);
+}
+
+void CoreChromeOSOptionsHandler::NotifySettingsChanged(
+ const std::string* setting_name) {
+ DCHECK(dom_ui_);
+ DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name));
+ Value* value = NULL;
+ if (!CrosSettings::Get()->Get(*setting_name, &value)) {
+ NOTREACHED();
+ if (value)
+ delete value;
+ return;
+ }
+ for (PreferenceCallbackMap::const_iterator iter =
+ pref_callback_map_.find(*setting_name);
+ iter != pref_callback_map_.end(); ++iter) {
+ const std::wstring& callback_function = iter->second;
+ ListValue result_value;
+ result_value.Append(Value::CreateStringValue(setting_name->c_str()));
+ result_value.Append(value->DeepCopy());
+ dom_ui_->CallJavascriptFunction(callback_function, result_value);
+ }
+ if (value)
+ delete value;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
index 0c4dc5c..d3b63f5 100644
--- a/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_CORE_CHROMEOS_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_CORE_CHROMEOS_OPTIONS_HANDLER_H_
+#pragma once
#include "chrome/browser/dom_ui/core_options_handler.h"
@@ -12,15 +13,30 @@ namespace chromeos {
// CoreChromeOSOptionsHandler handles ChromeOS settings.
class CoreChromeOSOptionsHandler : public ::CoreOptionsHandler {
public:
+ CoreChromeOSOptionsHandler();
protected:
- // ::CoreOptionsHandler Implementation
- virtual Value* FetchPref(const std::wstring& pref_name);
- virtual void ObservePref(const std::wstring& pref_name);
- virtual void SetPref(const std::wstring& pref_name,
+ // ::CoreOptionsHandler overrides
+ virtual Value* FetchPref(const std::string& pref_name);
+ virtual void ObservePref(const std::string& pref_name);
+ virtual void SetPref(const std::string& pref_name,
Value::ValueType pref_type,
- const std::string& value_string);
-
+ const std::string& value_string,
+ const std::string& metric);
+ virtual void StopObservingPref(const std::string& path);
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ // Notifies registered JS callbacks on ChromeOS setting change.
+ void NotifySettingsChanged(const std::string* setting_name);
+
+ // Keeps the track of change caused by the handler to make sure
+ // it does not signal itself again.
+ bool handling_change_;
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/labs_handler.cc b/chrome/browser/chromeos/dom_ui/labs_handler.cc
index d6ecee0..7f45611 100644
--- a/chrome/browser/chromeos/dom_ui/labs_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/labs_handler.cc
@@ -5,20 +5,8 @@
#include "chrome/browser/chromeos/dom_ui/labs_handler.h"
#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/i18n/time_formatting.h"
-#include "base/stl_util-inl.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
#include "base/values.h"
-#include "chrome/common/notification_service.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
LabsHandler::LabsHandler() {
}
@@ -30,15 +18,21 @@ void LabsHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
// Labs page - ChromeOS
- localized_strings->SetString(L"labsPage",
- l10n_util::GetString(IDS_OPTIONS_LABS_TAB_LABEL));
- localized_strings->SetString(L"mediaplayer_title",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_MEDIAPLAYER));
- localized_strings->SetString(L"mediaplayer",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_MEDIAPLAYER_DESCRIPTION));
-
- localized_strings->SetString(L"advanced_file_title",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_ADVANCEDFS));
- localized_strings->SetString(L"advanced_filesystem",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_ADVANCEDFS_DESCRIPTION));
+ localized_strings->SetString("labsPage",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_LABS_TAB_LABEL));
+
+ localized_strings->SetString("mediaplayer_title",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_MEDIAPLAYER));
+ localized_strings->SetString("mediaplayer",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_MEDIAPLAYER_DESCRIPTION));
+
+ localized_strings->SetString("advanced_file_title",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_ADVANCEDFS));
+ localized_strings->SetString("advanced_filesystem",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_ADVANCEDFS_DESCRIPTION));
+
+ localized_strings->SetString("talk_title",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_TALK));
+ localized_strings->SetString("talk",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_TALK_DESCRIPTION));
}
diff --git a/chrome/browser/chromeos/dom_ui/labs_handler.h b/chrome/browser/chromeos/dom_ui/labs_handler.h
index 5c217bb..3fc1121 100644
--- a/chrome/browser/chromeos/dom_ui/labs_handler.h
+++ b/chrome/browser/chromeos/dom_ui/labs_handler.h
@@ -4,8 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LABS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_LABS_HANDLER_H_
-
-#include <string>
+#pragma once
#include "chrome/browser/dom_ui/options_ui.h"
@@ -19,7 +18,6 @@ class LabsHandler : public OptionsPageUIHandler {
virtual void GetLocalizedValues(DictionaryValue* localized_strings);
private:
-
DISALLOW_COPY_AND_ASSIGN(LabsHandler);
};
diff --git a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
index 150ae15..46a8e2d 100644
--- a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.cc
@@ -5,10 +5,13 @@
#include "chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h"
#include "app/l10n_util.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "grit/generated_resources.h"
+namespace chromeos {
+
LanguageHangulOptionsHandler::LanguageHangulOptionsHandler() {
}
@@ -19,21 +22,23 @@ void LanguageHangulOptionsHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
// Language Hangul page - ChromeOS
- localized_strings->SetString(L"keyboard_layout",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_KEYBOARD_LAYOUT_TEXT));
+ localized_strings->SetString("hangul_keyboard_layout",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_KEYBOARD_LAYOUT_TEXT));
- localized_strings->Set(L"keyboardLayoutList", GetKeyboardLayoutList());
+ localized_strings->Set("HangulkeyboardLayoutList", GetKeyboardLayoutList());
}
ListValue* LanguageHangulOptionsHandler::GetKeyboardLayoutList() {
ListValue* keyboard_layout_list = new ListValue();
- for (size_t i = 0; i < arraysize(chromeos::kHangulKeyboardNameIDPairs); ++i) {
+ for (size_t i = 0; i < language_prefs::kNumHangulKeyboardNameIDPairs; ++i) {
ListValue* option = new ListValue();
- option->Append(Value::CreateStringValue(ASCIIToWide(
- chromeos::kHangulKeyboardNameIDPairs[i].keyboard_id)));
- option->Append(Value::CreateStringValue(l10n_util::GetString(
- chromeos::kHangulKeyboardNameIDPairs[i].message_id)));
+ option->Append(Value::CreateStringValue(
+ language_prefs::kHangulKeyboardNameIDPairs[i].keyboard_id));
+ option->Append(Value::CreateStringValue(l10n_util::GetStringUTF16(
+ language_prefs::kHangulKeyboardNameIDPairs[i].message_id)));
keyboard_layout_list->Append(option);
}
return keyboard_layout_list;
}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h
index 1872fbc..cedfb05 100644
--- a/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h
@@ -4,12 +4,15 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_HANGUL_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_HANGUL_OPTIONS_HANDLER_H_
+#pragma once
#include "chrome/browser/dom_ui/options_ui.h"
class DictionaryValue;
class ListValue;
+namespace chromeos {
+
// Hangul options page UI handler.
class LanguageHangulOptionsHandler : public OptionsPageUIHandler {
public:
@@ -26,4 +29,6 @@ class LanguageHangulOptionsHandler : public OptionsPageUIHandler {
DISALLOW_COPY_AND_ASSIGN(LanguageHangulOptionsHandler);
};
+} // namespace chromeos
+
#endif // CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_HANGUL_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/language_options_handler.cc b/chrome/browser/chromeos/dom_ui/language_options_handler.cc
index c78cccc..594f8b1 100644
--- a/chrome/browser/chromeos/dom_ui/language_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/language_options_handler.cc
@@ -4,12 +4,29 @@
#include "chrome/browser/chromeos/dom_ui/language_options_handler.h"
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+
#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/input_method_library.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/pref_names.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+namespace chromeos {
+
LanguageOptionsHandler::LanguageOptionsHandler() {
}
@@ -19,26 +36,248 @@ LanguageOptionsHandler::~LanguageOptionsHandler() {
void LanguageOptionsHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
- localized_strings->SetString(L"languagePage",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE));
- localized_strings->SetString(L"add_button",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON));
- localized_strings->SetString(L"configure",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE));
- localized_strings->SetString(L"input_method",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD));
- localized_strings->SetString(L"languages",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES));
- localized_strings->SetString(L"remove_button",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON));
- localized_strings->SetString(L"others",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS));
- localized_strings->SetString(L"is_displayed_in_this_language",
- l10n_util::GetStringF(
+ localized_strings->SetString("languagePage",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_DIALOG_TITLE));
+ localized_strings->SetString("add_button",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_BUTTON));
+ localized_strings->SetString("configure",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE));
+ localized_strings->SetString("input_method",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD));
+ localized_strings->SetString("languages",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_LANGUAGES));
+ localized_strings->SetString("please_add_another_input_method",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_INPUT_METHOD));
+ localized_strings->SetString("please_add_another_language",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_PLEASE_ADD_ANOTHER_LANGUAGE));
+ localized_strings->SetString("ok_button", l10n_util::GetStringUTF16(IDS_OK));
+ localized_strings->SetString("remove_button",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON));
+ localized_strings->SetString("restart_button",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_RESTART_BUTTON));
+ localized_strings->SetString("add_language_instructions",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS));
+ localized_strings->SetString("input_method_instructions",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_INPUT_METHOD_INSTRUCTIONS));
+ localized_strings->SetString("switch_input_methods_hint",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_SWITCH_INPUT_METHODS_HINT,
+ ASCIIToUTF16("alt+shift")));
+ localized_strings->SetString("select_previous_input_method_hint",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_SELECT_PREVIOUS_INPUT_METHOD_HINT,
+ ASCIIToUTF16("ctrl+space")));
+ localized_strings->SetString("cannot_be_displayed_in_this_language",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
+ localized_strings->SetString("is_displayed_in_this_language",
+ l10n_util::GetStringFUTF16(
IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
- l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
- localized_strings->SetString(L"display_in_this_language",
- l10n_util::GetStringF(
+ l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
+ localized_strings->SetString("display_in_this_language",
+ l10n_util::GetStringFUTF16(
IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
- l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
+ l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
+ localized_strings->SetString("restart_required",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_RESTART_REQUIRED));
+ localized_strings->SetString("this_language_is_currently_in_use",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_THIS_LANGUAGE_IS_CURRENTLY_IN_USE,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)));
+
+ // GetSupportedInputMethods() never return NULL.
+ scoped_ptr<InputMethodDescriptors> descriptors(
+ CrosLibrary::Get()->GetInputMethodLibrary()->GetSupportedInputMethods());
+
+ // The followigns are resources, rather than local strings.
+ localized_strings->SetString("currentUiLanguageCode",
+ g_browser_process->GetApplicationLocale());
+ localized_strings->Set("inputMethodList", GetInputMethodList(*descriptors));
+ localized_strings->Set("languageList", GetLanguageList(*descriptors));
+ localized_strings->Set("uiLanguageCodeSet", GetUiLanguageCodeSet());
+}
+
+void LanguageOptionsHandler::RegisterMessages() {
+ DCHECK(dom_ui_);
+ dom_ui_->RegisterMessageCallback("inputMethodDisable",
+ NewCallback(this, &LanguageOptionsHandler::InputMethodDisableCallback));
+ dom_ui_->RegisterMessageCallback("inputMethodEnable",
+ NewCallback(this, &LanguageOptionsHandler::InputMethodEnableCallback));
+ dom_ui_->RegisterMessageCallback("inputMethodOptionsOpen",
+ NewCallback(this,
+ &LanguageOptionsHandler::InputMethodOptionsOpenCallback));
+ dom_ui_->RegisterMessageCallback("languageOptionsOpen",
+ NewCallback(this, &LanguageOptionsHandler::LanguageOptionsOpenCallback));
+ dom_ui_->RegisterMessageCallback("uiLanguageChange",
+ NewCallback(this, &LanguageOptionsHandler::UiLanguageChangeCallback));
+ dom_ui_->RegisterMessageCallback("uiLanguageRestart",
+ NewCallback(this, &LanguageOptionsHandler::RestartCallback));
}
+
+ListValue* LanguageOptionsHandler::GetInputMethodList(
+ const InputMethodDescriptors& descriptors) {
+ ListValue* input_method_list = new ListValue();
+
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ const InputMethodDescriptor& descriptor = descriptors[i];
+ const std::string language_code =
+ input_method::GetLanguageCodeFromDescriptor(descriptor);
+ const std::string display_name =
+ input_method::GetInputMethodDisplayNameFromId(descriptor.id);
+
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("id", descriptor.id);
+ dictionary->SetString("displayName", display_name);
+
+ // One input method can be associated with multiple languages, hence
+ // we use a dictionary here.
+ DictionaryValue* language_codes = new DictionaryValue();
+ language_codes->SetBoolean(language_code, true);
+ // Check kExtraLanguages to see if there are languages associated with
+ // this input method. If these are present, add these.
+ for (size_t j = 0; j < arraysize(input_method::kExtraLanguages); ++j) {
+ const std::string extra_input_method_id =
+ input_method::kExtraLanguages[j].input_method_id;
+ const std::string extra_language_code =
+ input_method::kExtraLanguages[j].language_code;
+ if (extra_input_method_id == descriptor.id) {
+ language_codes->SetBoolean(extra_language_code, true);
+ }
+ }
+ dictionary->Set("languageCodeSet", language_codes);
+
+ input_method_list->Append(dictionary);
+ }
+
+ return input_method_list;
+}
+
+ListValue* LanguageOptionsHandler::GetLanguageList(
+ const InputMethodDescriptors& descriptors) {
+ std::set<std::string> language_codes;
+ // Collect the language codes from the supported input methods.
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ const InputMethodDescriptor& descriptor = descriptors[i];
+ const std::string language_code =
+ input_method::GetLanguageCodeFromDescriptor(descriptor);
+ language_codes.insert(language_code);
+ }
+ // Collect the language codes from kExtraLanguages.
+ for (size_t i = 0; i < arraysize(input_method::kExtraLanguages); ++i) {
+ const char* language_code =
+ input_method::kExtraLanguages[i].language_code;
+ language_codes.insert(language_code);
+ }
+
+ // Map of display name -> {language code, native_display_name}.
+ // In theory, we should be able to create a map that is sorted by
+ // display names using ICU comparator, but doing it is hard, thus we'll
+ // use an auxiliary vector to achieve the same result.
+ typedef std::pair<std::string, std::wstring> LanguagePair;
+ typedef std::map<std::wstring, LanguagePair> LanguageMap;
+ LanguageMap language_map;
+ // The auxiliary vector mentioned above.
+ std::vector<std::wstring> display_names;
+
+ // Build the list of display names, and build the language map.
+ for (std::set<std::string>::const_iterator iter = language_codes.begin();
+ iter != language_codes.end(); ++iter) {
+ const std::wstring display_name =
+ input_method::GetLanguageDisplayNameFromCode(*iter);
+ const std::wstring native_display_name =
+ input_method::GetLanguageNativeDisplayNameFromCode(*iter);
+ display_names.push_back(display_name);
+ language_map[display_name] =
+ std::make_pair(*iter, native_display_name);
+ }
+ DCHECK_EQ(display_names.size(), language_map.size());
+
+ // Sort display names using locale specific sorter.
+ l10n_util::SortStrings(g_browser_process->GetApplicationLocale(),
+ &display_names);
+
+ // Build the language list from the language map.
+ ListValue* language_list = new ListValue();
+ for (size_t i = 0; i < display_names.size(); ++i) {
+ const LanguagePair& pair = language_map[display_names[i]];
+ DictionaryValue* dictionary = new DictionaryValue();
+ dictionary->SetString("code", pair.first);
+ dictionary->SetString("displayName", WideToUTF16Hack(display_names[i]));
+ dictionary->SetString("nativeDisplayName", WideToUTF16Hack(pair.second));
+ language_list->Append(dictionary);
+ }
+
+ return language_list;
+}
+
+DictionaryValue* LanguageOptionsHandler::GetUiLanguageCodeSet() {
+ DictionaryValue* dictionary = new DictionaryValue();
+ const std::vector<std::string>& available_locales =
+ l10n_util::GetAvailableLocales();
+ for (size_t i = 0; i < available_locales.size(); ++i) {
+ dictionary->SetBoolean(available_locales[i], true);
+ }
+ return dictionary;
+}
+
+void LanguageOptionsHandler::InputMethodDisableCallback(
+ const ListValue* args) {
+ const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+ const std::string action = StringPrintf(
+ "LanguageOptions_DisableInputMethod_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+void LanguageOptionsHandler::InputMethodEnableCallback(
+ const ListValue* args) {
+ const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+ const std::string action = StringPrintf(
+ "LanguageOptions_EnableInputMethod_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+void LanguageOptionsHandler::InputMethodOptionsOpenCallback(
+ const ListValue* args) {
+ const std::string input_method_id = WideToASCII(ExtractStringValue(args));
+ const std::string action = StringPrintf(
+ "InputMethodOptions_Open_%s", input_method_id.c_str());
+ UserMetrics::RecordComputedAction(action);
+}
+
+void LanguageOptionsHandler::LanguageOptionsOpenCallback(
+ const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Open"));
+}
+
+void LanguageOptionsHandler::UiLanguageChangeCallback(
+ const ListValue* args) {
+ const std::string language_code = WideToASCII(ExtractStringValue(args));
+ CHECK(!language_code.empty());
+ const std::string action = StringPrintf(
+ "LanguageOptions_UiLanguageChange_%s", language_code.c_str());
+ UserMetrics::RecordComputedAction(action);
+
+ PrefService* prefs = g_browser_process->local_state();
+ prefs->SetString(prefs::kApplicationLocale, language_code);
+ prefs->SavePersistentPrefs();
+ dom_ui_->CallJavascriptFunction(
+ L"options.LanguageOptions.uiLanguageSaved");
+}
+
+void LanguageOptionsHandler::RestartCallback(const ListValue* args) {
+ UserMetrics::RecordAction(UserMetricsAction("LanguageOptions_Restart"));
+
+ Browser* browser = Browser::GetBrowserForController(
+ &dom_ui_->tab_contents()->controller(), NULL);
+ // TODO(kochi): For ChromiumOS, just exiting means browser restart.
+ // Implement browser restart for Chromium Win/Linux/Mac.
+ if (browser)
+ browser->ExecuteCommand(IDC_EXIT);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/dom_ui/language_options_handler.h b/chrome/browser/chromeos/dom_ui/language_options_handler.h
index da17a41..79ab685 100644
--- a/chrome/browser/chromeos/dom_ui/language_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/language_options_handler.h
@@ -4,10 +4,15 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
+#pragma once
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/dom_ui/options_ui.h"
class DictionaryValue;
+class ListValue;
+
+namespace chromeos {
// ChromeOS language options page UI handler.
class LanguageOptionsHandler : public OptionsPageUIHandler {
@@ -18,8 +23,61 @@ class LanguageOptionsHandler : public OptionsPageUIHandler {
// OptionsUIHandler implementation.
virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+ // DOMMessageHandler implementation.
+ virtual void RegisterMessages();
+
+ // The following static methods are public for ease of testing.
+
+ // Gets the list of input methods from the given input descriptors.
+ // The return value will look like:
+ // [{'id': 'pinyin', 'displayName': 'Pinyin',
+ // 'languageCodeSet': {'zh-CW': true}}, ...]
+ //
+ // Note that true in languageCodeSet does not mean anything. We just use
+ // the dictionary as a set.
+ static ListValue* GetInputMethodList(
+ const InputMethodDescriptors& descriptors);
+
+ // Gets the list of languages from the given input descriptors.
+ // The return value will look like:
+ // [{'code': 'fi', 'displayName': 'Finnish', 'nativeDisplayName': 'suomi'},
+ // ...]
+ static ListValue* GetLanguageList(const InputMethodDescriptors& descriptors);
+
+ // Gets the set of language codes that can be used as UI language.
+ // The return value will look like:
+ // {'en-US': true, 'fi': true, 'fr': true, ...}
+ //
+ // Note that true in languageCodeSet does not mean anything. We just use
+ // the dictionary as a set.
+ static DictionaryValue* GetUiLanguageCodeSet();
+
private:
+ // Called when the input method is disabled.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodDisableCallback(const ListValue* args);
+
+ // Called when the input method is enabled.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodEnableCallback(const ListValue* args);
+
+ // Called when the input method options page is opened.
+ // |args| will contain the input method ID as string (ex. "mozc").
+ void InputMethodOptionsOpenCallback(const ListValue* args);
+
+ // Called when the language options is opened.
+ void LanguageOptionsOpenCallback(const ListValue* args);
+
+ // Called when the UI language is changed.
+ // |args| will contain the language code as string (ex. "fr").
+ void UiLanguageChangeCallback(const ListValue* args);
+
+ // Called when the restart button is clicked.
+ void RestartCallback(const ListValue* args);
+
DISALLOW_COPY_AND_ASSIGN(LanguageOptionsHandler);
};
+} // namespace
+
#endif // CHROME_BROWSER_CHROMEOS_DOM_UI_LANGUAGE_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/sync_options_handler.cc b/chrome/browser/chromeos/dom_ui/sync_options_handler.cc
deleted file mode 100644
index 073b8d4..0000000
--- a/chrome/browser/chromeos/dom_ui/sync_options_handler.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2010 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/chromeos/dom_ui/sync_options_handler.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/i18n/time_formatting.h"
-#include "base/stl_util-inl.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/common/notification_service.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-
-SyncOptionsHandler::SyncOptionsHandler() {}
-
-SyncOptionsHandler::~SyncOptionsHandler() {}
-
-void SyncOptionsHandler::GetLocalizedValues(
- DictionaryValue* localized_strings) {
- DCHECK(localized_strings);
- // Sync page - ChromeOS
- localized_strings->SetString(L"syncPage",
- l10n_util::GetString(IDS_SYNC_NTP_SYNC_SECTION_TITLE));
- localized_strings->SetString(L"sync_title",
- l10n_util::GetString(IDS_CUSTOMIZE_SYNC_DESCRIPTION));
- localized_strings->SetString(L"syncsettings",
- l10n_util::GetString(IDS_SYNC_DATATYPE_PREFERENCES));
- localized_strings->SetString(L"syncbookmarks",
- l10n_util::GetString(IDS_SYNC_DATATYPE_BOOKMARKS));
- localized_strings->SetString(L"synctypedurls",
- l10n_util::GetString(IDS_SYNC_DATATYPE_TYPED_URLS));
- localized_strings->SetString(L"syncpasswords",
- l10n_util::GetString(IDS_SYNC_DATATYPE_PASSWORDS));
- localized_strings->SetString(L"syncextensions",
- l10n_util::GetString(IDS_SYNC_DATATYPE_EXTENSIONS));
- localized_strings->SetString(L"syncautofill",
- l10n_util::GetString(IDS_SYNC_DATATYPE_AUTOFILL));
- localized_strings->SetString(L"syncthemes",
- l10n_util::GetString(IDS_SYNC_DATATYPE_THEMES));
-}
diff --git a/chrome/browser/chromeos/dom_ui/sync_options_handler.h b/chrome/browser/chromeos/dom_ui/sync_options_handler.h
deleted file mode 100644
index a58c583..0000000
--- a/chrome/browser/chromeos/dom_ui/sync_options_handler.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_SYNC_OPTIONS_HANDLER_H_
-#define CHROME_BROWSER_CHROMEOS_DOM_UI_SYNC_OPTIONS_HANDLER_H_
-
-#include "chrome/browser/dom_ui/options_ui.h"
-
-// ChromeOS system options page UI handler.
-class SyncOptionsHandler : public OptionsPageUIHandler {
- public:
- SyncOptionsHandler();
- virtual ~SyncOptionsHandler();
-
- // OptionsUIHandler implementation.
- virtual void GetLocalizedValues(DictionaryValue* localized_strings);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SyncOptionsHandler);
-};
-
-#endif // CHROME_BROWSER_CHROMEOS_DOM_UI_SYNC_OPTIONS_HANDLER_H_
diff --git a/chrome/browser/chromeos/dom_ui/system_options_handler.cc b/chrome/browser/chromeos/dom_ui/system_options_handler.cc
index b280526..d47c82c 100644
--- a/chrome/browser/chromeos/dom_ui/system_options_handler.cc
+++ b/chrome/browser/chromeos/dom_ui/system_options_handler.cc
@@ -4,15 +4,16 @@
#include "chrome/browser/chromeos/dom_ui/system_options_handler.h"
+#include <string>
+
#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
#include "base/basictypes.h"
#include "base/callback.h"
-#include "base/i18n/time_formatting.h"
-#include "base/stl_util-inl.h"
-#include "base/time.h"
+#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/chromeos/dom_ui/system_settings_provider.h"
+#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/common/notification_service.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
@@ -20,124 +21,49 @@
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
-static const char* kTimeZonesUtf8[] = {
- "Pacific/Samoa",
- "US/Hawaii",
- "US/Alaska",
- "US/Pacific",
- "US/Mountain",
- "US/Central",
- "US/Eastern",
- "America/Santiago",
- "America/Sao_Paulo",
- "Atlantic/South_Georgia",
- "Atlantic/Cape_Verde",
- "Europe/London",
- "Europe/Rome",
- "Europe/Helsinki",
- "Europe/Moscow",
- "Asia/Dubai",
- "Asia/Karachi",
- "Asia/Dhaka",
- "Asia/Bangkok",
- "Asia/Hong_Kong",
- "Asia/Tokyo",
- "Australia/Sydney",
- "Asia/Magadan",
- "Pacific/Auckland" };
-
-SystemOptionsHandler::SystemOptionsHandler() {
- // TODO(chocobo): For now, add all the GMT timezones.
- // We may eventually want to use icu::TimeZone::createEnumeration()
- // to list all the timezones and pick the ones we want to show.
- // NOTE: This currently does not handle daylight savings properly
- // b/c this is just a manually selected list of timezones that
- // happen to span the GMT-11 to GMT+12 Today. When daylight savings
- // kick in, this list might have more than one timezone in the same
- // GMT bucket.
- for (size_t i = 0; i < arraysize(kTimeZonesUtf8); i++) {
- timezones_.push_back(icu::TimeZone::createTimeZone(
- icu::UnicodeString::fromUTF8(kTimeZonesUtf8[i])));
- }
+SystemOptionsHandler::SystemOptionsHandler()
+ : chromeos::CrosOptionsPageUIHandler(
+ new chromeos::SystemSettingsProvider()) {
}
SystemOptionsHandler::~SystemOptionsHandler() {
- STLDeleteElements(&timezones_);
}
void SystemOptionsHandler::GetLocalizedValues(
DictionaryValue* localized_strings) {
DCHECK(localized_strings);
// System page - ChromeOS
- localized_strings->SetString(L"systemPage",
- l10n_util::GetString(IDS_OPTIONS_SYSTEM_TAB_LABEL));
- localized_strings->SetString(L"datetime_title",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME));
- localized_strings->SetString(L"timezone",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION));
+ localized_strings->SetString("systemPage",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SYSTEM_TAB_LABEL));
+ localized_strings->SetString("datetime_title",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME));
+ localized_strings->SetString("timezone",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION));
- localized_strings->SetString(L"touchpad",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD));
- localized_strings->SetString(L"enable_tap_to_click",
- l10n_util::GetString(
+ localized_strings->SetString("touchpad",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD));
+ localized_strings->SetString("enable_tap_to_click",
+ l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION));
- localized_strings->SetString(L"enable_vert_edge_scroll",
- l10n_util::GetString(
- IDS_OPTIONS_SETTINGS_VERT_EDGE_SCROLL_ENABLED_DESCRIPTION));
- localized_strings->SetString(L"sensitivity",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION));
- localized_strings->SetString(L"speed_factor",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SPEED_FACTOR_DESCRIPTION));
-
- localized_strings->SetString(L"language",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE));
- localized_strings->SetString(L"language_customize",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE));
+ localized_strings->SetString("sensitivity",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION));
- localized_strings->SetString(L"accessibility_title",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY));
- localized_strings->SetString(L"accessibility",
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_ACCESSIBILITY_DESCRIPTION));
-
- localized_strings->Set(L"timezoneList", GetTimezoneList());
-}
+ localized_strings->SetString("language",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE));
+ localized_strings->SetString("language_customize",
+ l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE));
+ localized_strings->SetString("modifier_keys_customize",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_LANGUAGES_MODIFIER_KEYS_CUSTOMIZE));
-ListValue* SystemOptionsHandler::GetTimezoneList() {
- ListValue* timezoneList = new ListValue();
- for (std::vector<icu::TimeZone*>::iterator iter = timezones_.begin();
- iter != timezones_.end(); ++iter) {
- const icu::TimeZone* timezone = *iter;
- ListValue* option = new ListValue();
- option->Append(Value::CreateStringValue(GetTimezoneID(timezone)));
- option->Append(Value::CreateStringValue(GetTimezoneName(timezone)));
- timezoneList->Append(option);
- }
- return timezoneList;
-}
-
-std::wstring SystemOptionsHandler::GetTimezoneName(
- const icu::TimeZone* timezone) {
- DCHECK(timezone);
- icu::UnicodeString name;
- timezone->getDisplayName(name);
- std::wstring output;
- UTF16ToWide(name.getBuffer(), name.length(), &output);
- int hour_offset = timezone->getRawOffset() / 3600000;
- const wchar_t* format;
- if (hour_offset == 0)
- format = L"(GMT) ";
- else
- format = L"(GMT%+d) ";
-
- return StringPrintf(format, hour_offset) + output;
-}
+ localized_strings->SetString("accessibility_title",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY));
+ localized_strings->SetString("accessibility",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_ACCESSIBILITY_DESCRIPTION));
-std::wstring SystemOptionsHandler::GetTimezoneID(
- const icu::TimeZone* timezone) {
- DCHECK(timezone);
- icu::UnicodeString id;
- timezone->getID(id);
- std::wstring output;
- UTF16ToWide(id.getBuffer(), id.length(), &output);
- return output;
+ localized_strings->Set("timezoneList",
+ reinterpret_cast<chromeos::SystemSettingsProvider*>(
+ settings_provider_.get())->GetTimezoneList());
}
diff --git a/chrome/browser/chromeos/dom_ui/system_options_handler.h b/chrome/browser/chromeos/dom_ui/system_options_handler.h
index c21d5b0..5d96050 100644
--- a/chrome/browser/chromeos/dom_ui/system_options_handler.h
+++ b/chrome/browser/chromeos/dom_ui/system_options_handler.h
@@ -4,15 +4,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_DOM_UI_SYSTEM_OPTIONS_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_DOM_UI_SYSTEM_OPTIONS_HANDLER_H_
+#pragma once
-#include <string>
-#include <vector>
+#include "chrome/browser/chromeos/dom_ui/cros_options_page_ui_handler.h"
-#include "chrome/browser/dom_ui/options_ui.h"
-#include "third_party/icu/public/i18n/unicode/timezone.h"
+class DictionaryValue;
// ChromeOS system options page UI handler.
-class SystemOptionsHandler : public OptionsPageUIHandler {
+class SystemOptionsHandler : public chromeos::CrosOptionsPageUIHandler {
public:
SystemOptionsHandler();
virtual ~SystemOptionsHandler();
@@ -21,18 +20,6 @@ class SystemOptionsHandler : public OptionsPageUIHandler {
virtual void GetLocalizedValues(DictionaryValue* localized_strings);
private:
- // Creates the map of timezones used by the options page.
- ListValue* GetTimezoneList();
-
- // Gets timezone name.
- std::wstring GetTimezoneName(const icu::TimeZone* timezone);
-
- // Gets timezone ID which is also used as timezone pref value.
- std::wstring GetTimezoneID(const icu::TimeZone* timezone);
-
- // Timezones.
- std::vector<icu::TimeZone*> timezones_;
-
DISALLOW_COPY_AND_ASSIGN(SystemOptionsHandler);
};
diff --git a/chrome/browser/chromeos/drop_shadow_label.h b/chrome/browser/chromeos/drop_shadow_label.h
index 21ed7eb..5848160 100644
--- a/chrome/browser/chromeos/drop_shadow_label.h
+++ b/chrome/browser/chromeos/drop_shadow_label.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_DROP_SHADOW_LABEL_H_
#define CHROME_BROWSER_CHROMEOS_DROP_SHADOW_LABEL_H_
+#pragma once
#include "gfx/font.h"
#include "views/controls/label.h"
diff --git a/chrome/browser/chromeos/external_cookie_handler.h b/chrome/browser/chromeos/external_cookie_handler.h
index aef3367..b422ace 100644
--- a/chrome/browser/chromeos/external_cookie_handler.h
+++ b/chrome/browser/chromeos/external_cookie_handler.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_EXTERNAL_COOKIE_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_EXTERNAL_COOKIE_HANDLER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/external_metrics.h b/chrome/browser/chromeos/external_metrics.h
index 0af3dad..eac8c64 100644
--- a/chrome/browser/chromeos/external_metrics.h
+++ b/chrome/browser/chromeos/external_metrics.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_EXTERNAL_METRICS_H_
#define CHROME_BROWSER_CHROMEOS_EXTERNAL_METRICS_H_
+#pragma once
#include "base/basictypes.h"
#include "base/compiler_specific.h"
diff --git a/chrome/browser/chromeos/external_protocol_dialog.cc b/chrome/browser/chromeos/external_protocol_dialog.cc
index 5aeb8a9..2c53a29 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.cc
+++ b/chrome/browser/chromeos/external_protocol_dialog.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -82,7 +82,7 @@ views::View* ExternalProtocolDialog::GetContentsView() {
ExternalProtocolDialog::ExternalProtocolDialog(TabContents* tab_contents,
const GURL& url)
: creation_time_(base::TimeTicks::Now()),
- scheme_(UTF8ToWide(url.scheme())) {
+ scheme_(url.scheme()) {
const int kMaxUrlWithoutSchemeSize = 256;
std::wstring elided_url_without_scheme;
ElideString(ASCIIToWide(url.possibly_invalid_spec()),
diff --git a/chrome/browser/chromeos/external_protocol_dialog.h b/chrome/browser/chromeos/external_protocol_dialog.h
index 71ca656..84f7955 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.h
+++ b/chrome/browser/chromeos/external_protocol_dialog.h
@@ -1,9 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_EXTERNAL_PROTOCOL_DIALOG_H_
#define CHROME_BROWSER_CHROMEOS_EXTERNAL_PROTOCOL_DIALOG_H_
+#pragma once
#include "base/time.h"
#include "views/window/dialog_delegate.h"
@@ -43,7 +44,7 @@ class ExternalProtocolDialog : public views::DialogDelegate {
base::TimeTicks creation_time_;
// The scheme of the url.
- std::wstring scheme_;
+ std::string scheme_;
DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialog);
};
diff --git a/chrome/browser/chromeos/frame/browser_frame_chromeos.cc b/chrome/browser/chromeos/frame/browser_frame_chromeos.cc
index c0ca464..c946924 100644
--- a/chrome/browser/chromeos/frame/browser_frame_chromeos.cc
+++ b/chrome/browser/chromeos/frame/browser_frame_chromeos.cc
@@ -4,8 +4,11 @@
#include "chrome/browser/chromeos/frame/browser_frame_chromeos.h"
-#include "chrome/browser/chromeos/frame/normal_browser_frame_view.h"
+#include "base/command_line.h"
#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/frame/opaque_browser_frame_view.h"
+#include "chrome/browser/views/frame/popup_non_client_frame_view.h"
+#include "chrome/common/chrome_switches.h"
// static (Factory method.)
BrowserFrame* BrowserFrame::Create(BrowserView* browser_view,
@@ -27,21 +30,28 @@ BrowserFrameChromeos::~BrowserFrameChromeos() {
}
void BrowserFrameChromeos::Init() {
- // Excludes a browser intance that requires icon/title. This is typically true
- // for dev tools and javascript console.
- // TODO(oshima): handle app panels. This currently uses the default
- // implementation, which opens Chrome's app panel instead of
- // ChromeOS's panel.
- if (!IsPanel() &&
- !browser_view()->ShouldShowWindowIcon() &&
- !browser_view()->ShouldShowWindowTitle()) {
- set_browser_frame_view(new NormalBrowserFrameView(this, browser_view()));
+ // NOTE: This logic supersedes the logic in BrowserFrameGtk::Init()
+ // by always setting browser_frame_view_.
+ if (IsPanel()) {
+ // ChromeOS Panels should always use PopupNonClientFrameView.
+ set_browser_frame_view(new PopupNonClientFrameView());
+ } else {
+ // Default FrameView.
+ set_browser_frame_view(new OpaqueBrowserFrameView(this, browser_view()));
}
+
BrowserFrameGtk::Init();
+
+ if (!IsPanel()) {
+ // On chromeos we want windows to always render as active.
+ GetNonClientView()->DisableInactiveRendering(true);
+ }
}
bool BrowserFrameChromeos::IsMaximized() const {
- return !IsPanel() || WindowGtk::IsMaximized();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeosFrame))
+ return WindowGtk::IsMaximized();
+ return !IsFullscreen() && (!IsPanel() || WindowGtk::IsMaximized());
}
bool BrowserFrameChromeos::IsPanel() const {
diff --git a/chrome/browser/chromeos/frame/browser_frame_chromeos.h b/chrome/browser/chromeos/frame/browser_frame_chromeos.h
index b776591..4863047 100644
--- a/chrome/browser/chromeos/frame/browser_frame_chromeos.h
+++ b/chrome/browser/chromeos/frame/browser_frame_chromeos.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
#define CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
+#pragma once
#include "chrome/browser/views/frame/browser_frame_gtk.h"
diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc
index 25ecefd..8ffbe2e 100644
--- a/chrome/browser/chromeos/frame/browser_view.cc
+++ b/chrome/browser/chromeos/frame/browser_view.cc
@@ -12,11 +12,10 @@
#include "base/command_line.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/chromeos/frame/panel_browser_view.h"
-#include "chrome/browser/chromeos/options/language_config_view.h"
-#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/status/language_menu_button.h"
#include "chrome/browser/chromeos/status/network_menu_button.h"
#include "chrome/browser/chromeos/status/status_area_button.h"
+#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/views/app_launcher.h"
@@ -28,12 +27,11 @@
#include "chrome/browser/views/theme_background.h"
#include "chrome/browser/views/toolbar_view.h"
#include "chrome/common/chrome_switches.h"
+#include "cros/chromeos_wm_ipc_enums.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
-#include "cros/chromeos_wm_ipc_enums.h"
#include "views/controls/button/button.h"
#include "views/controls/button/image_button.h"
-#include "views/controls/image_view.h"
#include "views/controls/menu/menu_2.h"
#include "views/screen.h"
#include "views/widget/root_view.h"
@@ -42,15 +40,6 @@
namespace {
-// The OTR avatar ends 2 px above the bottom of the tabstrip (which, given the
-// way the tabstrip draws its bottom edge, will appear like a 1 px gap to the
-// user).
-const int kOTRBottomSpacing = 2;
-
-// There are 2 px on each side of the OTR avatar (between the frame border and
-// it on the left, and between it and the tabstrip on the right).
-const int kOTRSideSpacing = 2;
-
// Amount to offset the toolbar by when vertical tabs are enabled.
const int kVerticalTabStripToolbarOffset = 2;
@@ -83,9 +72,6 @@ class BrowserViewLayout : public ::BrowserViewLayout {
case VIEW_ID_STATUS_AREA:
status_area_ = static_cast<chromeos::StatusAreaView*>(view);
break;
- case VIEW_ID_OTR_AVATAR:
- otr_avatar_icon_ = view;
- break;
}
}
@@ -95,21 +81,20 @@ class BrowserViewLayout : public ::BrowserViewLayout {
virtual int LayoutTabStrip() {
if (browser_view_->IsFullscreen() || !browser_view_->IsTabStripVisible()) {
status_area_->SetVisible(false);
- otr_avatar_icon_->SetVisible(false);
tabstrip_->SetVisible(false);
tabstrip_->SetBounds(0, 0, 0, 0);
return 0;
- } else {
- gfx::Rect layout_bounds =
- browser_view_->frame()->GetBoundsForTabStrip(tabstrip_);
- gfx::Point tabstrip_origin = layout_bounds.origin();
- views::View::ConvertPointToView(browser_view_->GetParent(), browser_view_,
- &tabstrip_origin);
- layout_bounds.set_origin(tabstrip_origin);
- if (browser_view_->UseVerticalTabs())
- return LayoutTitlebarComponentsWithVerticalTabs(layout_bounds);
- return LayoutTitlebarComponents(layout_bounds);
}
+
+ gfx::Rect tabstrip_bounds(
+ browser_view_->frame()->GetBoundsForTabStrip(tabstrip_));
+ gfx::Point tabstrip_origin = tabstrip_bounds.origin();
+ views::View::ConvertPointToView(browser_view_->GetParent(), browser_view_,
+ &tabstrip_origin);
+ tabstrip_bounds.set_origin(tabstrip_origin);
+ return browser_view_->UseVerticalTabs() ?
+ LayoutTitlebarComponentsWithVerticalTabs(tabstrip_bounds) :
+ LayoutTitlebarComponents(tabstrip_bounds);
}
virtual int LayoutToolbar(int top) {
@@ -154,33 +139,20 @@ class BrowserViewLayout : public ::BrowserViewLayout {
return false;
}
- // Positions the titlebar, toolbar, tabstrip, tabstrip and otr icon. This is
+ // Positions the titlebar, toolbar and tabstrip. This is
// used when side tabs are enabled.
int LayoutTitlebarComponentsWithVerticalTabs(const gfx::Rect& bounds) {
if (bounds.IsEmpty())
return 0;
tabstrip_->SetVisible(true);
- otr_avatar_icon_->SetVisible(browser_view_->ShouldShowOffTheRecordAvatar());
status_area_->SetVisible(true);
gfx::Size status_size = status_area_->GetPreferredSize();
int status_height = status_size.height();
- // Layout the otr icon.
int status_x = bounds.x();
- if (!otr_avatar_icon_->IsVisible()) {
- otr_avatar_icon_->SetBounds(0, 0, 0, 0);
- } else {
- gfx::Size otr_size = otr_avatar_icon_->GetPreferredSize();
-
- status_height = std::max(status_height, otr_size.height());
- int y = bounds.bottom() - status_height;
- otr_avatar_icon_->SetBounds(status_x, y, otr_size.width(), status_height);
- status_x += otr_size.width();
- }
-
- // Layout the status area after the otr icon.
+ // Layout the status area.
status_area_->SetBounds(status_x, bounds.bottom() - status_height,
status_size.width(), status_height);
@@ -211,66 +183,33 @@ class BrowserViewLayout : public ::BrowserViewLayout {
return bounds.y() + toolbar_height;
}
- // Layouts components in the title bar area (given by
- // |bounds|). These include the main menu, the otr avatar icon (in
- // incognito window), the tabstrip and the the status area.
+ // Lays out tabstrip and status area in the title bar area (given by
+ // |bounds|).
int LayoutTitlebarComponents(const gfx::Rect& bounds) {
- if (bounds.IsEmpty()) {
+ if (bounds.IsEmpty())
return 0;
- }
+
tabstrip_->SetVisible(true);
- otr_avatar_icon_->SetVisible(browser_view_->ShouldShowOffTheRecordAvatar());
status_area_->SetVisible(true);
- int bottom = bounds.bottom();
-
// Layout status area after tab strip.
gfx::Size status_size = status_area_->GetPreferredSize();
- status_area_->SetBounds(bounds.x() + bounds.width() - status_size.width(),
- bounds.y(), status_size.width(),
- status_size.height());
- LayoutOTRAvatar(bounds);
-
- int curx = bounds.x();
- int remaining_width = std::max(
- 0, // In case there is no space left.
- otr_avatar_icon_->bounds().x() - curx);
-
- tabstrip_->SetBounds(curx, bounds.y(), remaining_width, bounds.height());
-
- gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds();
- tabstrip_->SetBackgroundOffset(
- gfx::Point(curx - toolbar_bounds.x(), bounds.y()));
- return bottom;
- }
-
- // Layouts OTR avatar within the given |bounds|.
- void LayoutOTRAvatar(const gfx::Rect& bounds) {
- gfx::Rect status_bounds = status_area_->bounds();
- if (!otr_avatar_icon_->IsVisible()) {
- otr_avatar_icon_->SetBounds(status_bounds.x(), status_bounds.y(), 0, 0);
- } else {
- gfx::Size preferred_size = otr_avatar_icon_->GetPreferredSize();
-
- int y = bounds.bottom() - preferred_size.height() - kOTRBottomSpacing;
- int x = status_bounds.x() - kOTRSideSpacing - preferred_size.width();
- otr_avatar_icon_->SetBounds(x, y, preferred_size.width(),
- preferred_size.height());
- }
+ status_area_->SetBounds(bounds.right() - status_size.width(), bounds.y(),
+ status_size.width(), status_size.height());
+ tabstrip_->SetBounds(bounds.x(), bounds.y(),
+ std::max(0, status_area_->bounds().x() - bounds.x()),
+ bounds.height());
+ return bounds.bottom();
}
-
chromeos::StatusAreaView* status_area_;
- views::View* otr_avatar_icon_;
DISALLOW_COPY_AND_ASSIGN(BrowserViewLayout);
};
BrowserView::BrowserView(Browser* browser)
: ::BrowserView(browser),
- status_area_(NULL),
- force_maximized_window_(false),
- otr_avatar_icon_(new views::ImageView()) {
+ status_area_(NULL) {
}
BrowserView::~BrowserView() {
@@ -294,10 +233,6 @@ void BrowserView::Init() {
BrowserFrameGtk* gtk_frame = static_cast<BrowserFrameGtk*>(frame());
gtk_frame->GetNonClientView()->SetContextMenuController(this);
- otr_avatar_icon_->SetImage(GetOTRAvatarIcon());
- otr_avatar_icon_->SetID(VIEW_ID_OTR_AVATAR);
- AddChildView(otr_avatar_icon_);
-
// Make sure the window is set to the right type.
std::vector<int> params;
params.push_back(browser()->tab_count());
@@ -333,11 +268,6 @@ views::LayoutManager* BrowserView::CreateLayoutManager() const {
return new BrowserViewLayout();
}
-void BrowserView::InitTabStrip(TabStripModel* tab_strip_model) {
- ::BrowserView::InitTabStrip(tab_strip_model);
- UpdateOTRBackground();
-}
-
void BrowserView::ChildPreferredSizeChanged(View* child) {
Layout();
SchedulePaint();
@@ -394,8 +324,7 @@ void BrowserView::OpenButtonOptions(const views::View* button_view) const {
if (button_view == status_area_->network_view()) {
browser()->OpenInternetOptionsDialog();
} else if (button_view == status_area_->language_view()) {
- LanguageConfigView::Show(GetProfile(),
- frame()->GetWindow()->GetNativeWindow());
+ browser()->OpenLanguageOptionsDialog();
} else {
browser()->OpenSystemOptionsDialog();
}
@@ -432,20 +361,15 @@ void BrowserView::InitSystemMenu() {
system_menu_menu_.reset(new views::Menu2(system_menu_contents_.get()));
}
-void BrowserView::UpdateOTRBackground() {
- if (UseVerticalTabs())
- otr_avatar_icon_->set_background(new ThemeBackground(this));
- else
- otr_avatar_icon_->set_background(NULL);
-}
-
} // namespace chromeos
// static
BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) {
// Create a browser view for chromeos.
BrowserView* view;
- if (browser->type() & Browser::TYPE_POPUP)
+ if ((browser->type() == Browser::TYPE_POPUP) ||
+ (browser->type() == Browser::TYPE_APP_POPUP) ||
+ (browser->type() == Browser::TYPE_APP_PANEL))
view = new chromeos::PanelBrowserView(browser);
else
view = new chromeos::BrowserView(browser);
diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h
index 0e9f40b..3c81c12 100644
--- a/chrome/browser/chromeos/frame/browser_view.h
+++ b/chrome/browser/chromeos/frame/browser_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_VIEW_H_
+#pragma once
#include <vector>
@@ -49,7 +50,6 @@ class BrowserView : public ::BrowserView,
virtual void Show();
virtual void FocusChromeOSStatus();
virtual views::LayoutManager* CreateLayoutManager() const;
- virtual void InitTabStrip(TabStripModel* tab_strip_model);
virtual void ChildPreferredSizeChanged(View* child);
virtual bool GetSavedWindowBounds(gfx::Rect* bounds) const;
@@ -75,10 +75,6 @@ class BrowserView : public ::BrowserView,
private:
void InitSystemMenu();
- // Updates the background of the otr icon. The background differs for vertical
- // tabs.
- void UpdateOTRBackground();
-
// Status Area view.
StatusAreaView* status_area_;
@@ -86,12 +82,6 @@ class BrowserView : public ::BrowserView,
scoped_ptr<menus::SimpleMenuModel> system_menu_contents_;
scoped_ptr<views::Menu2> system_menu_menu_;
- // A flag to specify if the browser window should be maximized.
- bool force_maximized_window_;
-
- // Off the record icon.
- views::ImageView* otr_avatar_icon_;
-
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/chromeos/frame/normal_browser_frame_view.cc b/chrome/browser/chromeos/frame/normal_browser_frame_view.cc
deleted file mode 100644
index 84c4614..0000000
--- a/chrome/browser/chromeos/frame/normal_browser_frame_view.cc
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright (c) 2010 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/chromeos/frame/normal_browser_frame_view.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "app/theme_provider.h"
-#include "app/x11_util.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/browser_theme_provider.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
-#include "chrome/common/chrome_switches.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
-#include "gfx/path.h"
-#include "grit/app_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "views/controls/button/image_button.h"
-#include "views/controls/image_view.h"
-#include "views/window/hit_test.h"
-#include "views/widget/root_view.h"
-#include "views/window/window.h"
-#include "views/window/window_resources.h"
-
-namespace {
-
-// The frame border is usually 0 as chromeos has no border. The border
-// can be enabled (4px fixed) with the command line option
-// "--chromeos-frame" so that one can resize the window on dev machine.
-const int kFrameBorderThicknessForDev = 4;
-
-// While resize areas on Windows are normally the same size as the window
-// borders, our top area is shrunk by 1 px to make it easier to move the window
-// around with our thinner top grabbable strip. (Incidentally, our side and
-// bottom resize areas don't match the frame border thickness either -- they
-// span the whole nonclient area, so there's no "dead zone" for the mouse.)
-const int kTopResizeAdjust = 1;
-
-// In the window corners, the resize areas don't actually expand bigger, but the
-// 16 px at the end of each edge triggers diagonal resizing.
-const int kResizeAreaCornerSize = 16;
-
-// The icon is inset 2 px from the left frame border.
-const int kIconLeftSpacing = 2;
-
-// The top 1 px of the tabstrip is shadow; in maximized mode we push this off
-// the top of the screen so the tabs appear flush against the screen edge.
-const int kTabstripTopShadowThickness = 1;
-
-const int kCustomFrameBackgroundVerticalOffset = 15;
-
-} // namespace
-
-namespace chromeos {
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, public:
-
-NormalBrowserFrameView::NormalBrowserFrameView(BrowserFrame* frame,
- BrowserView* browser_view)
- : BrowserNonClientFrameView(),
- frame_(frame),
- browser_view_(browser_view) {
- // Normal window does not have the window title/icon.
- DCHECK(!browser_view_->ShouldShowWindowIcon());
- DCHECK(!browser_view_->ShouldShowWindowTitle());
- DCHECK(!frame_->GetWindow()->GetDelegate()->ShouldShowWindowTitle());
- DCHECK(!frame_->GetWindow()->GetDelegate()->ShouldShowWindowIcon());
-}
-
-NormalBrowserFrameView::~NormalBrowserFrameView() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, BrowserNonClientFrameView implementation:
-
-gfx::Rect NormalBrowserFrameView::GetBoundsForTabStrip(
- BaseTabStrip* tabstrip) const {
- int border_thickness = FrameBorderThickness();
- if (browser_view_->UseVerticalTabs()) {
- // BrowserViewLayout adjusts the height/width based on the status area and
- // otr icon.
- gfx::Size ps = tabstrip->GetPreferredSize();
- return gfx::Rect(border_thickness, NonClientTopBorderHeight(),
- ps.width(), browser_view_->height());
- }
- return gfx::Rect(border_thickness, NonClientTopBorderHeight(),
- std::max(0, width() - (2 * border_thickness)),
- tabstrip->GetPreferredHeight());
-}
-
-void NormalBrowserFrameView::UpdateThrobber(bool running) {
- // No window icon.
-}
-
-gfx::Size NormalBrowserFrameView::GetMinimumSize() {
- gfx::Size min_size(browser_view_->GetMinimumSize());
- int border_thickness = FrameBorderThickness();
- min_size.Enlarge(2 * border_thickness,
- NonClientTopBorderHeight() + border_thickness);
-
- int min_titlebar_width = (2 * border_thickness) + kIconLeftSpacing;
- min_size.set_width(std::max(min_size.width(), min_titlebar_width));
- return min_size;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, views::NonClientFrameView implementation:
-
-gfx::Rect NormalBrowserFrameView::GetBoundsForClientView() const {
- return client_view_bounds_;
-}
-
-bool NormalBrowserFrameView::AlwaysUseNativeFrame() const {
- return frame_->AlwaysUseNativeFrame();
-}
-
-gfx::Rect NormalBrowserFrameView::GetWindowBoundsForClientBounds(
- const gfx::Rect& client_bounds) const {
- int top_height = NonClientTopBorderHeight();
- int border_thickness = FrameBorderThickness();
- return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
- std::max(0, client_bounds.y() - top_height),
- client_bounds.width() + (2 * border_thickness),
- client_bounds.height() + top_height + border_thickness);
-}
-
-int NormalBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
- if (!bounds().Contains(point))
- return HTNOWHERE;
- int frame_component =
- frame_->GetWindow()->GetClientView()->NonClientHitTest(point);
- if (frame_component != HTNOWHERE)
- return frame_component;
- int border_thickness = FrameBorderThickness();
- int window_component = GetHTComponentForFrame(point,
- std::max(0, border_thickness - kTopResizeAdjust), border_thickness,
- kResizeAreaCornerSize, kResizeAreaCornerSize,
- frame_->GetWindow()->GetDelegate()->CanResize());
- // Fall back to the caption if no other component matches.
- return (window_component == HTNOWHERE) ? HTCAPTION : window_component;
-}
-
-void NormalBrowserFrameView::GetWindowMask(const gfx::Size& size,
- gfx::Path* window_mask) {
- DCHECK(window_mask);
- // Always maximized.
-}
-
-void NormalBrowserFrameView::EnableClose(bool enable) {
- // No close button
-}
-
-void NormalBrowserFrameView::ResetWindowControls() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, views::View overrides:
-
-void NormalBrowserFrameView::Paint(gfx::Canvas* canvas) {
- views::Window* window = frame_->GetWindow();
- if (window->IsFullscreen())
- return; // Nothing is visible, so don't bother to paint.
-
- PaintMaximizedFrameBorder(canvas);
- PaintToolbarBackground(canvas);
-}
-
-void NormalBrowserFrameView::Layout() {
- int top_height = NonClientTopBorderHeight();
- int border_thickness = FrameBorderThickness();
- client_view_bounds_ = gfx::Rect(border_thickness, top_height,
- std::max(0, width() - (2 * border_thickness)),
- std::max(0, height() - top_height - border_thickness));
-}
-
-bool NormalBrowserFrameView::HitTest(const gfx::Point& l) const {
- // If the point is outside the bounds of the client area, claim it.
- if (NonClientFrameView::HitTest(l))
- return true;
-
- // Otherwise claim it only if it's in a non-tab portion of the tabstrip.
- bool vertical_tabs = browser_view_->UseVerticalTabs();
- const gfx::Rect& tabstrip_bounds = browser_view_->tabstrip()->bounds();
- if ((!vertical_tabs && l.y() > tabstrip_bounds.bottom()) ||
- (vertical_tabs && (l.x() > tabstrip_bounds.right() ||
- l.y() > tabstrip_bounds.bottom()))) {
- return false;
- }
-
- // We convert from our parent's coordinates since we assume we fill its bounds
- // completely. We need to do this since we're not a parent of the tabstrip,
- // meaning ConvertPointToView would otherwise return something bogus.
- gfx::Point browser_view_point(l);
- View::ConvertPointToView(GetParent(), browser_view_, &browser_view_point);
- return browser_view_->IsPositionInWindowCaption(browser_view_point);
-}
-
-void NormalBrowserFrameView::ViewHierarchyChanged(bool is_add,
- views::View* parent,
- views::View* child) {
- if (is_add && child == this) {
- // The Accessibility glue looks for the product name on these two views to
- // determine if this is in fact a Chrome window.
- GetRootView()->SetAccessibleName(l10n_util::GetString(IDS_PRODUCT_NAME));
- }
-}
-
-bool NormalBrowserFrameView::GetAccessibleRole(AccessibilityTypes::Role* role) {
- DCHECK(role);
-
- *role = AccessibilityTypes::ROLE_TITLEBAR;
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, TabIconView::TabContentsProvider implementation:
-
-bool NormalBrowserFrameView::ShouldTabIconViewAnimate() const {
- // This function is queried during the creation of the window as the
- // TabIconView we host is initialized, so we need to NULL check the selected
- // TabContents because in this condition there is not yet a selected tab.
- TabContents* current_tab = browser_view_->GetSelectedTabContents();
- return current_tab ? current_tab->is_loading() : false;
-}
-
-SkBitmap NormalBrowserFrameView::GetFavIconForTabIconView() {
- return frame_->GetWindow()->GetDelegate()->GetWindowIcon();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NormalBrowserFrameView, private:
-
-int NormalBrowserFrameView::FrameBorderThickness() const {
- static int border_thickness_ =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeosFrame) ?
- kFrameBorderThicknessForDev : 0;
- return border_thickness_;
-}
-
-int NormalBrowserFrameView::NonClientTopBorderHeight() const {
- return std::max(0, FrameBorderThickness() -
- (browser_view_->IsTabStripVisible() ? kTabstripTopShadowThickness : 0));
-}
-
-void NormalBrowserFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) {
- ThemeProvider* tp = GetThemeProvider();
- views::Window* window = frame_->GetWindow();
-
- // Window frame mode and color
- SkBitmap* theme_frame;
- int y = 0;
- // Never theme app and popup windows.
- if (!browser_view_->IsBrowserTypeNormal()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- theme_frame = rb.GetBitmapNamed(ShouldPaintAsActive() ?
- IDR_FRAME : IDR_FRAME_INACTIVE);
- } else if (!browser_view_->IsOffTheRecord()) {
- theme_frame = tp->GetBitmapNamed(ShouldPaintAsActive() ?
- IDR_THEME_FRAME : IDR_THEME_FRAME_INACTIVE);
- // TODO(oshima): gtk based CHROMEOS is using non custom frame
- // mode which does this adjustment. This should be removed
- // once it's fully migrated to views. -1 is due to the layout
- // difference between views and gtk and will be removed.
- // See http://crbug.com/28580.
- y = -kCustomFrameBackgroundVerticalOffset - 1;
- } else {
- theme_frame = tp->GetBitmapNamed(ShouldPaintAsActive() ?
- IDR_THEME_FRAME_INCOGNITO: IDR_THEME_FRAME_INCOGNITO_INACTIVE);
- y = -kCustomFrameBackgroundVerticalOffset - 1;
- }
- // Draw the theme frame.
- canvas->TileImageInt(*theme_frame, 0, y, width(), theme_frame->height());
-
- // Draw the theme frame overlay
- if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
- browser_view_->IsBrowserTypeNormal()) {
- SkBitmap* theme_overlay = tp->GetBitmapNamed(ShouldPaintAsActive() ?
- IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE);
- canvas->DrawBitmapInt(*theme_overlay, 0, 0);
- }
-
- if (!browser_view_->IsToolbarVisible()) {
- // There's no toolbar to edge the frame border, so we need to draw a bottom
- // edge. The graphic we use for this has a built in client edge, so we clip
- // it off the bottom.
- SkBitmap* top_center =
- tp->GetBitmapNamed(IDR_APP_TOP_CENTER);
- int edge_height = top_center->height() - kClientEdgeThickness;
- canvas->TileImageInt(*top_center, 0,
- window->GetClientView()->y() - edge_height, width(), edge_height);
- }
-}
-
-void NormalBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
- if (!browser_view_->IsToolbarVisible())
- return;
-
- gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds());
- if (toolbar_bounds.IsEmpty())
- return;
-
- ThemeProvider* tp = GetThemeProvider();
- gfx::Point toolbar_origin(toolbar_bounds.origin());
- View::ConvertPointToView(frame_->GetWindow()->GetClientView(),
- this, &toolbar_origin);
- toolbar_bounds.set_origin(toolbar_origin);
-
- // Gross hack: We split the toolbar images into two pieces, since sometimes
- // (popup mode) the toolbar isn't tall enough to show the whole image. The
- // split happens between the top shadow section and the bottom gradient
- // section so that we never break the gradient.
- int split_point = kFrameShadowThickness * 2;
- int bottom_y = toolbar_bounds.y() + split_point;
- SkBitmap* toolbar_left =
- tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER);
- int bottom_edge_height =
- std::min(toolbar_left->height(), toolbar_bounds.height()) - split_point;
-
- SkColor theme_toolbar_color =
- tp->GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
- canvas->FillRectInt(theme_toolbar_color, toolbar_bounds.x(), bottom_y,
- toolbar_bounds.width(), bottom_edge_height);
-
- int strip_height = browser_view_->GetTabStripHeight();
- SkBitmap* theme_toolbar = tp->GetBitmapNamed(IDR_THEME_TOOLBAR);
-
- canvas->TileImageInt(*theme_toolbar,
- toolbar_bounds.x() - kClientEdgeThickness,
- strip_height - kFrameShadowThickness,
- toolbar_bounds.x() - kClientEdgeThickness, bottom_y,
- toolbar_bounds.width() + (2 * kClientEdgeThickness),
- theme_toolbar->height());
-
- canvas->DrawBitmapInt(*toolbar_left, 0, 0, toolbar_left->width(), split_point,
- toolbar_bounds.x() - toolbar_left->width(), toolbar_bounds.y(),
- toolbar_left->width(), split_point, false);
- canvas->DrawBitmapInt(*toolbar_left, 0,
- toolbar_left->height() - bottom_edge_height, toolbar_left->width(),
- bottom_edge_height, toolbar_bounds.x() - toolbar_left->width(), bottom_y,
- toolbar_left->width(), bottom_edge_height, false);
-
- SkBitmap* toolbar_center =
- tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER);
- canvas->TileImageInt(*toolbar_center, 0, 0, toolbar_bounds.x(),
- toolbar_bounds.y(), toolbar_bounds.width(), split_point);
-
- SkBitmap* toolbar_right = tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER);
- canvas->DrawBitmapInt(*toolbar_right, 0, 0, toolbar_right->width(),
- split_point, toolbar_bounds.right(), toolbar_bounds.y(),
- toolbar_right->width(), split_point, false);
- canvas->DrawBitmapInt(*toolbar_right, 0,
- toolbar_right->height() - bottom_edge_height, toolbar_right->width(),
- bottom_edge_height, toolbar_bounds.right(), bottom_y,
- toolbar_right->width(), bottom_edge_height, false);
-
- // Draw the content/toolbar separator.
- canvas->DrawLineInt(ResourceBundle::toolbar_separator_color,
- toolbar_bounds.x(), toolbar_bounds.bottom() - 1,
- toolbar_bounds.right() - 1, toolbar_bounds.bottom() - 1);
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/frame/normal_browser_frame_view.h b/chrome/browser/chromeos/frame/normal_browser_frame_view.h
deleted file mode 100644
index 5de45dc..0000000
--- a/chrome/browser/chromeos/frame/normal_browser_frame_view.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_FRAME_NORMAL_BROWSER_FRAME_VIEW_H_
-#define CHROME_BROWSER_CHROMEOS_FRAME_NORMAL_BROWSER_FRAME_VIEW_H_
-
-#include "chrome/browser/views/frame/browser_frame.h"
-#include "chrome/browser/views/frame/browser_non_client_frame_view.h"
-#include "chrome/browser/views/tab_icon_view.h"
-#include "views/controls/button/button.h"
-#include "views/window/non_client_view.h"
-
-class BaseTabStrip;
-class BrowserView;
-namespace gfx {
-class Font;
-}
-class TabContents;
-namespace views {
-class ImageButton;
-class ImageView;
-}
-
-namespace chromeos {
-
-class NormalBrowserFrameView : public BrowserNonClientFrameView,
- public TabIconView::TabIconViewModel {
- public:
- // Constructs a non-client view for an BrowserFrame.
- NormalBrowserFrameView(BrowserFrame* frame, BrowserView* browser_view);
- virtual ~NormalBrowserFrameView();
-
- // Overridden from BrowserNonClientFrameView:
- virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
- virtual void UpdateThrobber(bool running);
- virtual gfx::Size GetMinimumSize();
-
- protected:
- // Overridden from views::NonClientFrameView:
- virtual gfx::Rect GetBoundsForClientView() const;
- virtual bool AlwaysUseNativeFrame() const;
- virtual gfx::Rect GetWindowBoundsForClientBounds(
- const gfx::Rect& client_bounds) const;
- virtual int NonClientHitTest(const gfx::Point& point);
- virtual void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask);
- virtual void EnableClose(bool enable);
- virtual void ResetWindowControls();
-
- // Overridden from views::View:
- virtual void Paint(gfx::Canvas* canvas);
- virtual void Layout();
- virtual bool HitTest(const gfx::Point& l) const;
- virtual void ViewHierarchyChanged(bool is_add,
- views::View* parent,
- views::View* child);
- virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
-
- // Overridden from TabIconView::TabIconViewModel:
- virtual bool ShouldTabIconViewAnimate() const;
- virtual SkBitmap GetFavIconForTabIconView();
-
- private:
- // Returns the thickness of the border that makes up the window frame edges.
- // This does not include any client edge.
- int FrameBorderThickness() const;
-
- // Returns the height of the entire nonclient top border, including the window
- // frame, any title area, and any connected client edge.
- int NonClientTopBorderHeight() const;
-
- // Paint various sub-components of this view. The *FrameBorder() functions
- // also paint the background of the titlebar area, since the top frame border
- // and titlebar background are a contiguous component.
- void PaintMaximizedFrameBorder(gfx::Canvas* canvas);
- void PaintToolbarBackground(gfx::Canvas* canvas);
-
- // The frame that hosts this view.
- BrowserFrame* frame_;
-
- // The BrowserView hosted within this View.
- BrowserView* browser_view_;
-
- // The bounds of the ClientView.
- gfx::Rect client_view_bounds_;
-
- DISALLOW_COPY_AND_ASSIGN(NormalBrowserFrameView);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_FRAME_NORMAL_BROWSER_FRAME_VIEW_H_
diff --git a/chrome/browser/chromeos/frame/panel_browser_view.cc b/chrome/browser/chromeos/frame/panel_browser_view.cc
index 0d72579..b52f035 100644
--- a/chrome/browser/chromeos/frame/panel_browser_view.cc
+++ b/chrome/browser/chromeos/frame/panel_browser_view.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/chromeos/frame/panel_browser_view.h"
#include "chrome/browser/chromeos/frame/panel_controller.h"
-#include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "cros/chromeos_wm_ipc_enums.h"
#include "views/window/window.h"
namespace chromeos {
@@ -36,10 +36,12 @@ void PanelBrowserView::Init() {
}
void PanelBrowserView::Show() {
- panel_controller_.reset(new PanelController(this, GetNativeHandle()));
- panel_controller_->Init(
- true /* focus when opened */, bounds(), creator_xid_,
- WM_IPC_PANEL_USER_RESIZE_HORIZONTALLY_AND_VERTICALLY);
+ if (panel_controller_.get() == NULL) {
+ panel_controller_.reset(new PanelController(this, GetNativeHandle()));
+ panel_controller_->Init(
+ true /* focus when opened */, bounds(), creator_xid_,
+ WM_IPC_PANEL_USER_RESIZE_HORIZONTALLY_AND_VERTICALLY);
+ }
BrowserView::Show();
}
diff --git a/chrome/browser/chromeos/frame/panel_browser_view.h b/chrome/browser/chromeos/frame/panel_browser_view.h
index c3d7ec3..337245f 100644
--- a/chrome/browser/chromeos/frame/panel_browser_view.h
+++ b/chrome/browser/chromeos/frame/panel_browser_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_FRAME_PANEL_BROWSER_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_FRAME_PANEL_BROWSER_VIEW_H_
+#pragma once
#include "app/x11_util.h"
#include "base/scoped_ptr.h"
diff --git a/chrome/browser/chromeos/frame/panel_controller.cc b/chrome/browser/chromeos/frame/panel_controller.cc
index 621f63a..2f3f7eb 100644
--- a/chrome/browser/chromeos/frame/panel_controller.cc
+++ b/chrome/browser/chromeos/frame/panel_controller.cc
@@ -8,20 +8,25 @@
#include "app/resource_bundle.h"
#include "base/logging.h"
-#include "base/singleton.h"
#include "base/scoped_ptr.h"
+#include "base/singleton.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/common/notification_service.h"
+#include "cros/chromeos_wm_ipc_enums.h"
+#include "gfx/canvas_skia.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "cros/chromeos_wm_ipc_enums.h"
+#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/controls/button/image_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/event.h"
+#include "views/painter.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window.h"
@@ -39,20 +44,43 @@ static gfx::Font* inactive_font = NULL;
namespace {
-const int kTitleWidth = 200;
-const int kTitleHeight = 20;
+const int kTitleHeight = 24;
const int kTitleIconSize = 16;
-const int kTitleWidthPad = 2;
-const int kTitleHeightPad = 1;
-const int kButtonPad = 4;
-
-const SkColor kActiveGradientStart = 0xffebeff9;
-const SkColor kActiveGradientEnd = 0xffb3c4f6;
-const SkColor kInactiveGradientStart = 0xfff2f2f2;
-const SkColor kInactiveGradientEnd = 0xfff2f2f2;
-const SkColor kActiveColor = SK_ColorBLACK;
-const SkColor kInactiveColor = 0xff333333;
-const SkColor kCloseButtonColor = SK_ColorBLACK;
+const int kTitleWidthPad = 4;
+const int kTitleHeightPad = 4;
+const int kTitleCornerRadius = 4;
+const int kTitleCloseButtonPad = 6;
+const SkColor kTitleActiveGradientStart = SK_ColorWHITE;
+const SkColor kTitleActiveGradientEnd = 0xffe7edf1;
+const SkColor kTitleActiveColor = SK_ColorBLACK;
+const SkColor kTitleInactiveColor = SK_ColorBLACK;
+const SkColor kTitleCloseButtonColor = SK_ColorBLACK;
+
+// Used to draw the background of the panel title window.
+class TitleBackgroundPainter : public views::Painter {
+ virtual void Paint(int w, int h, gfx::Canvas* canvas) {
+ SkRect rect = {0, 0, w, h};
+ SkPath path;
+ SkScalar corners[] = {
+ kTitleCornerRadius, kTitleCornerRadius,
+ kTitleCornerRadius, kTitleCornerRadius,
+ 0, 0,
+ 0, 0
+ };
+ path.addRoundRect(rect, corners);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ SkPoint p[2] = {{0, 0}, {0, h}};
+ SkColor colors[2] = {kTitleActiveGradientStart, kTitleActiveGradientEnd};
+ SkShader* s = SkGradientShader::CreateLinear(
+ p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
+ paint.setShader(s);
+ // Need to unref shader, otherwise never deleted.
+ s->unref();
+ canvas->AsCanvasSkia()->drawPath(path, paint);
+ }
+};
static bool resources_initialized;
static void InitializeResources() {
@@ -62,8 +90,10 @@ static void InitializeResources() {
resources_initialized = true;
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- inactive_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont));
- active_font = new gfx::Font(inactive_font->DeriveFont(0, gfx::Font::BOLD));
+ gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont);
+ // Title fonts are the same for active and inactive.
+ inactive_font = new gfx::Font(base_font.DeriveFont(0, gfx::Font::BOLD));
+ active_font = inactive_font;
close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
@@ -92,10 +122,10 @@ void PanelController::Init(bool initial_focus,
const gfx::Rect& window_bounds,
XID creator_xid,
WmIpcPanelUserResizeType resize_type) {
- gfx::Rect title_bounds(
- 0, 0, window_bounds.width(), kTitleHeight);
+ gfx::Rect title_bounds(0, 0, window_bounds.width(), kTitleHeight);
title_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
+ title_window_->MakeTransparent();
title_window_->Init(NULL, title_bounds);
gtk_widget_set_size_request(title_window_->GetNativeView(),
title_bounds.width(), title_bounds.height());
@@ -285,13 +315,14 @@ void PanelController::OnCloseButtonPressed() {
PanelController::TitleContentView::TitleContentView(
PanelController* panel_controller)
: panel_controller_(panel_controller) {
+ LOG(INFO) << "panel: c " << this;
InitializeResources();
close_button_ = new views::ImageButton(this);
close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
close_button_->SetBackground(
- kCloseButtonColor, close_button_n, close_button_m);
+ kTitleCloseButtonColor, close_button_n, close_button_m);
AddChildView(close_button_);
title_icon_ = new views::ImageView();
@@ -300,12 +331,15 @@ PanelController::TitleContentView::TitleContentView(
title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(title_label_);
- // Default to inactive
+ set_background(
+ views::Background::CreateBackgroundPainter(
+ true, new TitleBackgroundPainter()));
OnFocusOut();
}
void PanelController::TitleContentView::Layout() {
- int close_button_x = bounds().width() - (close_button_width + kButtonPad);
+ int close_button_x = bounds().width() -
+ (close_button_width + kTitleCloseButtonPad);
close_button_->SetBounds(
close_button_x,
(bounds().height() - close_button_height) / 2,
@@ -313,15 +347,15 @@ void PanelController::TitleContentView::Layout() {
close_button_height);
title_icon_->SetBounds(
kTitleWidthPad,
- kTitleHeightPad * 2,
+ kTitleHeightPad,
kTitleIconSize,
kTitleIconSize);
int title_x = kTitleWidthPad * 2 + kTitleIconSize;
title_label_->SetBounds(
title_x,
- kTitleHeightPad,
- close_button_x - (title_x + kButtonPad),
- bounds().height() - kTitleHeightPad);
+ 0,
+ close_button_x - (title_x + kTitleCloseButtonPad),
+ bounds().height());
}
bool PanelController::TitleContentView::OnMousePressed(
@@ -343,18 +377,14 @@ bool PanelController::TitleContentView::OnMouseDragged(
}
void PanelController::TitleContentView::OnFocusIn() {
- set_background(views::Background::CreateVerticalGradientBackground(
- kActiveGradientStart, kActiveGradientEnd));
- title_label_->SetColor(kActiveColor);
+ title_label_->SetColor(kTitleActiveColor);
title_label_->SetFont(*active_font);
Layout();
SchedulePaint();
}
void PanelController::TitleContentView::OnFocusOut() {
- set_background(views::Background::CreateVerticalGradientBackground(
- kInactiveGradientStart, kInactiveGradientEnd));
- title_label_->SetColor(kInactiveColor);
+ title_label_->SetColor(kTitleInactiveColor);
title_label_->SetFont(*inactive_font);
Layout();
SchedulePaint();
@@ -370,4 +400,8 @@ void PanelController::TitleContentView::ButtonPressed(
panel_controller_->OnCloseButtonPressed();
}
+PanelController::TitleContentView::~TitleContentView() {
+ LOG(INFO) << "panel: delete " << this;
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/frame/panel_controller.h b/chrome/browser/chromeos/frame/panel_controller.h
index 32be295..5d4920f 100644
--- a/chrome/browser/chromeos/frame/panel_controller.h
+++ b/chrome/browser/chromeos/frame/panel_controller.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_FRAME_PANEL_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_FRAME_PANEL_CONTROLLER_H_
+#pragma once
#include <gtk/gtk.h>
#include "app/x11_util.h"
+#include "cros/chromeos_wm_ipc_enums.h"
#include "views/controls/button/button.h"
-#include "third_party/cros/chromeos_wm_ipc_enums.h"
class BrowserView;
class SkBitmap;
@@ -73,7 +74,7 @@ class PanelController {
public views::ButtonListener {
public:
explicit TitleContentView(PanelController* panelController);
- virtual ~TitleContentView() {}
+ virtual ~TitleContentView();
virtual void Layout();
virtual bool OnMousePressed(const views::MouseEvent& event);
virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
diff --git a/chrome/browser/chromeos/google_update_chromeos.cc b/chrome/browser/chromeos/google_update_chromeos.cc
index a7b2cc3..c1bf0ba 100644
--- a/chrome/browser/chromeos/google_update_chromeos.cc
+++ b/chrome/browser/chromeos/google_update_chromeos.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/google_update.h"
+#include "chrome/browser/google/google_update.h"
#include "base/message_loop.h"
#include "base/path_service.h"
diff --git a/chrome/browser/chromeos/gview_request_interceptor.cc b/chrome/browser/chromeos/gview_request_interceptor.cc
index dba4d9d..1d2b9cc 100644
--- a/chrome/browser/chromeos/gview_request_interceptor.cc
+++ b/chrome/browser/chromeos/gview_request_interceptor.cc
@@ -6,13 +6,14 @@
#include "base/file_path.h"
#include "base/path_service.h"
+#include "base/singleton.h"
#include "chrome/common/chrome_paths.h"
+#include "googleurl/src/gurl.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
-#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_redirect_job.h"
-#include "googleurl/src/gurl.h"
#include "webkit/glue/plugins/plugin_list.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/gview_request_interceptor.h b/chrome/browser/chromeos/gview_request_interceptor.h
index dcb5f20..adbbd25 100644
--- a/chrome/browser/chromeos/gview_request_interceptor.h
+++ b/chrome/browser/chromeos/gview_request_interceptor.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_GVIEW_REQUEST_INTERCEPTOR_H__
#define CHROME_BROWSER_CHROMEOS_GVIEW_REQUEST_INTERCEPTOR_H__
+#pragma once
#include <string>
#include "base/hash_tables.h"
diff --git a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
index 1cc28b9..7ba3b5d 100644
--- a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
+++ b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
@@ -5,12 +5,15 @@
#include <string>
#include "base/message_loop.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
+#include "chrome/browser/plugin_service.h"
+#include "chrome/common/chrome_paths.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_unittest.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/plugins/plugin_list.h"
namespace chromeos {
@@ -49,6 +52,7 @@ class GViewRequestInterceptorTest : public testing::Test {
URLRequest::RegisterProtocolFactory("http",
&GViewRequestInterceptorTest::Factory);
interceptor_ = GViewRequestInterceptor::GetGViewRequestInterceptor();
+ ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path_));
}
virtual void TearDown() {
@@ -61,10 +65,44 @@ class GViewRequestInterceptorTest : public testing::Test {
return new GViewURLRequestTestJob(request);
}
+ void RegisterPDFPlugin() {
+ NPAPI::PluginVersionInfo info;
+ info.path = pdf_path_;
+ memset(&info.entry_points, 0, sizeof(info.entry_points));
+ NPAPI::PluginList::Singleton()->RegisterInternalPlugin(info);
+ NPAPI::PluginList::Singleton()->RefreshPlugins();
+ }
+
+ void UnregisterPDFPlugin() {
+ NPAPI::PluginList::Singleton()->UnregisterInternalPlugin(pdf_path_);
+ NPAPI::PluginList::Singleton()->RefreshPlugins();
+ }
+
+ void SetPDFPluginLoadedState(bool want_loaded, bool* out_is_enabled) {
+ WebPluginInfo info;
+ bool is_loaded =
+ NPAPI::PluginList::Singleton()->GetPluginInfoByPath(pdf_path_, &info);
+ if (is_loaded && !want_loaded) {
+ UnregisterPDFPlugin();
+ is_loaded =
+ NPAPI::PluginList::Singleton()->GetPluginInfoByPath(pdf_path_, &info);
+ } else if (!is_loaded && want_loaded) {
+ // This "loads" the plug-in even if it's not present on the
+ // system - which is OK since we don't actually use it, just
+ // need it to be "enabled" for the test.
+ RegisterPDFPlugin();
+ is_loaded =
+ NPAPI::PluginList::Singleton()->GetPluginInfoByPath(pdf_path_, &info);
+ }
+ EXPECT_EQ(want_loaded, is_loaded);
+ *out_is_enabled = info.enabled;
+ }
+
protected:
MessageLoopForIO message_loop_;
TestDelegate test_delegate_;
URLRequest::Interceptor* interceptor_;
+ FilePath pdf_path_;
};
TEST_F(GViewRequestInterceptorTest, DoNotInterceptHtml) {
@@ -84,7 +122,46 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) {
EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
}
-TEST_F(GViewRequestInterceptorTest, InterceptPdf) {
+TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
+ bool enabled;
+ SetPDFPluginLoadedState(true, &enabled);
+
+ if (!enabled) {
+ bool pdf_plugin_enabled =
+ NPAPI::PluginList::Singleton()->EnablePlugin(pdf_path_);
+ EXPECT_TRUE(pdf_plugin_enabled);
+ }
+
+ URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
+ request.Start();
+ MessageLoop::current()->Run();
+ EXPECT_EQ(0, test_delegate_.received_redirect_count());
+ EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
+}
+
+TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) {
+ bool enabled;
+ SetPDFPluginLoadedState(true, &enabled);
+
+ if (enabled) {
+ bool pdf_plugin_disabled =
+ NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path_);
+ EXPECT_TRUE(pdf_plugin_disabled);
+ }
+
+ URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
+ request.Start();
+ MessageLoop::current()->Run();
+ EXPECT_EQ(1, test_delegate_.received_redirect_count());
+ EXPECT_EQ(
+ GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.pdf"),
+ request.url());
+}
+
+TEST_F(GViewRequestInterceptorTest, InterceptPdfWithNoPlugin) {
+ bool enabled;
+ SetPDFPluginLoadedState(false, &enabled);
+
URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
request.Start();
MessageLoop::current()->Run();
diff --git a/chrome/browser/chromeos/input_method/candidate_window.cc b/chrome/browser/chromeos/input_method/candidate_window.cc
index 2e95a20..3444f53 100644
--- a/chrome/browser/chromeos/input_method/candidate_window.cc
+++ b/chrome/browser/chromeos/input_method/candidate_window.cc
@@ -11,23 +11,26 @@
#include <vector>
#include "app/app_paths.h"
+#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/at_exit.h"
#include "base/command_line.h"
-#include "base/file_path.h"
#include "base/logging.h"
#include "base/observer_list.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library_loader.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
-#include "gfx/canvas.h"
-#include "gfx/font.h"
#include "cros/chromeos_cros_api.h"
#include "cros/chromeos_input_method_ui.h"
+#include "gfx/canvas.h"
+#include "gfx/font.h"
+#include "grit/app_locale_settings.h"
#include "views/controls/label.h"
#include "views/controls/textfield/textfield.h"
#include "views/event.h"
@@ -54,6 +57,11 @@ const SkColor kFooterTopColor = SkColorSetRGB(0xff, 0xff, 0xff);
const SkColor kFooterBottomColor = SkColorSetRGB(0xee, 0xee, 0xee);
const SkColor kShortcutColor = SkColorSetRGB(0x61, 0x61, 0x61);
const SkColor kDisabledShortcutColor = SkColorSetRGB(0xcc, 0xcc, 0xcc);
+const SkColor kAnnotationColor = SkColorSetRGB(0x88, 0x88, 0x88);
+
+// We'll use a bigger font size, so Chinese characters are more readable
+// in the candidate window.
+const int kFontSizeDelta = 2; // Two size bigger.
// The minimum width of candidate labels in the vertical candidate
// window. We use this value to prevent the candidate window from being
@@ -64,6 +72,29 @@ const int kMinCandidateLabelWidth = 100;
// too wide when one of candidates are long.
const int kMaxCandidateLabelWidth = 500;
+// VerticalCandidateLabel is used for rendering candidate text in
+// the vertical candidate window.
+class VerticalCandidateLabel : public views::Label {
+ virtual ~VerticalCandidateLabel() {}
+
+ // Returns the preferred size, but guarantees that the width has at
+ // least kMinCandidateLabelWidth pixels.
+ virtual gfx::Size GetPreferredSize() {
+ gfx::Size size = Label::GetPreferredSize();
+ // Hack. +2 is needed to prevent labels from getting elided like
+ // "abc..." in some cases. TODO(satorux): Figure out why it's
+ // necessary.
+ size.set_width(size.width() + 2);
+ if (size.width() < kMinCandidateLabelWidth) {
+ size.set_width(kMinCandidateLabelWidth);
+ }
+ if (size.width() > kMaxCandidateLabelWidth) {
+ size.set_width(kMaxCandidateLabelWidth);
+ }
+ return size;
+ }
+};
+
// Wraps the given view with some padding, and returns it.
views::View* WrapWithPadding(views::View* view, const gfx::Insets& insets) {
views::View* wrapper = new views::View;
@@ -83,6 +114,193 @@ views::View* WrapWithPadding(views::View* view, const gfx::Insets& insets) {
return wrapper;
}
+// Creates shortcut text from the given index and the orientation.
+std::wstring CreateShortcutText(int index,
+ chromeos::InputMethodLookupTable::Orientation orientation) {
+ // Choose the character used for the shortcut label.
+ const wchar_t kShortcutCharacters[] = L"1234567890ABCDEF";
+ // The default character should not be used but just in case.
+ wchar_t shortcut_character = L'?';
+ // -1 to exclude the null character at the end.
+ if (index < static_cast<int>(arraysize(kShortcutCharacters) - 1)) {
+ shortcut_character = kShortcutCharacters[index];
+ }
+
+ std::wstring shortcut_text;
+ if (orientation == chromeos::InputMethodLookupTable::kVertical) {
+ shortcut_text = base::StringPrintf(L"%lc", shortcut_character);
+ } else {
+ shortcut_text = base::StringPrintf(L"%lc.", shortcut_character);
+ }
+
+ return shortcut_text;
+}
+
+// Creates the shortcut label, and returns it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateShortcutLabel(
+ chromeos::InputMethodLookupTable::Orientation orientation) {
+ // Create the shortcut label. The label will be owned by
+ // |wrapped_shortcut_label|, hence it's deleted when
+ // |wrapped_shortcut_label| is deleted.
+ views::Label* shortcut_label = new views::Label;
+
+ if (orientation == chromeos::InputMethodLookupTable::kVertical) {
+ shortcut_label->SetFont(
+ shortcut_label->font().DeriveFont(kFontSizeDelta, gfx::Font::BOLD));
+ } else {
+ shortcut_label->SetFont(
+ shortcut_label->font().DeriveFont(kFontSizeDelta));
+ }
+ // TODO(satorux): Maybe we need to use language specific fonts for
+ // candidate_label, like Chinese font for Chinese input method?
+ shortcut_label->SetColor(kShortcutColor);
+
+ return shortcut_label;
+}
+
+// Wraps the shortcut label, then decorates wrapped shortcut label
+// and returns it (never returns NULL).
+// The label text is not set in this function.
+views::View* CreateWrappedShortcutLabel(views::Label* shortcut_label,
+ chromeos::InputMethodLookupTable::Orientation orientation) {
+ // Wrap it with padding.
+ const gfx::Insets kVerticalShortcutLabelInsets(1, 6, 1, 6);
+ const gfx::Insets kHorizontalShortcutLabelInsets(1, 3, 1, 0);
+ const gfx::Insets insets =
+ (orientation == chromeos::InputMethodLookupTable::kVertical ?
+ kVerticalShortcutLabelInsets :
+ kHorizontalShortcutLabelInsets);
+ views::View* wrapped_shortcut_label =
+ WrapWithPadding(shortcut_label, insets);
+
+ // Add decoration based on the orientation.
+ if (orientation == chromeos::InputMethodLookupTable::kVertical) {
+ // Set the background color.
+ wrapped_shortcut_label->set_background(
+ views::Background::CreateSolidBackground(
+ kShortcutBackgroundColor));
+ }
+
+ return wrapped_shortcut_label;
+}
+
+// Creates the candidate label, and returns it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateCandidateLabel(
+ chromeos::InputMethodLookupTable::Orientation orientation) {
+ views::Label* candidate_label = NULL;
+
+ // Create the candidate label. The label will be added to |this| as a
+ // child view, hence it's deleted when |this| is deleted.
+ if (orientation == chromeos::InputMethodLookupTable::kVertical) {
+ candidate_label = new VerticalCandidateLabel;
+ } else {
+ candidate_label = new views::Label;
+ }
+
+ // Change the font size.
+ candidate_label->SetFont(
+ candidate_label->font().DeriveFont(kFontSizeDelta));
+ candidate_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+
+ return candidate_label;
+}
+
+// Creates the annotation label, and return it (never returns NULL).
+// The label text is not set in this function.
+views::Label* CreateAnnotationLabel(
+ chromeos::InputMethodLookupTable::Orientation orientation) {
+ // Create the annotation label.
+ views::Label* annotation_label = new views::Label;
+
+ // Change the font size and color.
+ annotation_label->SetFont(
+ annotation_label->font().DeriveFont(kFontSizeDelta));
+ annotation_label->SetColor(kAnnotationColor);
+ annotation_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+
+ return annotation_label;
+}
+
+// Computes shortcut column width.
+int ComputeShortcutColumnWidth(
+ const chromeos::InputMethodLookupTable& lookup_table) {
+ int shortcut_column_width = 0;
+ // Create the shortcut label. The label will be owned by
+ // |wrapped_shortcut_label|, hence it's deleted when
+ // |wrapped_shortcut_label| is deleted.
+ views::Label* shortcut_label = CreateShortcutLabel(lookup_table.orientation);
+ scoped_ptr<views::View> wrapped_shortcut_label(
+ CreateWrappedShortcutLabel(shortcut_label, lookup_table.orientation));
+
+ // Compute the max width in shortcut labels.
+ // We'll create temporary shortcut labels, and choose the largest width.
+ for (int i = 0; i < lookup_table.page_size; ++i) {
+ shortcut_label->SetText(
+ CreateShortcutText(i, lookup_table.orientation));
+ shortcut_column_width =
+ std::max(shortcut_column_width,
+ wrapped_shortcut_label->GetPreferredSize().width());
+ }
+
+ return shortcut_column_width;
+}
+
+// Computes candidate column width.
+int ComputeCandidateColumnWidth(
+ const chromeos::InputMethodLookupTable& lookup_table) {
+ int candidate_column_width = 0;
+ scoped_ptr<views::Label> candidate_label(
+ CreateCandidateLabel(lookup_table.orientation));
+
+ // Compute the start index of |lookup_table_|.
+ const int current_page_index =
+ lookup_table.cursor_absolute_index / lookup_table.page_size;
+ const size_t start_from = current_page_index * lookup_table.page_size;
+
+ // Compute the max width in candidate labels.
+ // We'll create temporary candidate labels, and choose the largest width.
+ for (size_t i = 0; i < lookup_table.candidates.size(); ++i) {
+ const size_t index = start_from + i;
+
+ candidate_label->SetText(
+ UTF8ToWide(lookup_table.candidates[index]));
+ candidate_column_width =
+ std::max(candidate_column_width,
+ candidate_label->GetPreferredSize().width());
+ }
+
+ return candidate_column_width;
+}
+
+// Computes annotation column width.
+int ComputeAnnotationColumnWidth(
+ const chromeos::InputMethodLookupTable& lookup_table) {
+ int annotation_column_width = 0;
+ scoped_ptr<views::Label> annotation_label(
+ CreateAnnotationLabel(lookup_table.orientation));
+
+ // Compute the start index of |lookup_table_|.
+ const int current_page_index =
+ lookup_table.cursor_absolute_index / lookup_table.page_size;
+ const size_t start_from = current_page_index * lookup_table.page_size;
+
+ // Compute max width in annotation labels.
+ // We'll create temporary annotation labels, and choose the largest width.
+ for (size_t i = 0; i < lookup_table.annotations.size(); ++i) {
+ const size_t index = start_from + i;
+
+ annotation_label->SetText(
+ UTF8ToWide(lookup_table.annotations[index]));
+ annotation_column_width =
+ std::max(annotation_column_width,
+ annotation_label->GetPreferredSize().width());
+ }
+
+ return annotation_column_width;
+}
+
} // namespace
namespace chromeos {
@@ -163,8 +381,7 @@ class CandidateWindowView : public views::View {
private:
// Initializes the candidate views if needed.
void MaybeInitializeCandidateViews(
- int num_views,
- InputMethodLookupTable::Orientation orientation);
+ const InputMethodLookupTable& lookup_table);
// Creates the footer area, where we show status information.
// For instance, we show a cursor position like 2/19.
@@ -216,6 +433,11 @@ class CandidateWindowView : public views::View {
views::Label* header_label_;
// The footer label is shown in the footer area.
views::Label* footer_label_;
+
+ // Current columns width in |candidate_area_|.
+ int previous_shortcut_column_width_;
+ int previous_candidate_column_width_;
+ int previous_annotation_column_width_;
};
// CandidateRow renderes a row of a candidate.
@@ -225,7 +447,11 @@ class CandidateView : public views::View {
int index_in_page,
InputMethodLookupTable::Orientation orientation);
virtual ~CandidateView() {}
- void Init();
+ // Initializes the candidate view with the given column widths.
+ // A width of 0 means that the column is resizable.
+ void Init(int shortcut_column_width,
+ int candidate_column_width,
+ int annotation_column_width);
// Sets candidate text to the given text.
void SetCandidateText(const std::wstring& text);
@@ -233,8 +459,8 @@ class CandidateView : public views::View {
// Sets shortcut text to the given text.
void SetShortcutText(const std::wstring& text);
- // Sets shortcut text from the given integer.
- void SetShortcutTextFromInt(int index);
+ // Sets annotation text to the given text.
+ void SetAnnotationText(const std::wstring& text);
// Selects the candidate row. Changes the appearance to make it look
// like a selected candidate.
@@ -278,29 +504,8 @@ class CandidateView : public views::View {
views::Label* shortcut_label_;
// The candidate label renders candidates.
views::Label* candidate_label_;
-};
-
-// VerticalCandidateLabel is used for rendering candidate text in
-// the vertical candidate window.
-class VerticalCandidateLabel : public views::Label {
- virtual ~VerticalCandidateLabel() {}
-
- // Returns the preferred size, but guarantees that the width has at
- // least kMinCandidateLabelWidth pixels.
- virtual gfx::Size GetPreferredSize() {
- gfx::Size size = Label::GetPreferredSize();
- // Hack. +2 is needed to prevent labels from getting elided like
- // "abc..." in some cases. TODO(satorux): Figure out why it's
- // necessary.
- size.set_width(size.width() + 2);
- if (size.width() < kMinCandidateLabelWidth) {
- size.set_width(kMinCandidateLabelWidth);
- }
- if (size.width() > kMaxCandidateLabelWidth) {
- size.set_width(kMaxCandidateLabelWidth);
- }
- return size;
- }
+ // The annotation label renders annotations.
+ views::Label* annotation_label_;
};
// CandidateWindowController controls the CandidateWindow.
@@ -308,12 +513,12 @@ class CandidateWindowController : public CandidateWindowView::Observer {
public:
CandidateWindowController();
virtual ~CandidateWindowController();
- void Init();
+ bool Init();
// Returns the work area of the monitor nearest the candidate window.
gfx::Rect GetMonitorWorkAreaNearestWindow();
- // Moves the candidate window per the the given cursor location, and the
+ // Moves the candidate window per the given cursor location, and the
// horizontal offset.
void MoveCandidateWindow(const gfx::Rect& cursor_location,
int horizontal_offset);
@@ -359,6 +564,10 @@ class CandidateWindowController : public CandidateWindowView::Observer {
static void OnUpdateLookupTable(void* input_method_library,
const InputMethodLookupTable& lookup_table);
+ // This function is called by libcros when ibus connects or disconnects.
+ // |input_method_library| is a void pointer to this object.
+ static void OnConnectionChange(void* input_method_library, bool connected);
+
// The connection is used for communicating with input method UI logic
// in libcros.
InputMethodUiStatusConnection* ui_status_connection_;
@@ -382,83 +591,57 @@ CandidateView::CandidateView(
orientation_(orientation),
parent_candidate_window_(parent_candidate_window),
shortcut_label_(NULL),
- candidate_label_(NULL) {
+ candidate_label_(NULL),
+ annotation_label_(NULL) {
}
-void CandidateView::Init() {
+void CandidateView::Init(int shortcut_column_width,
+ int candidate_column_width,
+ int annotation_column_width) {
views::GridLayout* layout = new views::GridLayout(this);
SetLayoutManager(layout); // |this| owns |layout|.
- // Create the shortcut label. The label will eventually be part of the
- // tree of |this| via |wrapped_shortcut_label|, hence it's deleted when
- // |this| is deleted.
- shortcut_label_ = new views::Label();
-
- // Wrap it with padding.
- const gfx::Insets kVerticalShortcutLabelInsets(1, 6, 1, 6);
- const gfx::Insets kHorizontalShortcutLabelInsets(1, 3, 1, 0);
- const gfx::Insets insets =
- (orientation_ == InputMethodLookupTable::kVertical ?
- kVerticalShortcutLabelInsets :
- kHorizontalShortcutLabelInsets);
+ // Create Labels.
+ shortcut_label_ = CreateShortcutLabel(orientation_);
views::View* wrapped_shortcut_label =
- WrapWithPadding(shortcut_label_, insets);
- // We'll use a bigger font size, so Chinese characters are more readable
- // in the candidate window.
- const int kFontSizeDelta = 2; // Two size bigger.
- // Make the font bold, and change the size.
- if (orientation_ == InputMethodLookupTable::kVertical) {
- shortcut_label_->SetFont(
- shortcut_label_->font().DeriveFont(kFontSizeDelta, gfx::Font::BOLD));
- } else {
- shortcut_label_->SetFont(
- shortcut_label_->font().DeriveFont(kFontSizeDelta));
- }
- // TODO(satorux): Maybe we need to use language specific fonts for
- // candidate_label, like Chinese font for Chinese input method?
+ CreateWrappedShortcutLabel(shortcut_label_, orientation_);
+ candidate_label_ = CreateCandidateLabel(orientation_);
+ annotation_label_ = CreateAnnotationLabel(orientation_);
- // Add decoration based on the orientation.
- if (orientation_ == InputMethodLookupTable::kVertical) {
- // Set the background color.
- wrapped_shortcut_label->set_background(
- views::Background::CreateSolidBackground(
- kShortcutBackgroundColor));
- }
- shortcut_label_->SetColor(kShortcutColor);
+ // Initialize the column set with three columns.
+ views::ColumnSet* column_set = layout->AddColumnSet(0);
- // Create the candidate label. The label will be added to |this| as a
- // child view, hence it's deleted when |this| is deleted.
- if (orientation_ == InputMethodLookupTable::kVertical) {
- candidate_label_ = new VerticalCandidateLabel;
- } else {
- candidate_label_ = new views::Label;
- }
- // Change the font size.
- candidate_label_->SetFont(
- candidate_label_->font().DeriveFont(kFontSizeDelta));
+ // If orientation is vertical, each column width is fixed.
+ // Otherwise the width is resizable.
+ const views::GridLayout::SizeType column_type =
+ orientation_ == InputMethodLookupTable::kVertical ?
+ views::GridLayout::FIXED : views::GridLayout::USE_PREF;
- candidate_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ const int padding_column_width =
+ orientation_ == InputMethodLookupTable::kVertical ? 4 : 6;
- // Initialize the column set with two columns.
- views::ColumnSet* column_set = layout->AddColumnSet(0);
+ // Set shortcut column type and width.
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 0, views::GridLayout::USE_PREF, 0, 0);
- if (orientation_ == InputMethodLookupTable::kVertical) {
- column_set->AddPaddingColumn(0, 4);
- }
+ 0, column_type, shortcut_column_width, 0);
+ column_set->AddPaddingColumn(0, padding_column_width);
+
+ // Set candidate column type and width.
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
- 0, views::GridLayout::USE_PREF, 0, 0);
- if (orientation_ == InputMethodLookupTable::kVertical) {
- column_set->AddPaddingColumn(0, 4);
- } else {
- column_set->AddPaddingColumn(0, 6);
- }
+ 0, column_type, candidate_column_width, 0);
+ column_set->AddPaddingColumn(0, padding_column_width);
- // Add the shortcut label and the candidate label.
+ // Set annotation column type and width.
+ column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
+ 0, column_type, annotation_column_width, 0);
+ column_set->AddPaddingColumn(0, padding_column_width);
+
+ // Add the shortcut label, the candidate label, and annotation label.
layout->StartRow(0, 0);
- // |wrapped_shortcut_label| and |candidate_label_| will be owned by |this|.
+ // |wrapped_shortcut_label|, |candidate_label_|, and |annotation_label_|
+ // will be owned by |this|.
layout->AddView(wrapped_shortcut_label);
layout->AddView(candidate_label_);
+ layout->AddView(annotation_label_);
}
void CandidateView::SetCandidateText(const std::wstring& text) {
@@ -469,19 +652,8 @@ void CandidateView::SetShortcutText(const std::wstring& text) {
shortcut_label_->SetText(text);
}
-void CandidateView::SetShortcutTextFromInt(int index) {
- // Choose the character used for the shortcut label.
- const wchar_t kShortcutCharacters[] = L"1234567890ABCDEF";
- // The default character should not be used but just in case.
- wchar_t shortcut_character = L'?';
- if (index < static_cast<int>(arraysize(kShortcutCharacters) - 1)) {
- shortcut_character = kShortcutCharacters[index];
- }
- if (orientation_ == InputMethodLookupTable::kVertical) {
- shortcut_label_->SetText(StringPrintf(L"%lc", shortcut_character));
- } else {
- shortcut_label_->SetText(StringPrintf(L"%lc.", shortcut_character));
- }
+void CandidateView::SetAnnotationText(const std::wstring& text) {
+ annotation_label_->SetText(text);
}
void CandidateView::Select() {
@@ -539,7 +711,10 @@ CandidateWindowView::CandidateWindowView(
footer_area_(NULL),
header_area_(NULL),
header_label_(NULL),
- footer_label_(NULL) {
+ footer_label_(NULL),
+ previous_shortcut_column_width_(0),
+ previous_candidate_column_width_(0),
+ previous_annotation_column_width_(0) {
}
void CandidateWindowView::Init() {
@@ -613,8 +788,11 @@ void CandidateWindowView::UpdateAuxiliaryText(const std::string& utf8_text) {
void CandidateWindowView::UpdateCandidates(
const InputMethodLookupTable& lookup_table) {
// Initialize candidate views if necessary.
- MaybeInitializeCandidateViews(lookup_table.page_size,
- lookup_table.orientation);
+ MaybeInitializeCandidateViews(lookup_table);
+
+ // In MaybeInitializeCandidateViews(),
+ // |lookup_table| values and |lookup_table_| values are compared,
+ // so this substitution is needed after the function.
lookup_table_ = lookup_table;
// Compute the index of the current page.
@@ -642,16 +820,21 @@ void CandidateWindowView::UpdateCandidates(
// (ex. show 6, 7, 8, ... in empty rows when the number of
// candidates is 5). Second, we want to add a period after each
// shortcut label when the candidate window is horizontal.
- candidate_view->SetShortcutTextFromInt(i);
+ candidate_view->SetShortcutText(
+ CreateShortcutText(i, lookup_table_.orientation));
}
// Set the candidate text.
- if (candidate_index < lookup_table_.candidates.size()) {
+ if (candidate_index < lookup_table_.candidates.size() &&
+ candidate_index < lookup_table_.annotations.size()) {
candidate_view->SetCandidateText(
UTF8ToWide(lookup_table_.candidates[candidate_index]));
+ candidate_view->SetAnnotationText(
+ UTF8ToWide(lookup_table_.annotations[candidate_index]));
candidate_view->SetRowEnabled(true);
} else {
// Disable the empty row.
candidate_view->SetCandidateText(L"");
+ candidate_view->SetAnnotationText(L"");
candidate_view->SetRowEnabled(false);
}
}
@@ -663,15 +846,39 @@ void CandidateWindowView::UpdateCandidates(
}
void CandidateWindowView::MaybeInitializeCandidateViews(
- int num_views,
- InputMethodLookupTable::Orientation orientation) {
- // If the requested number of views matches the number of current views,
- // just reuse these.
- if (num_views == static_cast<int>(candidate_views_.size()) &&
- orientation == lookup_table_.orientation) {
+ const InputMethodLookupTable& lookup_table) {
+ const InputMethodLookupTable::Orientation orientation =
+ lookup_table.orientation;
+ const int page_size = lookup_table.page_size;
+
+ // Current column width.
+ int shortcut_column_width = 0;
+ int candidate_column_width = 0;
+ int annotation_column_width = 0;
+
+ // If orientation is horizontal, don't need to compute width,
+ // because each label is left aligned.
+ if (orientation == InputMethodLookupTable::kVertical) {
+ shortcut_column_width = ComputeShortcutColumnWidth(lookup_table);
+ candidate_column_width = ComputeCandidateColumnWidth(lookup_table);
+ annotation_column_width = ComputeAnnotationColumnWidth(lookup_table);
+ }
+
+ // If the requested number of views matches the number of current views, and
+ // previous and current column width are same, just reuse these.
+ if (static_cast<int>(candidate_views_.size()) == page_size &&
+ lookup_table_.orientation == orientation &&
+ previous_shortcut_column_width_ == shortcut_column_width &&
+ previous_candidate_column_width_ == candidate_column_width &&
+ previous_annotation_column_width_ == annotation_column_width) {
return;
}
+ // Update the previous column widths.
+ previous_shortcut_column_width_ = shortcut_column_width;
+ previous_candidate_column_width_ = candidate_column_width;
+ previous_annotation_column_width_ = annotation_column_width;
+
// Clear the existing candidate_views if any.
for (size_t i = 0; i < candidate_views_.size(); ++i) {
candidate_area_->RemoveChildView(candidate_views_[i]);
@@ -688,7 +895,7 @@ void CandidateWindowView::MaybeInitializeCandidateViews(
views::GridLayout::FILL,
0, views::GridLayout::USE_PREF, 0, 0);
} else {
- for (int i = 0; i < num_views; ++i) {
+ for (int i = 0; i < page_size; ++i) {
column_set->AddColumn(views::GridLayout::FILL,
views::GridLayout::FILL,
0, views::GridLayout::USE_PREF, 0, 0);
@@ -709,16 +916,27 @@ void CandidateWindowView::MaybeInitializeCandidateViews(
if (orientation == InputMethodLookupTable::kHorizontal) {
layout->StartRow(0, 0);
}
- for (int i = 0; i < num_views; ++i) {
+
+ for (int i = 0; i < page_size; ++i) {
CandidateView* candidate_row = new CandidateView(this, i, orientation);
- candidate_row->Init();
+ candidate_row->Init(shortcut_column_width,
+ candidate_column_width,
+ annotation_column_width);
candidate_views_.push_back(candidate_row);
if (orientation == InputMethodLookupTable::kVertical) {
layout->StartRow(0, 0);
}
- // |candidate_row| will be owned by candidate_area_|.
+ // |candidate_row| will be owned by |candidate_area_|.
layout->AddView(candidate_row);
}
+
+ // Compute views size in |layout|.
+ // If we don't call this function, GetHorizontalOffset() often
+ // returns invalid value (returns 0), then candidate window
+ // moves right from the correct position in MoveCandidateWindow().
+ // TODO(nhiroki): Figure out why it returns invalid value.
+ // It seems that the x-position of the candidate labels is not set.
+ layout->Layout(this);
}
views::View* CandidateWindowView::CreateHeaderArea() {
@@ -858,7 +1076,7 @@ int CandidateWindowView::GetHorizontalOffset() {
}
-void CandidateWindowController::Init() {
+bool CandidateWindowController::Init() {
// Initialize the input method UI status connection.
InputMethodUiStatusMonitorFunctions functions;
functions.hide_auxiliary_text =
@@ -872,11 +1090,17 @@ void CandidateWindowController::Init() {
functions.update_lookup_table =
&CandidateWindowController::OnUpdateLookupTable;
ui_status_connection_ = MonitorInputMethodUiStatus(functions, this);
- CHECK(ui_status_connection_)
- << "MonitorInputMethodUiStatus() failed.";
+ if (!ui_status_connection_) {
+ LOG(ERROR) << "MonitorInputMethodUiStatus() failed.";
+ return false;
+ }
+ MonitorInputMethodConnection(ui_status_connection_,
+ &CandidateWindowController::OnConnectionChange);
// Create the candidate window view.
CreateView();
+
+ return true;
}
void CandidateWindowController::CreateView() {
@@ -978,6 +1202,16 @@ void CandidateWindowController::OnSetCursorLocation(
CandidateWindowController* controller =
static_cast<CandidateWindowController*>(input_method_library);
+ // A workaround for http://crosbug.com/6460. We should ignore very short Y
+ // move to prevent the window from shaking up and down.
+ const int kKeepPositionThreshold = 2; // px
+ const gfx::Rect& last_location = controller->cursor_location();
+ const int delta_y = abs(last_location.y() - y);
+ if ((last_location.x() == x) && (delta_y <= kKeepPositionThreshold)) {
+ DLOG(INFO) << "Ignored set_cursor_location signal to prevent window shake";
+ return;
+ }
+
// Remember the cursor location.
controller->set_cursor_location(gfx::Rect(x, y, width, height));
// Move the window per the cursor location.
@@ -1032,6 +1266,15 @@ void CandidateWindowController::OnCandidateCommitted(int index,
NotifyCandidateClicked(ui_status_connection_, index, button, flags);
}
+void CandidateWindowController::OnConnectionChange(
+ void* input_method_library,
+ bool connected) {
+ if (!connected) {
+ MessageLoopForUI::current()->PostTask(FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+}
+
} // namespace chromeos
int main(int argc, char** argv) {
@@ -1045,30 +1288,26 @@ int main(int argc, char** argv) {
base::EnableTerminationOnHeapCorruption();
app::RegisterPathProvider();
CommandLine::Init(argc, argv);
- // TODO(markusheintz): The command line switch --Lang is now processed
- // by the CommandLinePrefStore and mapped to the preference
- // prefs::kApplicationLocale. This preferences can be read through the
- // PrefService. l10n_util::GetApplicationLocale() which is called by the
- // ResourceBundle code now ignores the --Lang flag.
- // In order to support the --Lang flag here the preference
- // prefs::kApplicationLocale must be read and passed instead of L"en-US".
- ResourceBundle::InitSharedInstance(L"en-US");
-
- // Write logs to a file for debugging, if --logtofile=FILE_NAME is given.
+
+ // Check if the UI language code is passed from the command line,
+ // otherwise, default to "en-US".
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- std::string log_file_name =
- command_line.GetSwitchValueASCII(switches::kChromeosLogToFile);
- if (!log_file_name.empty()) {
- logging::SetMinLogLevel(logging::LOG_INFO);
- logging::InitLogging(log_file_name.c_str(),
- logging::LOG_ONLY_TO_FILE,
- logging::DONT_LOCK_LOG_FILE,
- logging::DELETE_OLD_LOG_FILE);
- // Redirect stderr to log_file_name. This is neeed to capture the
- // logging from libcros.so.
- if (!freopen(log_file_name.c_str(), "a", stderr)) {
- LOG(INFO) << "Failed to redirect stderr to " << log_file_name.c_str();
- }
+ std::string ui_language_code =
+ command_line.GetSwitchValueASCII(switches::kCandidateWindowLang);
+ if (ui_language_code.empty()) {
+ ui_language_code = "en-US";
+ }
+ ResourceBundle::InitSharedInstance(ui_language_code);
+
+ // Change the UI font if needed.
+ const std::string font_name =
+ l10n_util::GetStringUTF8(IDS_UI_FONT_FAMILY_CROS);
+ // The font name should not be empty here, but just in case.
+ if (font_name != "default" && !font_name.empty()) {
+ // Don't use gtk_util::SetGtkFont() in chrome/browser/gtk not to
+ // introduce a dependency to it.
+ g_object_set(gtk_settings_get_default(),
+ "gtk-font-name", font_name.c_str(), NULL);
}
// Load libcros.
@@ -1083,7 +1322,9 @@ int main(int argc, char** argv) {
// Create the candidate window controller.
chromeos::CandidateWindowController controller;
- controller.Init();
+ if (!controller.Init()) {
+ return 1;
+ }
// Start the main loop.
views::AcceleratorHandler accelerator_handler;
diff --git a/chrome/browser/chromeos/input_method/candidate_window.gyp b/chrome/browser/chromeos/input_method/candidate_window.gyp
index e2f3ced..0d3b446 100644
--- a/chrome/browser/chromeos/input_method/candidate_window.gyp
+++ b/chrome/browser/chromeos/input_method/candidate_window.gyp
@@ -11,6 +11,7 @@
'target_name': 'candidate_window',
'type': 'executable',
'dependencies': [
+ '../../../../app/app.gyp:app_strings',
'../../../../base/base.gyp:base',
'../../../../build/linux/system.gyp:gtk',
'../../../../build/linux/system.gyp:x11',
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index abb94c2..3d981f1 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -8,12 +8,15 @@
#include <map>
#include <utility>
+#include "unicode/uloc.h"
+
#include "app/l10n_util.h"
#include "app/l10n_util_collator.h"
#include "base/basictypes.h"
#include "base/hash_tables.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
+#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
@@ -22,21 +25,17 @@
#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "grit/generated_resources.h"
-#include "third_party/icu/public/common/unicode/uloc.h"
namespace {
// Map from language code to associated input method IDs, etc.
typedef std::multimap<std::string, std::string> LanguageCodeToIdsMap;
struct IdMaps {
- LanguageCodeToIdsMap* language_code_to_ids;
- std::map<std::string, std::string>* id_to_language_code;
- std::map<std::string, std::string>* id_to_display_name;
+ scoped_ptr<LanguageCodeToIdsMap> language_code_to_ids;
+ scoped_ptr<std::map<std::string, std::string> > id_to_language_code;
+ scoped_ptr<std::map<std::string, std::string> > id_to_display_name;
- private:
- IdMaps() : language_code_to_ids(NULL),
- id_to_language_code(NULL),
- id_to_display_name(NULL) {
+ void ReloadMaps() {
chromeos::InputMethodLibrary* library =
chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
scoped_ptr<chromeos::InputMethodDescriptors> supported_input_methods(
@@ -46,9 +45,9 @@ struct IdMaps {
// TODO(yusukes): Handle this error in nicer way.
}
- language_code_to_ids = new LanguageCodeToIdsMap;
- id_to_language_code = new std::map<std::string, std::string>;
- id_to_display_name = new std::map<std::string, std::string>;
+ language_code_to_ids->clear();
+ id_to_language_code->clear();
+ id_to_display_name->clear();
// Build the id to descriptor map for handling kExtraLanguages later.
typedef std::map<std::string,
@@ -81,6 +80,13 @@ struct IdMaps {
}
}
+ private:
+ IdMaps() : language_code_to_ids(new LanguageCodeToIdsMap),
+ id_to_language_code(new std::map<std::string, std::string>),
+ id_to_display_name(new std::map<std::string, std::string>) {
+ ReloadMaps();
+ }
+
void AddInputMethodToMaps(
const std::string& language_code,
const chromeos::InputMethodDescriptor& input_method) {
@@ -153,10 +159,6 @@ const struct EnglishToResouceId {
IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VIQR_INPUT_METHOD },
{ "vni (m17n)",
IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VNI_INPUT_METHOD },
- { "latn-post (m17n)",
- IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_POST_INPUT_METHOD },
- { "latn-pre (m17n)",
- IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_PRE_INPUT_METHOD },
{ "Bopomofo", IDS_OPTIONS_SETTINGS_LANGUAGES_BOPOMOFO_INPUT_METHOD },
{ "Chewing", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_INPUT_METHOD },
{ "Pinyin", IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_INPUT_METHOD },
@@ -190,15 +192,20 @@ const struct EnglishToResouceId {
{ "USA - Dvorak", IDS_STATUSBAR_LAYOUT_USA_DVORAK },
{ "Romania", IDS_STATUSBAR_LAYOUT_ROMANIA },
{ "USA", IDS_STATUSBAR_LAYOUT_USA },
+ { "USA - International (AltGr dead keys)",
+ IDS_STATUSBAR_LAYOUT_USA_INTERNATIONAL },
{ "Lithuania", IDS_STATUSBAR_LAYOUT_LITHUANIA },
{ "United Kingdom - Extended - Winkeys",
IDS_STATUSBAR_LAYOUT_UNITED_KINGDOM },
{ "Slovakia", IDS_STATUSBAR_LAYOUT_SLOVAKIA },
{ "Russia", IDS_STATUSBAR_LAYOUT_RUSSIA },
+ { "Russia - Phonetic", IDS_STATUSBAR_LAYOUT_RUSSIA_PHONETIC },
{ "Greece", IDS_STATUSBAR_LAYOUT_GREECE },
{ "Belgium", IDS_STATUSBAR_LAYOUT_BELGIUM },
{ "Bulgaria", IDS_STATUSBAR_LAYOUT_BULGARIA },
+ { "Bulgaria - Traditional phonetic", IDS_STATUSBAR_LAYOUT_BULGARIA_PHONETIC },
{ "Switzerland", IDS_STATUSBAR_LAYOUT_SWITZERLAND },
+ { "Switzerland - French", IDS_STATUSBAR_LAYOUT_SWITZERLAND_FRENCH },
{ "Turkey", IDS_STATUSBAR_LAYOUT_TURKEY },
{ "Portugal", IDS_STATUSBAR_LAYOUT_PORTUGAL },
{ "Spain", IDS_STATUSBAR_LAYOUT_SPAIN },
@@ -211,6 +218,11 @@ const struct EnglishToResouceId {
{ "Sweden", IDS_STATUSBAR_LAYOUT_SWEDEN },
{ "Netherlands", IDS_STATUSBAR_LAYOUT_NETHERLANDS },
{ "Latvia", IDS_STATUSBAR_LAYOUT_LATVIA },
+ { "Canada", IDS_STATUSBAR_LAYOUT_CANADA },
+ { "Canada - English", IDS_STATUSBAR_LAYOUT_CANADA_ENGLISH },
+ { "Israel", IDS_STATUSBAR_LAYOUT_ISRAEL },
+ { "Korea, Republic of - 101/104 key Compatible",
+ IDS_STATUSBAR_LAYOUT_KOREA_104 },
};
const size_t kNumEntries = arraysize(kEnglishToResourceIdArray);
@@ -231,20 +243,6 @@ const char* kIso639VariantMapping[][2] = {
{"slo", "slk"},
};
-// The list defines pairs of language code and the default input method
-// id. The list is used for reordering input method ids.
-//
-// TODO(satorux): We may need to handle secondary, and ternary input
-// methods, rather than handling the default input method only.
-const struct LanguageDefaultInputMethodId {
- const char* language_code;
- const char* input_method_id;
-} kLanguageDefaultInputMethodIds[] = {
- { "en-US", "xkb:us::eng", }, // US - English
- { "fr", "xkb:fr::fra", }, // France - French
- { "de", "xkb:de::ger", }, // Germany - German
-};
-
// The comparator is used for sorting language codes by their
// corresponding language names, using the ICU collator.
struct CompareLanguageCodesByLanguageName
@@ -264,6 +262,7 @@ struct CompareLanguageCodesByLanguageName
return l10n_util::StringComparator<std::wstring>(collator_)(key1, key2);
}
+ private:
icu::Collator* collator_;
};
@@ -293,6 +292,7 @@ struct CompareInputMethodIdsByLanguageName
return comparator_(language_code_1, language_code_2);
}
+ private:
const CompareLanguageCodesByLanguageName comparator_;
const std::map<std::string, std::string>& id_to_language_code_map_;
};
@@ -444,16 +444,6 @@ std::string GetLanguageCodeFromDescriptor(
return language_code;
}
-std::wstring MaybeRewriteLanguageName(const std::wstring& language_name) {
- // "t" is used as the language code for input methods that don't fall
- // under any other languages.
- if (language_name == L"t") {
- return l10n_util::GetString(
- IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS);
- }
- return language_name;
-}
-
std::string GetLanguageCodeFromInputMethodId(
const std::string& input_method_id) {
// The code should be compatible with one of codes used for UI languages,
@@ -490,10 +480,14 @@ std::wstring GetLanguageDisplayNameFromCode(const std::string& language_code) {
if (!g_browser_process) {
return L"";
}
- return MaybeRewriteLanguageName(UTF16ToWide(
- l10n_util::GetDisplayNameForLocale(
- language_code, g_browser_process->GetApplicationLocale(),
- true)));
+ return UTF16ToWide(l10n_util::GetDisplayNameForLocale(
+ language_code, g_browser_process->GetApplicationLocale(), true));
+}
+
+std::wstring GetLanguageNativeDisplayNameFromCode(
+ const std::string& language_code) {
+ return UTF16ToWide(l10n_util::GetDisplayNameForLocale(
+ language_code, language_code, true));
}
void SortLanguageCodesByNames(std::vector<std::string>* language_codes) {
@@ -536,24 +530,6 @@ void SortInputMethodIdsByNamesInternal(
collator.get(), id_to_language_code_map));
}
-void ReorderInputMethodIdsForLanguageCode(
- const std::string& language_code,
- std::vector<std::string>* input_method_ids) {
- for (size_t i = 0; i < arraysize(kLanguageDefaultInputMethodIds); ++i) {
- if (language_code == kLanguageDefaultInputMethodIds[i].language_code) {
- std::vector<std::string>::iterator iter =
- std::find(input_method_ids->begin(), input_method_ids->end(),
- kLanguageDefaultInputMethodIds[i].input_method_id);
- // If it's not on the top of |input_method_id|, swap it with the top one.
- if (iter != input_method_ids->end() &&
- iter != input_method_ids->begin()) {
- std::swap(*input_method_ids->begin(), *iter);
- }
- break; // Don't have to check other language codes.
- }
- }
-}
-
bool GetInputMethodIdsFromLanguageCode(
const std::string& normalized_language_code,
InputMethodType type,
@@ -594,9 +570,11 @@ void EnableInputMethods(const std::string& language_code, InputMethodType type,
std::vector<std::string> input_method_ids;
GetInputMethodIdsFromLanguageCode(language_code, type, &input_method_ids);
+ std::string keyboard = CrosLibrary::Get()->GetKeyboardLibrary()->
+ GetHardwareKeyboardLayoutName();
if (std::count(input_method_ids.begin(), input_method_ids.end(),
- kHardwareKeyboardLayout) == 0) {
- input_method_ids.push_back(kHardwareKeyboardLayout);
+ keyboard) == 0) {
+ input_method_ids.push_back(keyboard);
}
// First, sort the vector by input method id, then by its display name.
std::sort(input_method_ids.begin(), input_method_ids.end());
@@ -607,11 +585,16 @@ void EnableInputMethods(const std::string& language_code, InputMethodType type,
value.type = ImeConfigValue::kValueTypeStringList;
value.string_list_value = input_method_ids;
InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
- library->SetImeConfig(kGeneralSectionName, kPreloadEnginesConfigName, value);
+ library->SetImeConfig(language_prefs::kGeneralSectionName,
+ language_prefs::kPreloadEnginesConfigName, value);
if (!initial_input_method_id.empty()) {
library->ChangeInputMethod(initial_input_method_id);
}
}
+void OnLocaleChanged() {
+ Singleton<IdMaps>::get()->ReloadMaps();
+}
+
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_util.h b/chrome/browser/chromeos/input_method/input_method_util.h
index 72d86ea..f97a792 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.h
+++ b/chrome/browser/chromeos/input_method/input_method_util.h
@@ -4,7 +4,9 @@
#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_
#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_
+#pragma once
+#include <map>
#include <string>
#include <vector>
@@ -14,8 +16,8 @@
namespace chromeos {
namespace input_method {
-// The list of language that do not have associated input methods. For
-// these languages, we associate input methods here.
+// The list of language that do not have associated input methods in IBus.
+// For these languages, we associate input methods here.
const struct ExtraLanguage {
const char* language_code;
const char* input_method_id;
@@ -74,12 +76,6 @@ std::string GetLanguageCodeFromDescriptor(
// "pinyin" => ""
std::string GetKeyboardLayoutName(const std::string& input_method_id);
-// Rewrites the language name and returns the modified version if
-// necessary. Otherwise, returns the given language name as is.
-// In particular, this rewrites the special language name used for input
-// methods that don't fall under any other languages.
-std::wstring MaybeRewriteLanguageName(const std::wstring& language_name);
-
// Converts an input method ID to a language code of the IME. Returns "Eng"
// when |input_method_id| is unknown.
// Example: "hangul" => "ko"
@@ -95,10 +91,17 @@ std::string GetInputMethodDisplayNameFromId(const std::string& input_method_id);
// Converts a language code to a language display name, using the
// current application locale. MaybeRewriteLanguageName() is called
// internally.
-// Examples: "fr" => "French"
+// Examples: "fi" => "Finnish"
// "en-US" => "English (United States)"
std::wstring GetLanguageDisplayNameFromCode(const std::string& language_code);
+// Converts a language code to a language native display name.
+// MaybeRewriteLanguageName() is called internally.
+// Examples: "fi" => "suomi" (rather than Finnish)
+// "en-US" => "English (United States)"
+std::wstring GetLanguageNativeDisplayNameFromCode(
+ const std::string& language_code);
+
// Sorts the given language codes by their corresponding language names,
// using the unicode string comparator. Uses unstable sorting.
void SortLanguageCodesByNames(std::vector<std::string>* language_codes);
@@ -107,15 +110,6 @@ void SortLanguageCodesByNames(std::vector<std::string>* language_codes);
// using the unicode string comparator. Uses stable sorting.
void SortInputMethodIdsByNames(std::vector<std::string>* input_method_ids);
-// Reorders the given input method ids for the language code. For
-// example, if |language_codes| is "fr" and |input_method_ids| contains
-// ["xkb:be::fra", and "xkb:fr::fra"], the list is reordered to
-// ["xkb:fr::fra", and "xkb:be::fra"], so that French keyboard layout
-// comes before Belgian keyboard layout.
-void ReorderInputMethodIdsForLanguageCode(
- const std::string& language_code,
- std::vector<std::string>* input_method_ids);
-
enum InputMethodType {
kKeyboardLayoutsOnly,
kAllInputMethods,
@@ -156,6 +150,8 @@ bool GetInputMethodIdsFromLanguageCodeInternal(
InputMethodType type,
std::vector<std::string>* out_input_method_ids);
+void OnLocaleChanged();
+
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
index b4a3c95..f228d11 100644
--- a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
@@ -34,6 +34,9 @@ TEST(InputMethodUtilTest, NormalizeLanguageCode) {
// TODO(yusukes): test all language codes that IBus provides.
EXPECT_EQ("ja", NormalizeLanguageCode("ja"));
EXPECT_EQ("ja", NormalizeLanguageCode("jpn"));
+ // In the past "t" had a meaning of "other language" for some m17n latin
+ // input methods for testing purpose, but it is no longer used. We test "t"
+ // here as just an "unknown" language.
EXPECT_EQ("t", NormalizeLanguageCode("t"));
EXPECT_EQ("zh-CN", NormalizeLanguageCode("zh-CN"));
EXPECT_EQ("zh-CN", NormalizeLanguageCode("zh_CN"));
@@ -74,12 +77,6 @@ TEST(InputMethodUtilTest, GetLanguageCodeFromDescriptor) {
InputMethodDescriptor("xkb:uk::eng", "United Kingdom", "us", "eng")));
}
-TEST(InputMethodUtilTest, MaybeRewriteLanguageName) {
- EXPECT_EQ(L"English", MaybeRewriteLanguageName(L"English"));
- EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS),
- MaybeRewriteLanguageName(L"t"));
-}
-
TEST(InputMethodUtilTest, GetKeyboardLayoutName) {
// Unsupported cases
EXPECT_EQ("", GetKeyboardLayoutName("UNSUPPORTED_ID"));
@@ -88,8 +85,6 @@ TEST(InputMethodUtilTest, GetKeyboardLayoutName) {
EXPECT_EQ("", GetKeyboardLayoutName("mozc"));
EXPECT_EQ("", GetKeyboardLayoutName("mozc-jp"));
EXPECT_EQ("", GetKeyboardLayoutName("pinyin"));
- EXPECT_EQ("", GetKeyboardLayoutName("m17n:t:latn-pre"));
- EXPECT_EQ("", GetKeyboardLayoutName("m17n:t:latn-post"));
EXPECT_EQ("", GetKeyboardLayoutName("m17n:ar:kbd"));
EXPECT_EQ("", GetKeyboardLayoutName("m17n:he:kbd"));
EXPECT_EQ("", GetKeyboardLayoutName("m17n:hi:itrans"));
@@ -142,10 +137,11 @@ TEST(InputMethodUtilTest, GetKeyboardLayoutName) {
}
TEST(InputMethodUtilTest, GetLanguageDisplayNameFromCode) {
- EXPECT_EQ(L"French", GetLanguageDisplayNameFromCode("fr"));
- // MaybeRewriteLanguageName() should be applied.
- EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS),
- GetLanguageDisplayNameFromCode("t"));
+ EXPECT_EQ(L"Finnish", GetLanguageDisplayNameFromCode("fi"));
+}
+
+TEST(InputMethodUtilTest, GetLanguageNativeDisplayNameFromCode) {
+ EXPECT_EQ(L"suomi", GetLanguageNativeDisplayNameFromCode("fi"));
}
TEST(InputMethodUtilTest, SortLanguageCodesByNames) {
@@ -155,6 +151,7 @@ TEST(InputMethodUtilTest, SortLanguageCodesByNames) {
language_codes.push_back("ja");
language_codes.push_back("fr");
+ // For "t", see the comment in NormalizeLanguageCode test.
language_codes.push_back("t");
SortLanguageCodesByNames(&language_codes);
ASSERT_EQ(3U, language_codes.size());
@@ -178,7 +175,6 @@ TEST(LanguageConfigModelTest, SortInputMethodIdsByNamesInternal) {
id_to_language_code_map.insert(std::make_pair("mozc-jp", "ja"));
id_to_language_code_map.insert(std::make_pair("xkb:jp::jpn", "ja"));
id_to_language_code_map.insert(std::make_pair("xkb:fr::fra", "fr"));
- id_to_language_code_map.insert(std::make_pair("m17n:latn-pre", "t"));
std::vector<std::string> input_method_ids;
// Check if this function can handle an empty list.
@@ -187,87 +183,30 @@ TEST(LanguageConfigModelTest, SortInputMethodIdsByNamesInternal) {
input_method_ids.push_back("mozc"); // Japanese
input_method_ids.push_back("xkb:fr::fra"); // French
- input_method_ids.push_back("m17n:latn-pre"); // Others
SortInputMethodIdsByNamesInternal(id_to_language_code_map,
&input_method_ids);
- ASSERT_EQ(3U, input_method_ids.size());
+ ASSERT_EQ(2U, input_method_ids.size());
ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French
ASSERT_EQ("mozc", input_method_ids[1]); // Japanese
- ASSERT_EQ("m17n:latn-pre", input_method_ids[2]); // Others
// Add a duplicate entry and see if it works.
// Note that SortInputMethodIdsByNamesInternal uses std::stable_sort.
input_method_ids.push_back("xkb:jp::jpn"); // also Japanese
SortInputMethodIdsByNamesInternal(id_to_language_code_map,
&input_method_ids);
- ASSERT_EQ(4U, input_method_ids.size());
+ ASSERT_EQ(3U, input_method_ids.size());
ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French
ASSERT_EQ("mozc", input_method_ids[1]); // Japanese
ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese
- ASSERT_EQ("m17n:latn-pre", input_method_ids[3]); // Others
input_method_ids.push_back("mozc-jp"); // also Japanese
SortInputMethodIdsByNamesInternal(id_to_language_code_map,
&input_method_ids);
- ASSERT_EQ(5U, input_method_ids.size());
+ ASSERT_EQ(4U, input_method_ids.size());
ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French
ASSERT_EQ("mozc", input_method_ids[1]); // Japanese
ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese
ASSERT_EQ("mozc-jp", input_method_ids[3]); // Japanese
- ASSERT_EQ("m17n:latn-pre", input_method_ids[4]); // Others
-}
-
-TEST(InputMethodUtilTest, ReorderInputMethodIdsForLanguageCode_DE) {
- std::vector<std::string> input_method_ids;
- input_method_ids.push_back("xkb:ch::ger"); // Switzerland - German
- input_method_ids.push_back("xkb:de::ger"); // Germany - German
- ReorderInputMethodIdsForLanguageCode("de", &input_method_ids);
- // The list should be reordered.
- ASSERT_EQ(2U, input_method_ids.size());
- EXPECT_EQ("xkb:de::ger", input_method_ids[0]);
- EXPECT_EQ("xkb:ch::ger", input_method_ids[1]);
-}
-
-TEST(InputMethodUtilTest, ReorderInputMethodIdsForLanguageCode_FR) {
- std::vector<std::string> input_method_ids;
- input_method_ids.push_back("xkb:be::fra"); // Belgium - French
- input_method_ids.push_back("xkb:fr::fra"); // France - French
- ReorderInputMethodIdsForLanguageCode("fr", &input_method_ids);
- // The list should be reordered.
- ASSERT_EQ(2U, input_method_ids.size());
- EXPECT_EQ("xkb:fr::fra", input_method_ids[0]);
- EXPECT_EQ("xkb:be::fra", input_method_ids[1]);
-}
-
-TEST(InputMethodUtilTest, ReorderInputMethodIdsForLanguageCode_EN_US) {
- std::vector<std::string> input_method_ids;
- input_method_ids.push_back("xkb:us:dvorak:eng"); // US - Dvorak - English
- input_method_ids.push_back("xkb:us::eng"); // US - English
- ReorderInputMethodIdsForLanguageCode("en-US", &input_method_ids);
- // The list should be reordered.
- ASSERT_EQ(2U, input_method_ids.size());
- EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
- EXPECT_EQ("xkb:us:dvorak:eng", input_method_ids[1]);
-}
-
-TEST(InputMethodUtilTest, ReorderInputMethodIdsForLanguageCode_FI) {
- std::vector<std::string> input_method_ids;
- input_method_ids.push_back("xkb:fi::fin"); // Finland - Finnish
- ReorderInputMethodIdsForLanguageCode("fi", &input_method_ids);
- // There is no rule for reordering for Finnish.
- ASSERT_EQ(1U, input_method_ids.size());
- EXPECT_EQ("xkb:fi::fin", input_method_ids[0]);
-}
-
-TEST(InputMethodUtilTest, ReorderInputMethodIdsForLanguageCode_Noop) {
- std::vector<std::string> input_method_ids;
- input_method_ids.push_back("xkb:fr::fra"); // France - French
- input_method_ids.push_back("xkb:be::fra"); // Belgium - French
- // If the list is already sorted, nothing should happen.
- ReorderInputMethodIdsForLanguageCode("fr", &input_method_ids);
- ASSERT_EQ(2U, input_method_ids.size());
- EXPECT_EQ("xkb:fr::fra", input_method_ids[0]);
- EXPECT_EQ("xkb:be::fra", input_method_ids[1]);
}
TEST(LanguageConfigModelTest, GetInputMethodIdsForLanguageCode) {
diff --git a/chrome/browser/chromeos/language_preferences.h b/chrome/browser/chromeos/language_preferences.h
index 34ab1ec..2dfb95e 100644
--- a/chrome/browser/chromeos/language_preferences.h
+++ b/chrome/browser/chromeos/language_preferences.h
@@ -4,17 +4,20 @@
#ifndef CHROME_BROWSER_CHROMEOS_LANGUAGE_PREFERENCES_H_
#define CHROME_BROWSER_CHROMEOS_LANGUAGE_PREFERENCES_H_
+#pragma once
-#include "base/basictypes.h"
-#include "chrome/common/pref_names.h"
-#include "grit/generated_resources.h"
+#include <stddef.h> // For size_t
-// Section and config names for the IBus configuration daemon.
+// This file defines types and declare variables used in "Languages and
+// Input" settings in Chromium OS.
namespace chromeos {
+namespace language_prefs {
+// The struct is used for preferences consisting of multiple choices, like
+// punctuation types used in Japanese input method.
template <typename DataType>
struct LanguageMultipleChoicePreference {
- const wchar_t* pref_name; // Chrome preference name.
+ const char* pref_name; // Chrome preference name.
DataType default_pref_value;
const char* ibus_config_name;
// Currently we have 10 combobox items at most.
@@ -26,15 +29,19 @@ struct LanguageMultipleChoicePreference {
int label_message_id; // Resource grd ID for the label.
};
+// The struct is used for preferences of boolean values, like switches to
+// enable or disable particular features.
struct LanguageBooleanPrefs {
- const wchar_t* pref_name; // Chrome preference name.
+ const char* pref_name; // Chrome preference name.
bool default_pref_value;
const char* ibus_config_name;
int message_id;
};
+// The struct is used for preferences of integer range values, like the
+// key repeat rate.
struct LanguageIntegerRangePreference {
- const wchar_t* pref_name; // Chrome preference name.
+ const char* pref_name; // Chrome preference name.
int default_pref_value;
int min_pref_value;
int max_pref_value;
@@ -42,371 +49,121 @@ struct LanguageIntegerRangePreference {
int message_id;
};
+// ---------------------------------------------------------------------------
// For ibus-daemon
-const char kGeneralSectionName[] = "general";
-const char kHotKeySectionName[] = "general/hotkey";
-const char kPreloadEnginesConfigName[] = "preload_engines";
-const char kNextEngineInMenuConfigName[] = "next_engine_in_menu";
-const char kPreviousEngineConfigName[] = "previous_engine";
-
-// TODO(yusukes): Check if the "Kana/Eisu" key in the Japanese keyboard for
-// Chrome OS actually generates Zenkaku_Hankaku when the keyboard gets ready.
-
-// ibus-daemon accepts up to 5 next-engine hot-keys.
-const char kHotkeyNextEngineInMenu[] =
- "Shift+Alt+Release+Shift_L,Shift+Alt+Release+Meta_L,Control+Shift+space,"
- "Zenkaku_Hankaku";
-// TODO(suzhe): Add more key bindings?
-const char kHotkeyPreviousEngine[] = "Control+space";
-
-// For Simplified Chinese input method (ibus-chewing)
-const char kChewingSectionName[] = "engine/Chewing";
-
-// We have to sync the |ibus_config_name|s with those in
-// ibus-chewing/files/src/Config.cc.
-const LanguageBooleanPrefs kChewingBooleanPrefs[] = {
- { prefs::kLanguageChewingAutoShiftCur, false, "autoShiftCur",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_AUTO_SHIFT_CUR},
- { prefs::kLanguageChewingAddPhraseDirection, false, "addPhraseDirection",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_ADD_PHRASE_DIRECTION},
- { prefs::kLanguageChewingEasySymbolInput, true, "easySymbolInput",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_EASY_SYMBOL_INPUT},
- { prefs::kLanguageChewingEscCleanAllBuf, false, "escCleanAllBuf",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_ESC_CLEAN_ALL_BUF},
- { prefs::kLanguageChewingForceLowercaseEnglish, false,
- "forceLowercaseEnglish",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_FORCE_LOWER_CASE_ENGLISH},
- { prefs::kLanguageChewingPlainZhuyin, false, "plainZhuyin",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_PLAIN_ZHUYIN},
- { prefs::kLanguageChewingPhraseChoiceRearward, true, "phraseChoiceRearward",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_PHRASE_CHOICE_REARWARD},
- { prefs::kLanguageChewingSpaceAsSelection, true, "spaceAsSelection",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_SPACE_AS_SELECTION},
-};
-const size_t kNumChewingBooleanPrefs = ARRAYSIZE_UNSAFE(kChewingBooleanPrefs);
-
-const LanguageIntegerRangePreference kChewingIntegerPrefs[] = {
- { prefs::kLanguageChewingMaxChiSymbolLen, 20, 8, 40, "maxChiSymbolLen",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_MAX_CHI_SYMBOL_LEN},
- { prefs::kLanguageChewingCandPerPage, 10, 8, 10, "candPerPage",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTING_CAND_PER_PAGE},
-};
-const size_t kNumChewingIntegerPrefs = ARRAYSIZE_UNSAFE(kChewingIntegerPrefs);
-
-const LanguageMultipleChoicePreference<const char*>
- kChewingMultipleChoicePrefs[] = {
- { prefs::kLanguageChewingKeyboardType,
- "default",
- "KBType",
- {{ "default",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_DEFAULT },
- { "hsu", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_HSU },
- { "ibm", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_IBM },
- { "gin_yieh",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_GIN_YIEH },
- { "eten", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_ETEN },
- { "eten26", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_ETEN26 },
- { "dvorak", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_DVORAK },
- { "dvorak_hsu",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_DVORAK_HSU },
- { "dachen_26",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_DACHEN_26 },
- { "hanyu", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE_HANYU }},
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_KEYBOARD_TYPE,
- },
- { prefs::kLanguageChewingSelKeys,
- "1234567890",
- "selKeys",
- {{ "1234567890",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_1234567890 },
- { "asdfghjkl;",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_ASDFGHJKLS },
- { "asdfzxcv89",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_ASDFZXCV89 },
- { "asdfjkl789",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_ASDFJKL789 },
- { "aoeu;qjkix",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_AOEUSQJKIX },
- { "aoeuhtnsid",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_AOEUHTNSID },
- { "aoeuidhtns",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_AOEUIDHTNS },
- { "1234qweras",
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS_1234QWERAS }},
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SEL_KEYS,
- },
-};
-const size_t kNumChewingMultipleChoicePrefs =
- arraysize(kChewingMultipleChoicePrefs);
-
-const LanguageMultipleChoicePreference<int> kChewingHsuSelKeyType = {
- prefs::kLanguageChewingHsuSelKeyType,
- 1,
- "hsuSelKeyType",
- {{ 1, IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_HSU_SEL_KEY_TYPE_1 },
- { 2, IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_HSU_SEL_KEY_TYPE_2 }},
- IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_HSU_SEL_KEY_TYPE,
-};
-
+// ---------------------------------------------------------------------------
+extern const char kGeneralSectionName[];
+extern const char kHotKeySectionName[];
+extern const char kPreloadEnginesConfigName[];
+extern const char kNextEngineInMenuConfigName[];
+extern const char kPreviousEngineConfigName[];
+extern const char kHotkeyNextEngineInMenu[];
+extern const char kHotkeyPreviousEngine[];
+
+// ---------------------------------------------------------------------------
+// For Traditional Chinese input method (ibus-chewing)
+// ---------------------------------------------------------------------------
+extern const char kChewingSectionName[];
+
+extern const LanguageBooleanPrefs kChewingBooleanPrefs[];
+// This is not ideal, but we should hard-code the number here as the value
+// is referenced in other header files as array sizes. We have a
+// COMPILE_ASSERT in .cc to ensure that the number is correct.
+const size_t kNumChewingBooleanPrefs = 8;
+
+extern const LanguageIntegerRangePreference kChewingIntegerPrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumChewingIntegerPrefs = 2;
+const int kChewingMaxChiSymbolLenIndex = 0;
+const int kChewingCandPerPageIndex = 1;
+
+extern const LanguageMultipleChoicePreference<const char*>
+ kChewingMultipleChoicePrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumChewingMultipleChoicePrefs = 2;
+
+extern const LanguageMultipleChoicePreference<int> kChewingHsuSelKeyType;
+
+// ---------------------------------------------------------------------------
// For Korean input method (ibus-hangul)
-const char kHangulSectionName[] = "engine/Hangul";
-const char kHangulKeyboardConfigName[] = "HangulKeyboard";
-const char kHangulHanjaKeysConfigName[] = "HanjaKeys";
-// We add Control+Alt+9 in addition to the two default keys since Hanja key
-// might not be available on the Chrome OS keyboard and F9 key is reserved by
-// the window manager.
-// TODO: Hanja keys are not configurable yet (and we're not sure if it should.)
-const char kHangulHanjaKeys[] = "F9,Hangul_Hanja,Control+Alt+9";
+// ---------------------------------------------------------------------------
+extern const char kHangulSectionName[];
+extern const char kHangulKeyboardConfigName[];
+extern const char kHangulHanjaKeysConfigName[];
+extern const char kHangulHanjaKeys[];
-const struct HangulKeyboardNameIDPair {
+struct HangulKeyboardNameIDPair {
int message_id;
const char* keyboard_id;
-} kHangulKeyboardNameIDPairs[] = {
- // We have to sync the |keyboard_id|s with those in
- // ibus-hangul/files/setup/main.py.
- { IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_KEYBOARD_2_SET, "2" },
- { IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_KEYBOARD_3_SET_FINAL,
- "3f" },
- { IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_KEYBOARD_3_SET_390, "39" },
- { IDS_OPTIONS_SETTINGS_LANGUAGES_HANGUL_SETTINGS_KEYBOARD_3_SET_NO_SHIFT,
- "3s" },
- // We don't support "Sebeolsik 2 set" keyboard.
};
+extern const HangulKeyboardNameIDPair kHangulKeyboardNameIDPairs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumHangulKeyboardNameIDPairs = 4;
+
+// ---------------------------------------------------------------------------
// For Simplified Chinese input method (ibus-pinyin)
-const char kPinyinSectionName[] = "engine/Pinyin";
+// ---------------------------------------------------------------------------
+extern const char kPinyinSectionName[];
-// We have to sync the |ibus_config_name|s with those in
-// ibus-pinyin/files/src/Config.cc.
-const LanguageBooleanPrefs kPinyinBooleanPrefs[] = {
- { prefs::kLanguagePinyinCorrectPinyin, true, "CorrectPinyin",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_CORRECT_PINYIN },
- { prefs::kLanguagePinyinFuzzyPinyin, false, "FuzzyPinyin",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_FUZZY_PINYIN },
- { prefs::kLanguagePinyinShiftSelectCandidate, false, "ShiftSelectCandidate",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_SHIFT_SELECT_PINYIN },
- { prefs::kLanguagePinyinMinusEqualPage, true, "MinusEqualPage",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_MINUS_EQUAL_PAGE },
- { prefs::kLanguagePinyinCommaPeriodPage, true, "CommaPeriodPage",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_COMMA_PERIOD_PAGE },
- { prefs::kLanguagePinyinAutoCommit, false, "AutoCommit",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_AUTO_COMMIT },
- { prefs::kLanguagePinyinDoublePinyin, false, "DoublePinyin",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_DOUBLE_PINYIN },
- { prefs::kLanguagePinyinInitChinese, true, "InitChinese",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_INIT_CHINESE },
- { prefs::kLanguagePinyinInitFull, false, "InitFull",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_INIT_FULL },
- { prefs::kLanguagePinyinInitFullPunct, true, "InitFullPunct",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_INIT_FULL_PUNCT },
- { prefs::kLanguagePinyinInitSimplifiedChinese, true, "InitSimplifiedChinese",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_INIT_SIMPLIFIED_CHINESE },
- { prefs::kLanguagePinyinTradCandidate, false, "TradCandidate",
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_SETTING_TRAD_CANDIDATE },
- // TODO(yusukes): Support PINYIN_{INCOMPLETE,CORRECT,FUZZY}_... prefs (32
- // additional boolean prefs.)
-};
-const size_t kNumPinyinBooleanPrefs = ARRAYSIZE_UNSAFE(kPinyinBooleanPrefs);
-// TODO(yusukes): Support HalfWidthPuncts and IncompletePinyin prefs if needed.
+extern const LanguageBooleanPrefs kPinyinBooleanPrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumPinyinBooleanPrefs = 11;
-const LanguageMultipleChoicePreference<int> kPinyinDoublePinyinSchema = {
- prefs::kLanguagePinyinDoublePinyinSchema,
- 0,
- "DoublePinyinSchema",
- {{ 0, IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA_MSPY},
- { 1, IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA_ZRM},
- { 2, IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA_ABC},
- { 3, IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA_ZGPY},
- { 4, IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA_PYJJ}},
- IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_DOUBLE_SCHEMA,
-};
+extern const LanguageMultipleChoicePreference<int> kPinyinDoublePinyinSchema;
-const struct {
- const wchar_t* pref_name; // Chrome preference name.
+struct PinyinIntegerPref {
+ const char* pref_name; // Chrome preference name.
int default_pref_value;
const char* ibus_config_name;
// TODO(yusukes): Add message_id if needed.
-} kPinyinIntegerPrefs[] = {
- // TODO(yusukes): the type of lookup_table_page_size on ibus should be uint.
- { prefs::kLanguagePinyinLookupTablePageSize, 5, "LookupTablePageSize" },
-};
-const size_t kNumPinyinIntegerPrefs = ARRAYSIZE_UNSAFE(kPinyinIntegerPrefs);
-
-// For Japanese input method (ibus-mozc)
-const char kMozcSectionName[] = "engine/Mozc";
-
-#define IDS_MOZC(suffix) \
- IDS_OPTIONS_SETTINGS_LANGUAGES_MOZC_##suffix
-
-const LanguageBooleanPrefs kMozcBooleanPrefs[] = {
- { prefs::kLanguageMozcIncognitoMode,
- false,
- "incognito_mode",
- IDS_MOZC(INCOGNITO_MODE)
- },
- { prefs::kLanguageMozcUseAutoImeTurnOff,
- true,
- "use_auto_ime_turn_off",
- IDS_MOZC(USE_AUTO_IME_TURN_OFF)
- },
- { prefs::kLanguageMozcUseDateConversion,
- true,
- "use_date_conversion",
- IDS_MOZC(USE_DATE_CONVERSION)
- },
- { prefs::kLanguageMozcUseSingleKanjiConversion,
- true,
- "use_single_kanji_conversion",
- IDS_MOZC(USE_SINGLE_KANJI_CONVERSION)
- },
- { prefs::kLanguageMozcUseSymbolConversion,
- true,
- "use_symbol_conversion",
- IDS_MOZC(USE_SYMBOL_CONVERSION)
- },
- { prefs::kLanguageMozcUseNumberConversion,
- true,
- "use_number_conversion",
- IDS_MOZC(USE_NUMBER_CONVERSION)
- },
- { prefs::kLanguageMozcUseHistorySuggest,
- true,
- "use_history_suggest",
- IDS_MOZC(USE_HISTORY_SUGGEST)
- },
- { prefs::kLanguageMozcUseDictionarySuggest,
- true,
- "use_dictionary_suggest",
- IDS_MOZC(USE_DICTIONARY_SUGGEST)
- },
};
-const size_t kNumMozcBooleanPrefs = ARRAYSIZE_UNSAFE(kMozcBooleanPrefs);
-const LanguageMultipleChoicePreference<const char*>
- kMozcMultipleChoicePrefs[] = {
- { prefs::kLanguageMozcPreeditMethod,
- "ROMAN",
- "preedit_method",
- {{ "ROMAN", IDS_MOZC(PREEDIT_METHOD_ROMAN) },
- { "KANA", IDS_MOZC(PREEDIT_METHOD_KANA) }},
- IDS_MOZC(PREEDIT_METHOD),
- },
- { prefs::kLanguageMozcSessionKeymap,
- "MSIME",
- "session_keymap",
- {{ "ATOK", IDS_MOZC(SESSION_KEYMAP_ATOK) },
- { "MSIME", IDS_MOZC(SESSION_KEYMAP_MSIME) },
- { "KOTOERI", IDS_MOZC(SESSION_KEYMAP_KOTOERI) }},
- // TODO: Support "CUSTOM" keymap.
- IDS_MOZC(SESSION_KEYMAP),
- },
- { prefs::kLanguageMozcPunctuationMethod,
- "KUTEN_TOUTEN",
- "punctuation_method",
- {{ "KUTEN_TOUTEN",
- IDS_MOZC(PUNCTUATION_METHOD_KUTEN_TOUTEN) },
- { "COMMA_PERIOD",
- IDS_MOZC(PUNCTUATION_METHOD_COMMA_PERIOD) },
- { "KUTEN_PERIOD",
- IDS_MOZC(PUNCTUATION_METHOD_KUTEN_PERIOD) },
- { "COMMA_TOUTEN",
- IDS_MOZC(PUNCTUATION_METHOD_COMMA_TOUTEN) }},
- IDS_MOZC(PUNCTUATION_METHOD),
- },
- { prefs::kLanguageMozcSymbolMethod,
- "CORNER_BRACKET_MIDDLE_DOT",
- "symbol_method",
- {{ "CORNER_BRACKET_MIDDLE_DOT",
- IDS_MOZC(SYMBOL_METHOD_CORNER_BRACKET_MIDDLE_DOT) },
- { "SQUARE_BRACKET_SLASH",
- IDS_MOZC(SYMBOL_METHOD_SQUARE_BRACKET_SLASH) },
- { "CORNER_BRACKET_SLASH",
- IDS_MOZC(SYMBOL_METHOD_CORNER_BRACKET_SLASH) },
- { "SQUARE_BRACKET_MIDDLE_DOT",
- IDS_MOZC(SYMBOL_METHOD_SQUARE_BRACKET_MIDDLE_DOT) }},
- IDS_MOZC(SYMBOL_METHOD),
- },
- { prefs::kLanguageMozcSpaceCharacterForm,
- "FUNDAMENTAL_INPUT_MODE",
- "space_character_form",
- {{ "FUNDAMENTAL_INPUT_MODE",
- IDS_MOZC(SPACE_CHARACTER_FORM_FUNDAMENTAL_INPUT_MODE) },
- { "FUNDAMENTAL_FULL_WIDTH",
- IDS_MOZC(SPACE_CHARACTER_FORM_FUNDAMENTAL_FULL_WIDTH) },
- { "FUNDAMENTAL_HALF_WIDTH",
- IDS_MOZC(SPACE_CHARACTER_FORM_FUNDAMENTAL_HALF_WIDTH) }},
- IDS_MOZC(SPACE_CHARACTER_FORM),
- },
- { prefs::kLanguageMozcHistoryLearningLevel,
- "DEFAULT_HISTORY",
- "history_learning_level",
- {{ "DEFAULT_HISTORY",
- IDS_MOZC(HISTORY_LEARNING_LEVEL_DEFAULT_HISTORY) },
- { "READ_ONLY",
- IDS_MOZC(HISTORY_LEARNING_LEVEL_READ_ONLY) },
- { "NO_HISTORY",
- IDS_MOZC(HISTORY_LEARNING_LEVEL_NO_HISTORY) }},
- IDS_MOZC(HISTORY_LEARNING_LEVEL),
- },
- // TODO(mazda): Uncomment this block once the candidate window in Chrome OS
- // supports changing shortcut labels.
- // { prefs::kLanguageMozcSelectionShortcut,
- // "SHORTCUT_123456789",
- // "selection_shortcut",
- // {{ "NO_SHORTCUT",
- // IDS_MOZC(SELECTION_SHORTCUT_NO_SHORTCUT) },
- // { "SHORTCUT_123456789",
- // IDS_MOZC(SELECTION_SHORTCUT_SHORTCUT_123456789) },
- // { "SHORTCUT_ASDFGHJKL",
- // IDS_MOZC(SELECTION_SHORTCUT_SHORTCUT_ASDFGHJKL) }},
- // IDS_MOZC(SELECTION_SHORTCUT),
- // },
- { prefs::kLanguageMozcShiftKeyModeSwitch,
- "ASCII_INPUT_MODE",
- "shift_key_mode_switch",
- {{ "OFF",
- IDS_MOZC(SHIFT_KEY_MODE_SWITCH_OFF) },
- { "ASCII_INPUT_MODE",
- IDS_MOZC(SHIFT_KEY_MODE_SWITCH_ASCII_INPUT_MODE) },
- { "KATAKANA_INPUT_MODE",
- IDS_MOZC(SHIFT_KEY_MODE_SWITCH_KATAKANA_INPUT_MODE) }},
- IDS_MOZC(SHIFT_KEY_MODE_SWITCH),
- },
- { prefs::kLanguageMozcNumpadCharacterForm,
- "NUMPAD_HALF_WIDTH",
- "numpad_character_form",
- {{ "NUMPAD_INPUT_MODE",
- IDS_MOZC(NUMPAD_CHARACTER_FORM_NUMPAD_INPUT_MODE) },
- { "NUMPAD_FULL_WIDTH",
- IDS_MOZC(NUMPAD_CHARACTER_FORM_NUMPAD_FULL_WIDTH) },
- { "NUMPAD_HALF_WIDTH",
- IDS_MOZC(NUMPAD_CHARACTER_FORM_NUMPAD_HALF_WIDTH) },
- { "NUMPAD_DIRECT_INPUT",
- IDS_MOZC(NUMPAD_CHARACTER_FORM_NUMPAD_DIRECT_INPUT) }},
- IDS_MOZC(NUMPAD_CHARACTER_FORM),
- },
-};
-const size_t kNumMozcMultipleChoicePrefs = arraysize(kMozcMultipleChoicePrefs);
+extern const PinyinIntegerPref kPinyinIntegerPrefs[];
+const size_t kNumPinyinIntegerPrefs = 1;
-const LanguageIntegerRangePreference kMozcIntegerPrefs[] = {
- { prefs::kLanguageMozcSuggestionsSize, 3, 1, 9, "suggestions_size",
- IDS_MOZC(SUGGESTIONS_SIZE)},
+// ---------------------------------------------------------------------------
+// For Japanese input method (ibus-mozc)
+// ---------------------------------------------------------------------------
+extern const char kMozcSectionName[];
+
+extern const LanguageBooleanPrefs kMozcBooleanPrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumMozcBooleanPrefs = 8;
+
+extern const LanguageMultipleChoicePreference<const char*>
+ kMozcMultipleChoicePrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumMozcMultipleChoicePrefs = 8;
+
+extern const LanguageIntegerRangePreference kMozcIntegerPrefs[];
+// See comments at kNumChewingBooleanPrefs for why we hard-code this here.
+const size_t kNumMozcIntegerPrefs = 1;
+
+// ---------------------------------------------------------------------------
+// For keyboard stuff
+// ---------------------------------------------------------------------------
+// TODO(yusukes): Temporary solution for View version of modifier key remapper.
+// Remove RemapType and kXkbModifierMultipleChoicePrefs when we finish to
+// migrate to DOMUI.
+enum RemapType {
+ kNoRemap = 0,
+ kSwapCtrlAndAlt = 1,
+ kSwapSearchAndCtrl = 2,
};
-const size_t kNumMozcIntegerPrefs = ARRAYSIZE_UNSAFE(kMozcIntegerPrefs);
-
-#undef IDS_MOZC
+extern const LanguageMultipleChoicePreference<int>
+ kXkbModifierMultipleChoicePrefs;
-// For Traditional Chinese input methods (ibus-pinyin-bopomofo and ibus-chewing)
-// TODO(yusukes): Add constants for Traditional Chinese input methods.
+// A delay between the first and the start of the rest.
+extern const int kXkbAutoRepeatDelayInMs;
+// An interval between the repeated keys.
+extern const int kXkbAutoRepeatIntervalInMs;
// A string Chrome preference (Local State) of the preferred keyboard layout in
// the login screen.
-const wchar_t kPreferredKeyboardLayout[] = L"PreferredKeyboardLayout";
-
-// A input method name that corresponds the hardware keyboard layout.
-// TODO(yusukes): just assuming US qwerty keyboard is not always correct.
-const char kHardwareKeyboardLayout[] = "xkb:us::eng";
+extern const char kPreferredKeyboardLayout[];
+} // language_prefs
} // chromeos
#endif // CHROME_BROWSER_CHROMEOS_LANGUAGE_PREFERENCES_H_
diff --git a/chrome/browser/chromeos/language_preferences_unittest.cc b/chrome/browser/chromeos/language_preferences_unittest.cc
index 49c5472..2383a28 100644
--- a/chrome/browser/chromeos/language_preferences_unittest.cc
+++ b/chrome/browser/chromeos/language_preferences_unittest.cc
@@ -10,6 +10,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
+namespace language_prefs {
namespace {
@@ -101,6 +102,8 @@ TEST(LanguagePreferencesTest, TestDefaultValuesOfMultipleChoicePrefs) {
EXPECT_TRUE(CheckDefaultValueOfMultipleChoicePrefs(
kChewingMultipleChoicePrefs, kNumChewingMultipleChoicePrefs));
EXPECT_TRUE(CheckDefaultValueOfMultipleChoicePrefs(
+ &kXkbModifierMultipleChoicePrefs, 1));
+ EXPECT_TRUE(CheckDefaultValueOfMultipleChoicePrefs(
&kChewingHsuSelKeyType, 1));
EXPECT_TRUE(CheckDefaultValueOfMultipleChoicePrefs(
&kPinyinDoublePinyinSchema, 1));
@@ -114,6 +117,8 @@ TEST(LanguagePreferencesTest, TestDuplicationOfMultipleChoicePrefs) {
EXPECT_TRUE(CheckDuplicationOfMultipleChoicePrefs(
kChewingMultipleChoicePrefs, kNumChewingMultipleChoicePrefs));
EXPECT_TRUE(CheckDuplicationOfMultipleChoicePrefs(
+ &kXkbModifierMultipleChoicePrefs, 1));
+ EXPECT_TRUE(CheckDuplicationOfMultipleChoicePrefs(
&kChewingHsuSelKeyType, 1));
EXPECT_TRUE(CheckDuplicationOfMultipleChoicePrefs(
&kPinyinDoublePinyinSchema, 1));
@@ -129,4 +134,5 @@ TEST(LanguagePreferencesTest, TestDefaultValuesOfIntegerRangePrefs) {
kMozcIntegerPrefs, kNumMozcIntegerPrefs));
}
+} // namespace language_prefs
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/account_creation_view.cc b/chrome/browser/chromeos/login/account_creation_view.cc
index 054e966..82ff793 100644
--- a/chrome/browser/chromeos/login/account_creation_view.cc
+++ b/chrome/browser/chromeos/login/account_creation_view.cc
@@ -61,8 +61,6 @@ class AccountCreationTabContents : public WizardWebPageViewTabContents,
virtual bool FillAutoFillFormData(int query_id,
const webkit_glue::FormData& form,
- const string16& name,
- const string16& label,
int unique_id) {
return false;
}
diff --git a/chrome/browser/chromeos/login/account_creation_view.h b/chrome/browser/chromeos/login/account_creation_view.h
index 11aa14d..40bbe31 100644
--- a/chrome/browser/chromeos/login/account_creation_view.h
+++ b/chrome/browser/chromeos/login/account_creation_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ACCOUNT_CREATION_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_ACCOUNT_CREATION_VIEW_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/account_screen.cc b/chrome/browser/chromeos/login/account_screen.cc
index b9ad26d..d7298fc 100644
--- a/chrome/browser/chromeos/login/account_screen.cc
+++ b/chrome/browser/chromeos/login/account_screen.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/chromeos/login/account_screen.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/account_creation_view.h"
@@ -14,6 +15,7 @@
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "googleurl/src/gurl.h"
+#include "views/widget/widget_gtk.h"
namespace chromeos {
@@ -128,6 +130,12 @@ void AccountScreen::NavigationStateChanged(const TabContents* source,
}
}
+void AccountScreen::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
+ views::Widget* widget = view()->GetWidget();
+ if (widget && event.os_event && !event.skip_in_browser)
+ static_cast<views::WidgetGtk*>(widget)->HandleKeyboardEvent(event.os_event);
+}
+
///////////////////////////////////////////////////////////////////////////////
// AccountScreen, WebPageDelegate implementation:
void AccountScreen::OnPageLoaded() {
@@ -137,9 +145,7 @@ void AccountScreen::OnPageLoaded() {
if (g_browser_process) {
const std::string locale = g_browser_process->GetApplicationLocale();
input_method::EnableInputMethods(
- locale, input_method::kKeyboardLayoutsOnly, "");
- // TODO(yusukes,suzhe): Change the 2nd argument to kAllInputMethods when
- // crosbug.com/2670 is fixed.
+ locale, input_method::kAllInputMethods, "");
}
view()->ShowPageContent();
}
diff --git a/chrome/browser/chromeos/login/account_screen.h b/chrome/browser/chromeos/login/account_screen.h
index ec9173c..8d3ca4f 100644
--- a/chrome/browser/chromeos/login/account_screen.h
+++ b/chrome/browser/chromeos/login/account_screen.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ACCOUNT_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_ACCOUNT_SCREEN_H_
+#pragma once
#include <string>
@@ -52,6 +53,7 @@ class AccountScreen : public ViewScreen<AccountCreationView>,
virtual void NavigationStateChanged(const TabContents* source,
unsigned changed_flags);
virtual void LoadingStateChanged(TabContents* source);
+ virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
// WebPageScreen implementation:
virtual void CloseScreen(ScreenObserver::ExitCodes code);
diff --git a/chrome/browser/chromeos/login/account_screen_browsertest.cc b/chrome/browser/chromeos/login/account_screen_browsertest.cc
index 5f39335..eec150d 100644
--- a/chrome/browser/chromeos/login/account_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/account_screen_browsertest.cc
@@ -5,13 +5,14 @@
#include <string>
#include "chrome/browser/child_process_security_policy.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/login/account_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/browser/chrome_thread.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
+#include "net/test/test_server.h"
#include "net/url_request/url_request_about_job.h"
#include "net/url_request/url_request_filter.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -27,9 +28,8 @@ class AccountScreenTest : public WizardInProcessBrowserTest {
protected:
// Overridden from WizardInProcessBrowserTest:
virtual void SetUpWizard() {
- HTTPTestServer* server = StartHTTPServer();
- ASSERT_TRUE(server != NULL);
- GURL new_account_page_url(server->TestServerPage("files/new_account.html"));
+ ASSERT_TRUE(test_server()->Start());
+ GURL new_account_page_url(test_server()->GetURL("files/new_account.html"));
AccountScreen::set_new_account_page_url(new_account_page_url);
AccountScreen::set_check_for_https(false);
}
@@ -41,8 +41,7 @@ class AccountScreenTest : public WizardInProcessBrowserTest {
// A basic test. It does not care how things evolve after the URL is
// loaded. Thus no message loop is started. Just check that initial
// status is expected.
-// This test is flaky. See http://crbug.com/49004 .
-IN_PROC_BROWSER_TEST_F(AccountScreenTest, FLAKY_TestBasic) {
+IN_PROC_BROWSER_TEST_F(AccountScreenTest, TestBasic) {
ASSERT_TRUE(controller());
EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
}
@@ -69,7 +68,7 @@ static URLRequestJob* InspectorHook(URLRequest* request,
return new URLRequestAboutJob(request);
}
-IN_PROC_BROWSER_TEST_F(AccountScreenTest, FLAKY_TestSchemeInspector) {
+IN_PROC_BROWSER_TEST_F(AccountScreenTest, TestSchemeInspector) {
ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
chrome::kCrosScheme);
URLRequestFilter::GetInstance()->AddHostnameHandler(chrome::kCrosScheme,
diff --git a/chrome/browser/chromeos/login/auth_response_handler.h b/chrome/browser/chromeos/login/auth_response_handler.h
index 826baeb..9be1a5e 100644
--- a/chrome/browser/chromeos/login/auth_response_handler.h
+++ b/chrome/browser/chromeos/login/auth_response_handler.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/authentication_notification_details.h b/chrome/browser/chromeos/login/authentication_notification_details.h
index 4ad9f0d..2b14419 100644
--- a/chrome/browser/chromeos/login/authentication_notification_details.h
+++ b/chrome/browser/chromeos/login/authentication_notification_details.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATION_NOTIFICATION_DETAILS_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATION_NOTIFICATION_DETAILS_H_
+#pragma once
// A class to hold the parameters we get back from an authentication attempt
// through the login manager
diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h
index bc0bdca..5fba9c3 100644
--- a/chrome/browser/chromeos/login/authenticator.h
+++ b/chrome/browser/chromeos/login/authenticator.h
@@ -4,12 +4,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATOR_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATOR_H_
+#pragma once
-#include <vector>
-
-#include "base/logging.h"
+#include "base/basictypes.h"
#include "base/ref_counted.h"
-#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
@@ -25,10 +23,8 @@ namespace chromeos {
// consumer_->OnPasswordChangeDetected() on the UI thread.
class Authenticator : public base::RefCountedThreadSafe<Authenticator> {
public:
- explicit Authenticator(LoginStatusConsumer* consumer)
- : consumer_(consumer) {
- }
- virtual ~Authenticator() {}
+ explicit Authenticator(LoginStatusConsumer* consumer);
+ virtual ~Authenticator();
// Given a |username| and |password|, this method attempts to authenticate
// to login.
@@ -55,7 +51,7 @@ class Authenticator : public base::RefCountedThreadSafe<Authenticator> {
// and also call back to the login UI.
virtual void OnLoginSuccess(
const GaiaAuthConsumer::ClientLoginResult& credentials) = 0;
- virtual void OnLoginFailure(const std::string& data) = 0;
+ virtual void OnLoginFailure(const LoginFailure& error) = 0;
// Call these methods on the UI thread.
// If a password logs the user in online, but cannot be used to
@@ -75,6 +71,13 @@ class Authenticator : public base::RefCountedThreadSafe<Authenticator> {
virtual void ResyncEncryptedData(
const GaiaAuthConsumer::ClientLoginResult& credentials) = 0;
+ // Perform basic canonicalization of |email_address|, taking into account
+ // that gmail does not consider '.' or caps inside a username to matter.
+ // It also ignores everything after a '+'.
+ // For example, c.masone+abc@gmail.com == cMaSone@gmail.com, per
+ // http://mail.google.com/support/bin/answer.py?hl=en&ctx=mail&answer=10313#
+ static std::string Canonicalize(const std::string& email_address);
+
protected:
LoginStatusConsumer* consumer_;
diff --git a/chrome/browser/chromeos/login/background_view.cc b/chrome/browser/chromeos/login/background_view.cc
index 3d9f954..199f92f 100644
--- a/chrome/browser/chromeos/login/background_view.cc
+++ b/chrome/browser/chromeos/login/background_view.cc
@@ -4,21 +4,33 @@
#include "chrome/browser/chromeos/login/background_view.h"
+#include <string>
+#include <vector>
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/x11_util.h"
+#include "base/string16.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/oobe_progress_bar.h"
+#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/status/clock_menu_button.h"
#include "chrome/browser/chromeos/status/feedback_menu_button.h"
#include "chrome/browser/chromeos/status/language_menu_button.h"
#include "chrome/browser/chromeos/status/network_menu_button.h"
#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/dom_view.h"
#include "cros/chromeos_wm_ipc_enums.h"
+#include "googleurl/src/gurl.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "views/controls/button/text_button.h"
#include "views/controls/label.h"
#include "views/screen.h"
#include "views/widget/widget_gtk.h"
@@ -30,22 +42,35 @@
using views::WidgetGtk;
-namespace chromeos {
+namespace {
-BackgroundView::BackgroundView()
- : status_area_(NULL),
- os_version_label_(NULL),
- boot_times_label_(NULL),
- did_paint_(false) {
- views::Painter* painter = CreateBackgroundPainter();
- set_background(views::Background::CreateBackgroundPainter(true, painter));
- InitStatusArea();
- InitInfoLabels();
-}
+// The same as TextButton but switches cursor to hand cursor when mouse
+// is over the button.
+class TextButtonWithHandCursorOver : public views::TextButton {
+ public:
+ TextButtonWithHandCursorOver(views::ButtonListener* listener,
+ const std::wstring& text)
+ : views::TextButton(listener, text) {
+ }
+
+ virtual ~TextButtonWithHandCursorOver() {}
+
+ virtual gfx::NativeCursor GetCursorForPoint(
+ views::Event::EventType event_type,
+ const gfx::Point& p) {
+ if (!IsEnabled()) {
+ return NULL;
+ }
+ return gdk_cursor_new(GDK_HAND2);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextButtonWithHandCursorOver);
+};
+// This gets rid of the ugly X default cursor.
static void ResetXCursor() {
// TODO(sky): nuke this once new window manager is in place.
- // This gets rid of the ugly X default cursor.
Display* display = x11_util::GetXDisplay();
Cursor cursor = XCreateFontCursor(display, XC_left_ptr);
XID root_window = x11_util::GetX11RootWindow();
@@ -54,15 +79,54 @@ static void ResetXCursor() {
XChangeWindowAttributes(display, root_window, CWCursor, &attr);
}
+} // namespace
+
+namespace chromeos {
+
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundView public:
+
+BackgroundView::BackgroundView()
+ : status_area_(NULL),
+ os_version_label_(NULL),
+ boot_times_label_(NULL),
+ progress_bar_(NULL),
+ go_incognito_button_(NULL),
+ did_paint_(false),
+ delegate_(NULL),
+ background_area_(NULL) {
+}
+
+void BackgroundView::Init(const GURL& background_url) {
+ views::Painter* painter = CreateBackgroundPainter();
+ set_background(views::Background::CreateBackgroundPainter(true, painter));
+ InitStatusArea();
+ InitInfoLabels();
+ if (!background_url.is_empty()) {
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ background_area_ = new DOMView();
+ AddChildView(background_area_);
+ background_area_->Init(profile, NULL);
+ background_area_->SetVisible(false);
+ background_area_->LoadURL(background_url);
+ }
+}
+
// static
views::Widget* BackgroundView::CreateWindowContainingView(
const gfx::Rect& bounds,
+ const GURL& background_url,
BackgroundView** view) {
ResetXCursor();
WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
window->Init(NULL, bounds);
*view = new BackgroundView();
+ (*view)->Init(background_url);
+
+ if ((*view)->ScreenSaverEnabled())
+ (*view)->ShowScreenSaver();
+
window->SetContentsView(*view);
(*view)->UpdateWindowType();
@@ -78,6 +142,72 @@ void BackgroundView::SetStatusAreaVisible(bool visible) {
status_area_->SetVisible(visible);
}
+void BackgroundView::SetOobeProgressBarVisible(bool visible) {
+ if (!progress_bar_ && visible)
+ InitProgressBar();
+
+ if (progress_bar_)
+ progress_bar_->SetVisible(visible);
+}
+
+bool BackgroundView::IsOobeProgressBarVisible() {
+ return progress_bar_ && progress_bar_->IsVisible();
+}
+
+void BackgroundView::SetOobeProgress(LoginStep step) {
+ DCHECK(step <= PICTURE);
+ if (progress_bar_)
+ progress_bar_->SetProgress(step);
+}
+
+// Toggles GoIncognito button visibility.
+void BackgroundView::SetGoIncognitoButtonVisible(bool visible,
+ Delegate *delegate) {
+ // Set delegate to handle button pressing.
+ delegate_ = delegate;
+ bool currently_visible =
+ go_incognito_button_ && go_incognito_button_->IsVisible();
+ if (currently_visible != visible) {
+ if (!go_incognito_button_) {
+ InitGoIncognitoButton();
+ }
+ go_incognito_button_->SetVisible(visible);
+ }
+}
+
+void BackgroundView::ShowScreenSaver() {
+ SetStatusAreaVisible(false);
+ background_area_->SetVisible(true);
+}
+
+void BackgroundView::HideScreenSaver() {
+ SetStatusAreaVisible(true);
+ // TODO(oshima): we need a way to suspend screen saver
+ // to save power when it's not visible.
+ background_area_->SetVisible(false);
+}
+
+bool BackgroundView::IsScreenSaverVisible() {
+ return ScreenSaverEnabled() && background_area_->IsVisible();
+}
+
+bool BackgroundView::ScreenSaverEnabled() {
+ return background_area_ != NULL;
+}
+
+void BackgroundView::OnOwnerChanged() {
+ if (go_incognito_button_) {
+ // BackgroundView is passed among multiple controllers, so they should
+ // explicitly enable "Go incognito" button if needed.
+ RemoveChildView(go_incognito_button_);
+ delete go_incognito_button_;
+ go_incognito_button_ = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundView protected:
+
void BackgroundView::Paint(gfx::Canvas* canvas) {
views::View::Paint(canvas);
if (!did_paint_) {
@@ -87,14 +217,19 @@ void BackgroundView::Paint(gfx::Canvas* canvas) {
}
void BackgroundView::Layout() {
- int corner_padding = 5;
- int kInfoLeftPadding = 60;
- int kInfoBottomPadding = 40;
- int kInfoBetweenLinesPadding = 4;
+ const int kCornerPadding = 5;
+ const int kInfoLeftPadding = 60;
+ const int kInfoBottomPadding = 10;
+ const int kInfoBetweenLinesPadding = 4;
+ const int kProgressBarBottomPadding = 20;
+ const int kProgressBarWidth = 750;
+ const int kProgressBarHeight = 70;
+ const int kGoIncognitoButtonBottomPadding = 12;
+ const int kGoIncognitoButtonRightPadding = 12;
gfx::Size status_area_size = status_area_->GetPreferredSize();
status_area_->SetBounds(
- width() - status_area_size.width() - corner_padding,
- corner_padding,
+ width() - status_area_size.width() - kCornerPadding,
+ kCornerPadding,
status_area_size.width(),
status_area_size.height());
gfx::Size version_size = os_version_label_->GetPreferredSize();
@@ -109,8 +244,25 @@ void BackgroundView::Layout() {
boot_times_label_->SetBounds(
kInfoLeftPadding,
height() - (version_size.height() + kInfoBottomPadding),
- width() - 2 * corner_padding,
+ width() - 2 * kCornerPadding,
version_size.height());
+ if (progress_bar_) {
+ progress_bar_->SetBounds(
+ (width() - kProgressBarWidth) / 2,
+ (height() - kProgressBarBottomPadding - kProgressBarHeight),
+ kProgressBarWidth,
+ kProgressBarHeight);
+ }
+ if (go_incognito_button_) {
+ gfx::Size go_button_size = go_incognito_button_->GetPreferredSize();
+ go_incognito_button_->SetBounds(
+ width() - go_button_size.width()- kGoIncognitoButtonRightPadding,
+ height() - go_button_size.height() - kGoIncognitoButtonBottomPadding,
+ go_button_size.width(),
+ go_button_size.height());
+ }
+ if (background_area_)
+ background_area_->SetBounds(this->bounds());
}
void BackgroundView::ChildPreferredSizeChanged(View* child) {
@@ -118,6 +270,12 @@ void BackgroundView::ChildPreferredSizeChanged(View* child) {
SchedulePaint();
}
+void BackgroundView::OnLocaleChanged() {
+ UpdateLocalizedStrings();
+ Layout();
+ SchedulePaint();
+}
+
gfx::NativeWindow BackgroundView::GetNativeWindow() const {
return
GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
@@ -138,12 +296,6 @@ void BackgroundView::OpenButtonOptions(const views::View* button_view) const {
// TODO(avayvod): Add some dialog for options or remove them completely.
}
-bool BackgroundView::IsButtonVisible(const views::View* button_view) const {
- if (button_view == status_area_->feedback_view())
- return false;
- return true;
-}
-
bool BackgroundView::IsBrowserMode() const {
return false;
}
@@ -152,15 +304,25 @@ bool BackgroundView::IsScreenLockerMode() const {
return false;
}
-void BackgroundView::LocaleChanged() {
- Layout();
- SchedulePaint();
+void BackgroundView::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
+ if (sender == go_incognito_button_) {
+ DCHECK(delegate_);
+ if (delegate_) {
+ delegate_->OnGoIncognitoButton();
+ }
+ }
}
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundView private:
+
void BackgroundView::InitStatusArea() {
DCHECK(status_area_ == NULL);
status_area_ = new StatusAreaView(this);
status_area_->Init();
+ // Feedback button shoudn't be visible on OOBE/login/screen lock.
+ status_area_->feedback_view()->SetVisible(false);
AddChildView(status_area_);
}
@@ -190,6 +352,66 @@ void BackgroundView::InitInfoLabels() {
}
}
+void BackgroundView::InitProgressBar() {
+ std::vector<int> steps;
+ steps.push_back(IDS_OOBE_SELECT_NETWORK);
+#if defined(OFFICIAL_BUILD)
+ steps.push_back(IDS_OOBE_EULA);
+#endif
+ steps.push_back(IDS_OOBE_SIGNIN);
+#if defined(OFFICIAL_BUILD)
+ steps.push_back(IDS_OOBE_REGISTRATION);
+#endif
+ steps.push_back(IDS_OOBE_PICTURE);
+ progress_bar_ = new OobeProgressBar(steps);
+ AddChildView(progress_bar_);
+}
+
+void BackgroundView::InitGoIncognitoButton() {
+ SkColor kButtonColor = 0xFF4F6985;
+ SkColor kStrokeColor = 0xFF657A91;
+ int kStrokeWidth = 1;
+ int kVerticalPadding = 8;
+ int kHorizontalPadding = 12;
+ int kCornerRadius = 4;
+
+ go_incognito_button_ =
+ new TextButtonWithHandCursorOver(this, std::wstring());
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ go_incognito_button_->SetIcon(*rb.GetBitmapNamed(IDR_INCOGNITO_GUY));
+ go_incognito_button_->SetFocusable(true);
+ // Set label colors.
+ go_incognito_button_->SetEnabledColor(SK_ColorWHITE);
+ go_incognito_button_->SetDisabledColor(SK_ColorWHITE);
+ go_incognito_button_->SetHighlightColor(SK_ColorWHITE);
+ go_incognito_button_->SetHoverColor(SK_ColorWHITE);
+ // Disable throbbing and make border always visible.
+ go_incognito_button_->SetAnimationDuration(0);
+ go_incognito_button_->SetNormalHasBorder(true);
+ // Setup round shapes.
+ go_incognito_button_->set_background(
+ CreateRoundedBackground(
+ kCornerRadius, kStrokeWidth, kButtonColor, kStrokeColor));
+
+ go_incognito_button_->set_border(
+ views::Border::CreateEmptyBorder(kVerticalPadding,
+ kHorizontalPadding,
+ kVerticalPadding,
+ kHorizontalPadding));
+ // Set button text.
+ UpdateLocalizedStrings();
+ // Enable and add to the views hierarchy.
+ go_incognito_button_->SetEnabled(true);
+ AddChildView(go_incognito_button_);
+}
+
+void BackgroundView::UpdateLocalizedStrings() {
+ if (go_incognito_button_) {
+ go_incognito_button_->SetText(
+ UTF8ToWide(l10n_util::GetStringUTF8(IDS_GO_INCOGNITO_BUTTON)));
+ }
+}
+
void BackgroundView::UpdateWindowType() {
std::vector<int> params;
params.push_back(did_paint_ ? 1 : 0);
@@ -223,7 +445,7 @@ void BackgroundView::OnBootTimes(
if (boot_times.chrome > 0) {
boot_times_text =
- StringPrintf(
+ base::StringPrintf(
kBootTimesChromeExec,
boot_times.total,
boot_times.firmware,
@@ -232,7 +454,7 @@ void BackgroundView::OnBootTimes(
boot_times.chrome);
} else {
boot_times_text =
- StringPrintf(
+ base::StringPrintf(
kBootTimesNoChromeExec,
boot_times.total,
boot_times.firmware,
diff --git a/chrome/browser/chromeos/login/background_view.h b/chrome/browser/chromeos/login/background_view.h
index f5c4540..9fcad2a 100644
--- a/chrome/browser/chromeos/login/background_view.h
+++ b/chrome/browser/chromeos/login/background_view.h
@@ -4,45 +4,108 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_BACKGROUND_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_BACKGROUND_VIEW_H_
+#pragma once
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/version_loader.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
+#include "chrome/browser/chromeos/version_loader.h"
+#include "views/controls/button/button.h"
#include "views/view.h"
namespace views {
class Widget;
class Label;
+class TextButton;
}
+class DOMView;
+class GURL;
class Profile;
namespace chromeos {
+class OobeProgressBar;
class StatusAreaView;
// View used to render the background during login. BackgroundView contains
// StatusAreaView.
-class BackgroundView : public views::View, public StatusAreaHost {
+class BackgroundView : public views::View,
+ public StatusAreaHost,
+ public views::ButtonListener {
public:
+ // Delegate class to handle notificatoin from the view.
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Initializes incognito login.
+ virtual void OnGoIncognitoButton() = 0;
+ };
+
+ enum LoginStep {
+ SELECT_NETWORK,
+#if defined(OFFICIAL_BUILD)
+ EULA,
+#endif
+ SIGNIN,
+#if defined(OFFICIAL_BUILD)
+ REGISTRATION,
+#endif
+ PICTURE
+ };
+
BackgroundView();
+ // Initializes the background view. It backgroun_url is given (non empty),
+ // it creates a DOMView background area that renders a webpage.
+ void Init(const GURL& background_url);
+
// Creates a window containing an instance of WizardContentsView as the root
// view. The caller is responsible for showing (and closing) the returned
- // widget. The BackgroundView is set in |view|.
- static views::Widget* CreateWindowContainingView(const gfx::Rect& bounds,
- BackgroundView** view);
+ // widget. The BackgroundView is set in |view|. If background_url is non
+ // empty, the content page of the url is displayed as a background.
+ static views::Widget* CreateWindowContainingView(
+ const gfx::Rect& bounds,
+ const GURL& background_url,
+ BackgroundView** view);
// Toggles status area visibility.
void SetStatusAreaVisible(bool visible);
+ // Toggles OOBE progress bar visibility, the bar is hidden by default.
+ void SetOobeProgressBarVisible(bool visible);
+
+ // Gets progress bar visibility.
+ bool IsOobeProgressBarVisible();
+
+ // Sets current step on OOBE progress bar.
+ void SetOobeProgress(LoginStep step);
+
+ // Toggles GoIncognito button visibility.
+ void SetGoIncognitoButtonVisible(bool visible, Delegate *delegate);
+
+ // Shows screen saver.
+ void ShowScreenSaver();
+
+ // Hides screen saver.
+ void HideScreenSaver();
+
+ // Tells if screen saver is visible.
+ bool IsScreenSaverVisible();
+
+ // Tells if screen saver is enabled.
+ bool ScreenSaverEnabled();
+
+ // Tells that owner has been changed.
+ void OnOwnerChanged();
+
protected:
// Overridden from views::View:
virtual void Paint(gfx::Canvas* canvas);
virtual void Layout();
virtual void ChildPreferredSizeChanged(View* child);
- virtual void LocaleChanged();
+ virtual void OnLocaleChanged();
// Overridden from StatusAreaHost:
virtual Profile* GetProfile() const { return NULL; }
@@ -51,15 +114,24 @@ class BackgroundView : public views::View, public StatusAreaHost {
virtual bool ShouldOpenButtonOptions(
const views::View* button_view) const;
virtual void OpenButtonOptions(const views::View* button_view) const;
- virtual bool IsButtonVisible(const views::View* button_view) const;
virtual bool IsBrowserMode() const;
virtual bool IsScreenLockerMode() const;
-private:
+ // Overridden from views::ButtonListener.
+ virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+
+ private:
// Creates and adds the status_area.
void InitStatusArea();
// Creates and adds the labels for version and boot time.
void InitInfoLabels();
+ // Creates and add OOBE progress bar.
+ void InitProgressBar();
+ // Creates and add GoIncoginito button.
+ void InitGoIncognitoButton();
+
+ // Updates string from the resources.
+ void UpdateLocalizedStrings();
// Invokes SetWindowType for the window. This is invoked during startup and
// after we've painted.
@@ -71,9 +143,12 @@ private:
void OnBootTimes(
BootTimesLoader::Handle handle, BootTimesLoader::BootTimes boot_times);
+ // All of these variables could be NULL.
StatusAreaView* status_area_;
views::Label* os_version_label_;
views::Label* boot_times_label_;
+ OobeProgressBar* progress_bar_;
+ views::TextButton* go_incognito_button_;
// Handles asynchronously loading the version.
VersionLoader version_loader_;
@@ -90,6 +165,11 @@ private:
// TODO(sky): nuke this when the wm knows when chrome has painted.
bool did_paint_;
+ Delegate *delegate_;
+
+ // DOMView for rendering a webpage as a background.
+ DOMView* background_area_;
+
DISALLOW_COPY_AND_ASSIGN(BackgroundView);
};
diff --git a/chrome/browser/chromeos/login/camera.cc b/chrome/browser/chromeos/login/camera.cc
index db0fde7..8e1bef6 100644
--- a/chrome/browser/chromeos/login/camera.cc
+++ b/chrome/browser/chromeos/login/camera.cc
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "gfx/size.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -242,7 +243,7 @@ void Camera::StopCapturing() {
int Camera::OpenDevice(const char* device_name) const {
struct stat st;
if (stat(device_name, &st) == -1) {
- log_errno(StringPrintf("Cannot identify %s", device_name));
+ log_errno(base::StringPrintf("Cannot identify %s", device_name));
return -1;
}
if (!S_ISCHR(st.st_mode)) {
@@ -251,7 +252,7 @@ int Camera::OpenDevice(const char* device_name) const {
}
int fd = open(device_name, O_RDWR | O_NONBLOCK, 0);
if (fd == -1) {
- log_errno(StringPrintf("Cannot open %s", device_name));
+ log_errno(base::StringPrintf("Cannot open %s", device_name));
return -1;
}
return fd;
diff --git a/chrome/browser/chromeos/login/camera.h b/chrome/browser/chromeos/login/camera.h
index 0acfecd..eb4498c 100644
--- a/chrome/browser/chromeos/login/camera.h
+++ b/chrome/browser/chromeos/login/camera.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
+#pragma once
#include <string>
#include <vector>
diff --git a/chrome/browser/chromeos/login/captcha_view.h b/chrome/browser/chromeos/login/captcha_view.h
index 872729a..491c438 100644
--- a/chrome/browser/chromeos/login/captcha_view.h
+++ b/chrome/browser/chromeos/login/captcha_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CAPTCHA_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_CAPTCHA_VIEW_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/client_login_response_handler.h b/chrome/browser/chromeos/login/client_login_response_handler.h
index c0f1227..8fc1fe1 100644
--- a/chrome/browser/chromeos/login/client_login_response_handler.h
+++ b/chrome/browser/chromeos/login/client_login_response_handler.h
@@ -4,10 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_
+#pragma once
#include <string>
-#include "base/logging.h"
+#include "base/basictypes.h"
#include "chrome/browser/chromeos/login/auth_response_handler.h"
class URLRequestContextGetter;
diff --git a/chrome/browser/chromeos/login/cookie_fetcher.cc b/chrome/browser/chromeos/login/cookie_fetcher.cc
index 48c7dec..0ea3c74 100644
--- a/chrome/browser/chromeos/login/cookie_fetcher.cc
+++ b/chrome/browser/chromeos/login/cookie_fetcher.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "base/command_line.h"
-#include "base/file_path.h"
#include "base/path_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/client_login_response_handler.h"
diff --git a/chrome/browser/chromeos/login/cookie_fetcher.h b/chrome/browser/chromeos/login/cookie_fetcher.h
index ef82d55..4c6d66a 100644
--- a/chrome/browser/chromeos/login/cookie_fetcher.h
+++ b/chrome/browser/chromeos/login/cookie_fetcher.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_COOKIE_FETCHER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_COOKIE_FETCHER_H_
+#pragma once
#include <string>
#include "base/scoped_ptr.h"
diff --git a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc b/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
index d068007..b5e3a4f 100644
--- a/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
+++ b/chrome/browser/chromeos/login/cookie_fetcher_unittest.cc
@@ -5,16 +5,17 @@
#include <errno.h>
#include <string>
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/login/cookie_fetcher.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/login/client_login_response_handler.h"
+#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/issue_response_handler.h"
#include "chrome/browser/chromeos/login/mock_auth_response_handler.h"
#include "chrome/common/net/url_fetcher.h"
#include "chrome/test/testing_profile.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_status.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
using ::testing::Return;
diff --git a/chrome/browser/chromeos/login/eula_view.cc b/chrome/browser/chromeos/login/eula_view.cc
index 2efe93f..b9e7b2a 100644
--- a/chrome/browser/chromeos/login/eula_view.cc
+++ b/chrome/browser/chromeos/login/eula_view.cc
@@ -10,42 +10,55 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/basictypes.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/customization_document.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
-#include "chrome/browser/chromeos/login/screen_observer.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/options_util.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/dom_view.h"
+#include "chrome/common/native_web_keyboard_event.h"
+#include "chrome/common/url_constants.h"
#include "chrome/installer/util/google_update_settings.h"
+#include "cros/chromeos_cryptohome.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "views/controls/button/checkbox.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
-#include "views/controls/textfield/textfield.h"
#include "views/grid_layout.h"
+#include "views/layout_manager.h"
#include "views/standard_layout.h"
+#include "views/widget/widget_gtk.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
+
+#if defined(USE_LINUX_BREAKPAD)
+#include "chrome/app/breakpad_linux.h"
+#endif
+
+using views::WidgetGtk;
namespace {
const int kBorderSize = 10;
const int kMargin = 20;
const int kLastButtonHorizontalMargin = 10;
-const int kTextMargin = 10;
const int kCheckBowWidth = 22;
+const int kTextMargin = 10;
-// Fake EULA texts. TODO(glotov): implement reading actual file.
-const wchar_t kLoremIpsum[] = L"Lorem ipsum dolor sit amet, "
- L"consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"
- L"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
- L"exercitation ullamco laboris nisi ut aliquip ex ea commodo "
- L"consequat. Duis aute irure dolor in reprehenderit in voluptate velit "
- L"esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat "
- L"cupidatat non proident, sunt in culpa qui officia deserunt mollit anim "
- L"id est laborum.\n";
-const wchar_t kFakeGoogleEula[] = L"\nGoogle Chrome Terms of Service\n"
- L"These Terms of Service apply to the executable code version of "
- L"Google Chrome. ";
-const wchar_t kFakeOemEula[] = L"\nYBH Terms of Service\n";
+// TODO(glotov): this URL should be changed to actual Google ChromeOS EULA.
+// See crbug.com/4647
+const char kGoogleEulaUrl[] = "about:terms";
enum kLayoutColumnsets {
SINGLE_CONTROL_ROW,
@@ -54,35 +67,106 @@ enum kLayoutColumnsets {
LAST_ROW
};
+// A simple LayoutManager that causes the associated view's one child to be
+// sized to match the bounds of its parent except the bounds, if set.
+struct FillLayoutWithBorder : public views::LayoutManager {
+ // Overridden from LayoutManager:
+ virtual void Layout(views::View* host) {
+ DCHECK(host->GetChildViewCount());
+ host->GetChildViewAt(0)->SetBounds(host->GetLocalBounds(false));
+ }
+ virtual gfx::Size GetPreferredSize(views::View* host) {
+ return gfx::Size(host->width(), host->height());
+ }
+};
+
+// System security setting dialog.
+class TpmInfoView : public views::View,
+ public views::DialogDelegate {
+ public:
+ explicit TpmInfoView(std::wstring password) : password_(password) { }
+ void Init();
+
+ protected:
+ // views::DialogDelegate overrides:
+ virtual bool Accept() { return true; }
+ virtual bool IsModal() const { return true; }
+ virtual views::View* GetContentsView() { return this; }
+ virtual int GetDialogButtons() const {
+ return MessageBoxFlags::DIALOGBUTTON_OK;
+ }
+
+ // views::View overrides:
+ virtual std::wstring GetWindowTitle() const {
+ return l10n_util::GetString(IDS_EULA_SYSTEM_SECURITY_SETTING);
+ }
+
+ gfx::Size GetPreferredSize() {
+ return gfx::Size(views::Window::GetLocalizedContentsSize(
+ IDS_TPM_INFO_DIALOG_WIDTH_CHARS,
+ IDS_TPM_INFO_DIALOG_HEIGHT_LINES));
+ }
+
+ private:
+ std::wstring password_;
+ DISALLOW_COPY_AND_ASSIGN(TpmInfoView);
+};
+
+void TpmInfoView::Init() {
+ views::GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+ views::ColumnSet* column_set = layout->AddColumnSet(0);
+ column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+ views::GridLayout::USE_PREF, 0, 0);
+ layout->StartRow(0, 0);
+ views::Label* label = new views::Label(
+ l10n_util::GetString(IDS_EULA_SYSTEM_SECURITY_SETTING_DESCRIPTION));
+ label->SetMultiLine(true);
+ layout->AddView(label);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ column_set = layout->AddColumnSet(1);
+ column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+ views::GridLayout::USE_PREF, 0, 0);
+ layout->StartRow(0, 1);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ gfx::Font password_font =
+ rb.GetFont(ResourceBundle::MediumFont).DeriveFont(0, gfx::Font::BOLD);
+ label = new views::Label(password_, password_font);
+ layout->AddView(label);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+}
+
} // namespace
namespace chromeos {
+////////////////////////////////////////////////////////////////////////////////
+// EulaView, public:
+
EulaView::EulaView(chromeos::ScreenObserver* observer)
- : google_eula_text_(NULL),
+ : google_eula_label_(NULL),
+ google_eula_view_(NULL),
usage_statistics_checkbox_(NULL),
learn_more_link_(NULL),
- oem_eula_text_(NULL),
+ oem_eula_label_(NULL),
+ oem_eula_view_(NULL),
system_security_settings_link_(NULL),
- cancel_button_(NULL),
+ back_button_(NULL),
continue_button_(NULL),
- observer_(observer) {
+ observer_(observer),
+ bubble_(NULL) {
}
EulaView::~EulaView() {
+ // bubble_ will be set to NULL in callback.
+ if (bubble_)
+ bubble_->Close();
}
-void EulaView::Init() {
- // Use rounded rect background.
- views::Painter* painter = CreateWizardPainter(
- &BorderDefinition::kScreenBorder);
- set_background(
- views::Background::CreateBackgroundPainter(true, painter));
-
- // Layout created controls.
+// Convenience function to set layout's columnsets for this screen.
+static void SetUpGridLayout(views::GridLayout* layout) {
static const int kPadding = kBorderSize + kMargin;
- views::GridLayout* layout = new views::GridLayout(this);
- SetLayoutManager(layout);
views::ColumnSet* column_set = layout->AddColumnSet(SINGLE_CONTROL_ROW);
column_set->AddPaddingColumn(0, kPadding);
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
@@ -111,21 +195,77 @@ void EulaView::Init() {
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
views::GridLayout::USE_PREF, 0, 0);
column_set->AddPaddingColumn(0, kLastButtonHorizontalMargin + kBorderSize);
+}
+
+// Convenience function. Returns URL of the OEM EULA page that should be
+// displayed using current locale and manifest. Returns empty URL otherwise.
+static GURL GetOemEulaPagePath() {
+ const StartupCustomizationDocument *customization =
+ WizardController::default_controller()->GetCustomization();
+ if (customization) {
+ std::string locale = g_browser_process->GetApplicationLocale();
+ FilePath eula_page_path = customization->GetEULAPagePath(locale);
+ if (eula_page_path.empty()) {
+ LOG(INFO) << "No eula found for locale: " << locale;
+ locale = customization->initial_locale();
+ eula_page_path = customization->GetEULAPagePath(locale);
+ }
+ if (!eula_page_path.empty()) {
+ const std::string page_path = std::string(chrome::kFileScheme) +
+ chrome::kStandardSchemeSeparator + eula_page_path.value();
+ return GURL(page_path);
+ } else {
+ LOG(INFO) << "No eula found for locale: " << locale;
+ }
+ } else {
+ LOG(ERROR) << "No manifest found.";
+ }
+ return GURL();
+}
+
+void EulaView::Init() {
+ // Use rounded rect background.
+ views::Painter* painter = CreateWizardPainter(
+ &BorderDefinition::kScreenBorder);
+ set_background(
+ views::Background::CreateBackgroundPainter(true, painter));
+ // Layout created controls.
+ views::GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+ SetUpGridLayout(layout);
+
+ static const int kPadding = kBorderSize + kMargin;
layout->AddPaddingRow(0, kPadding);
+ layout->StartRow(0, SINGLE_CONTROL_ROW);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ gfx::Font label_font =
+ rb.GetFont(ResourceBundle::MediumFont).DeriveFont(0, gfx::Font::NORMAL);
+ google_eula_label_ = new views::Label(std::wstring(), label_font);
+ layout->AddView(google_eula_label_, 1, 1,
+ views::GridLayout::LEADING, views::GridLayout::FILL);
+
+ layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
layout->StartRow(1, SINGLE_CONTROL_ROW);
- google_eula_text_ = new views::Textfield(views::Textfield::STYLE_MULTILINE);
- google_eula_text_->SetReadOnly(true);
- google_eula_text_->SetFocusable(true);
- google_eula_text_->SetHorizontalMargins(kTextMargin, kTextMargin);
- layout->AddView(google_eula_text_);
+ views::View* box_view = new views::View();
+ box_view->set_border(views::Border::CreateSolidBorder(1, SK_ColorBLACK));
+ box_view->SetLayoutManager(new FillLayoutWithBorder());
+ layout->AddView(box_view);
+ google_eula_view_ = new DOMView();
+ box_view->AddChildView(google_eula_view_);
+
+ layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
layout->StartRow(0, SINGLE_CONTROL_WITH_SHIFT_ROW);
usage_statistics_checkbox_ = new views::Checkbox();
usage_statistics_checkbox_->SetMultiLine(true);
- usage_statistics_checkbox_->SetChecked(
- GoogleUpdateSettings::GetCollectStatsConsent());
+
+ // TODO(zelidrag): http://crosbug/6367 - Change default settings for checked
+ // and enabled state of usage_statistics_checkbox_ before the product is
+ // released.
+ usage_statistics_checkbox_->SetChecked(true);
layout->AddView(usage_statistics_checkbox_);
+ usage_statistics_checkbox_->SetEnabled(false);
layout->StartRow(0, SINGLE_LINK_WITH_SHIFT_ROW);
learn_more_link_ = new views::Link();
@@ -133,22 +273,37 @@ void EulaView::Init() {
layout->AddView(learn_more_link_);
layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
- layout->StartRow(1, SINGLE_CONTROL_ROW);
- oem_eula_text_ = new views::Textfield(views::Textfield::STYLE_MULTILINE);
- oem_eula_text_->SetReadOnly(true);
- oem_eula_text_->SetFocusable(true);
- oem_eula_text_->SetHorizontalMargins(kTextMargin, kTextMargin);
- layout->AddView(oem_eula_text_);
+ layout->StartRow(0, SINGLE_CONTROL_ROW);
+ oem_eula_label_ = new views::Label(std::wstring(), label_font);
+ layout->AddView(oem_eula_label_, 1, 1,
+ views::GridLayout::LEADING, views::GridLayout::FILL);
+
+ oem_eula_page_ = GetOemEulaPagePath();
+ if (!oem_eula_page_.is_empty()) {
+ layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+ layout->StartRow(1, SINGLE_CONTROL_ROW);
+ box_view = new views::View();
+ box_view->SetLayoutManager(new FillLayoutWithBorder());
+ box_view->set_border(views::Border::CreateSolidBorder(1, SK_ColorBLACK));
+ layout->AddView(box_view);
+
+ oem_eula_view_ = new DOMView();
+ box_view->AddChildView(oem_eula_view_);
+ }
- layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
layout->StartRow(0, LAST_ROW);
system_security_settings_link_ = new views::Link();
system_security_settings_link_->SetController(this);
+ if (!chromeos::CrosLibrary::Get()->EnsureLoaded() ||
+ !chromeos::CryptohomeTpmIsEnabled()) {
+ system_security_settings_link_->SetEnabled(false);
+ // TODO(glotov): add tooltip with description.
+ }
layout->AddView(system_security_settings_link_);
- cancel_button_ = new views::NativeButton(this, std::wstring());
- cancel_button_->SetEnabled(false);
- layout->AddView(cancel_button_);
+ back_button_ = new views::NativeButton(this, std::wstring());
+ layout->AddView(back_button_);
continue_button_ = new views::NativeButton(this, std::wstring());
layout->AddView(continue_button_);
@@ -158,28 +313,36 @@ void EulaView::Init() {
}
void EulaView::UpdateLocalizedStrings() {
- google_eula_text_->SetText(WideToUTF16(kFakeGoogleEula) +
- WideToUTF16(kLoremIpsum) +
- WideToUTF16(kLoremIpsum));
- oem_eula_text_->SetText(WideToUTF16(kFakeOemEula) +
- WideToUTF16(kLoremIpsum) +
- WideToUTF16(kLoremIpsum));
+ // Load Google EULA and its title.
+ LoadEulaView(google_eula_view_, google_eula_label_, GURL(kGoogleEulaUrl));
+
+ // Load OEM EULA and its title.
+ if (!oem_eula_page_.is_empty())
+ LoadEulaView(oem_eula_view_, oem_eula_label_, oem_eula_page_);
+
+ // Set tooltip for usage statistics checkbox if the metric is unmanaged.
+ if (!usage_statistics_checkbox_->IsEnabled()) {
+ usage_statistics_checkbox_->SetTooltipText(
+ l10n_util::GetString(IDS_OPTION_DISABLED_BY_POLICY));
+ }
+
+ // Load other labels from resources.
usage_statistics_checkbox_->SetLabel(
l10n_util::GetString(IDS_EULA_CHECKBOX_ENABLE_LOGGING));
learn_more_link_->SetText(
l10n_util::GetString(IDS_LEARN_MORE));
system_security_settings_link_->SetText(
- l10n_util::GetString(IDS_EULA_SYSTEM_SECURITY_SETTINGS_LINK));
+ l10n_util::GetString(IDS_EULA_SYSTEM_SECURITY_SETTING));
continue_button_->SetLabel(
l10n_util::GetString(IDS_EULA_ACCEPT_AND_CONTINUE_BUTTON));
- cancel_button_->SetLabel(
- l10n_util::GetString(IDS_CANCEL));
+ back_button_->SetLabel(
+ l10n_util::GetString(IDS_ACCNAME_BACK));
}
////////////////////////////////////////////////////////////////////////////////
-// views::View: implementation:
+// EulaView, protected, views::View implementation:
-void EulaView::LocaleChanged() {
+void EulaView::OnLocaleChanged() {
UpdateLocalizedStrings();
Layout();
}
@@ -190,19 +353,114 @@ void EulaView::LocaleChanged() {
void EulaView::ButtonPressed(views::Button* sender, const views::Event& event) {
if (sender == continue_button_) {
if (usage_statistics_checkbox_) {
- GoogleUpdateSettings::SetCollectStatsConsent(
- usage_statistics_checkbox_->checked());
+ bool enable_reporting = usage_statistics_checkbox_->checked();
+ enable_reporting =
+ OptionsUtil::ResolveMetricsReportingEnabled(enable_reporting);
+#if defined(USE_LINUX_BREAKPAD)
+ if (enable_reporting)
+ InitCrashReporter();
+#endif
}
observer_->OnExit(ScreenObserver::EULA_ACCEPTED);
+ } else if (sender == back_button_) {
+ observer_->OnExit(ScreenObserver::EULA_BACK);
}
- // TODO(glotov): handle cancel button.
}
////////////////////////////////////////////////////////////////////////////////
// views::LinkController implementation:
void EulaView::LinkActivated(views::Link* source, int event_flags) {
- // TODO(glotov): handle link clicks.
+ if (source == learn_more_link_) {
+ if (!help_app_.get())
+ help_app_.reset(new HelpAppLauncher(GetNativeWindow()));
+ help_app_->ShowHelpTopic(HelpAppLauncher::HELP_STATS_USAGE);
+ } else if (source == system_security_settings_link_) {
+ // Pull the password from TPM.
+ std::string password;
+ if (!chromeos::CrosLibrary::Get()->EnsureLoaded()) {
+ LOG(ERROR) << "Cros library not loaded. "
+ << "We must have disabled the link that led here.";
+ return;
+ } else if (chromeos::CryptohomeTpmIsReady() &&
+ chromeos::CryptohomeTpmGetPassword(&password)) {
+ TpmInfoView* view = new TpmInfoView(ASCIIToWide(password));
+ view->Init();
+ views::Window* window = views::Window::CreateChromeWindow(
+ GetNativeWindow(), gfx::Rect(), view);
+ window->SetIsAlwaysOnTop(true);
+ window->Show();
+ } else {
+ if (!bubble_)
+ bubble_ = MessageBubble::Show(
+ system_security_settings_link_->GetWidget(),
+ system_security_settings_link_->GetScreenBounds(),
+ BubbleBorder::LEFT_TOP,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
+ l10n_util::GetString(IDS_EULA_TPM_BUSY),
+ std::wstring(), this);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TabContentsDelegate implementation:
+
+// Convenience function. Queries |eula_view| for HTML title and, if it
+// is ready, assigns it to |eula_label| and returns true so the caller
+// view calls Layout().
+static bool PublishTitleIfReady(const TabContents* contents,
+ DOMView* eula_view,
+ views::Label* eula_label) {
+ if (contents != eula_view->tab_contents())
+ return false;
+ eula_label->SetText(UTF16ToWide(eula_view->tab_contents()->GetTitle()));
+ return true;
+}
+
+void EulaView::NavigationStateChanged(const TabContents* contents,
+ unsigned changed_flags) {
+ if (changed_flags & TabContents::INVALIDATE_TITLE) {
+ if (PublishTitleIfReady(contents, google_eula_view_, google_eula_label_) ||
+ PublishTitleIfReady(contents, oem_eula_view_, oem_eula_label_)) {
+ Layout();
+ }
+ }
+}
+
+void EulaView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
+ views::Widget* widget = GetWidget();
+ if (widget && event.os_event && !event.skip_in_browser)
+ static_cast<views::WidgetGtk*>(widget)->HandleKeyboardEvent(event.os_event);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// EulaView, private:
+
+gfx::NativeWindow EulaView::GetNativeWindow() const {
+ return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
+}
+
+void EulaView::LoadEulaView(DOMView* eula_view,
+ views::Label* eula_label,
+ const GURL& eula_url) {
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ eula_view->Init(profile,
+ SiteInstance::CreateSiteInstanceForURL(profile, eula_url));
+ eula_view->LoadURL(eula_url);
+ eula_view->tab_contents()->set_delegate(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// EulaView, private, views::View implementation:
+
+bool EulaView::OnKeyPressed(const views::KeyEvent&) {
+ // Close message bubble if shown. bubble_ will be set to NULL in callback.
+ if (bubble_) {
+ bubble_->Close();
+ return true;
+ }
+ return false;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/eula_view.h b/chrome/browser/chromeos/login/eula_view.h
index 9e7c112..ca40400 100644
--- a/chrome/browser/chromeos/login/eula_view.h
+++ b/chrome/browser/chromeos/login/eula_view.h
@@ -4,10 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_EULA_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EULA_VIEW_H_
+#pragma once
-#include <string>
-
+#include "base/scoped_ptr.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/view_screen.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "gfx/native_widget_types.h"
#include "views/controls/button/button.h"
#include "views/controls/link.h"
#include "views/view.h"
@@ -18,16 +21,63 @@ class Checkbox;
class Label;
class Link;
class NativeButton;
-class Textfield;
} // namespace views
+class DOMView;
+
namespace chromeos {
+class HelpAppLauncher;
+
+// Delegate for TabContents that will show EULA.
+// Blocks context menu and other actions.
+class EULATabContentsDelegate : public TabContentsDelegate {
+ public:
+ EULATabContentsDelegate() {}
+ virtual ~EULATabContentsDelegate() {}
+
+ protected:
+ // TabContentsDelegate implementation:
+ virtual void OpenURLFromTab(TabContents* source,
+ const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition) {}
+ virtual void NavigationStateChanged(const TabContents* source,
+ unsigned changed_flags) {}
+ virtual void AddNewContents(TabContents* source,
+ TabContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) {}
+ virtual void ActivateContents(TabContents* contents) {}
+ virtual void DeactivateContents(TabContents* contents) {}
+ virtual void LoadingStateChanged(TabContents* source) {}
+ virtual void CloseContents(TabContents* source) {}
+ virtual bool IsPopup(TabContents* source) { return false; }
+ virtual void URLStarredChanged(TabContents* source, bool starred) {}
+ virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
+ virtual bool ShouldAddNavigationToHistory(
+ const history::HistoryAddPageArgs& add_page_args,
+ NavigationType::Type navigation_type) {
+ return false;
+ }
+ virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
+ virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
+ virtual bool HandleContextMenu(const ContextMenuParams& params) {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EULATabContentsDelegate);
+};
+
class EulaView
: public views::View,
public views::ButtonListener,
- public views::LinkController {
+ public views::LinkController,
+ public MessageBubbleDelegate,
+ public EULATabContentsDelegate {
public:
explicit EulaView(chromeos::ScreenObserver* observer);
virtual ~EulaView();
@@ -40,7 +90,7 @@ class EulaView
protected:
// views::View implementation.
- virtual void LocaleChanged();
+ virtual void OnLocaleChanged();
// views::ButtonListener implementation.
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
@@ -49,17 +99,55 @@ class EulaView
void LinkActivated(views::Link* source, int event_flags);
private:
+ // views::View implementation.
+ virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
+ return true; }
+ virtual bool OnKeyPressed(const views::KeyEvent& e);
+
+ // TabContentsDelegate implementation.
+ virtual void NavigationStateChanged(const TabContents* contents,
+ unsigned changed_flags);
+ virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
+
+ // Returns corresponding native window.
+ gfx::NativeWindow GetNativeWindow() const;
+
+ // Loads specified URL to the specified DOMView and updates specified
+ // label with its title.
+ void LoadEulaView(DOMView* eula_view,
+ views::Label* eula_label,
+ const GURL& eula_url);
+
+ // Overridden from views::InfoBubbleDelegate.
+ virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape) { bubble_ = NULL; }
+ virtual bool CloseOnEscape() { return true; }
+ virtual bool FadeInOnShow() { return false; }
+ virtual void OnHelpLinkActivated() {}
+
// Dialog controls.
- views::Textfield* google_eula_text_;
+ views::Label* google_eula_label_;
+ DOMView* google_eula_view_;
views::Checkbox* usage_statistics_checkbox_;
views::Link* learn_more_link_;
- views::Textfield* oem_eula_text_;
+ views::Label* oem_eula_label_;
+ DOMView* oem_eula_view_;
views::Link* system_security_settings_link_;
- views::NativeButton* cancel_button_;
+ views::NativeButton* back_button_;
views::NativeButton* continue_button_;
chromeos::ScreenObserver* observer_;
+ // URL of the OEM EULA page (on disk).
+ GURL oem_eula_page_;
+
+ // Help application used for help dialogs.
+ scoped_ptr<HelpAppLauncher> help_app_;
+
+ // Pointer to shown message bubble. We don't need to delete it because
+ // it will be deleted on bubble closing.
+ MessageBubble* bubble_;
+
DISALLOW_COPY_AND_ASSIGN(EulaView);
};
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 5e6abeb..e8a609d 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -10,25 +10,27 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_thread.h"
+#include "base/values.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/login/authenticator.h"
+#include "chrome/browser/chromeos/cros_settings_provider_user.h"
#include "chrome/browser/chromeos/login/background_view.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/profile_manager.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "gfx/native_widget_types.h"
+#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/screen.h"
#include "views/widget/widget_gtk.h"
@@ -40,20 +42,14 @@ namespace {
// Max number of users we'll show. The true max is the min of this and the
// number of windows that fit on the screen.
-const size_t kMaxUsers = 6;
+const size_t kMaxUsers = 5;
// Used to indicate no user has been selected.
const size_t kNotSelected = -1;
-// ClientLogin response parameters.
-const char kError[] = "Error=";
-const char kCaptchaError[] = "CaptchaRequired";
-const char kCaptchaUrlParam[] = "CaptchaUrl=";
-const char kCaptchaTokenParam[] = "CaptchaToken=";
-const char kParamSuffix[] = "\n";
-
-// URL prefix for CAPTCHA image.
-const char kCaptchaUrlPrefix[] = "http://www.google.com/accounts/";
+// Offset of cursor in first position from edit left side. It's used to position
+// info bubble arrow to cursor.
+const int kCursorOffset = 5;
// Checks if display names are unique. If there are duplicates, enables
// tooltips with full emails to let users distinguish their accounts.
@@ -65,14 +61,30 @@ void EnableTooltipsIfNeeded(const std::vector<UserController*>& controllers) {
controllers[i]->user().GetDisplayName();
++visible_display_names[display_name];
}
- for (size_t i = 0; i + 1 < controllers.size(); ++i) {
+ for (size_t i = 0; i < controllers.size(); ++i) {
const std::string& display_name =
controllers[i]->user().GetDisplayName();
- bool show_tooltip = visible_display_names[display_name] > 1;
+ bool show_tooltip = controllers[i]->is_new_user() ||
+ controllers[i]->is_bwsi() ||
+ visible_display_names[display_name] > 1;
controllers[i]->EnableNameTooltip(show_tooltip);
}
}
+// Returns true if given email is in user whitelist.
+// Note this function is for display purpose only and should use
+// CheckWhitelist op for the real whitelist check.
+bool IsEmailInCachedWhitelist(const std::string& email) {
+ StringValue email_value(email);
+ const ListValue* whitelist = UserCrosSettingsProvider::cached_whitelist();
+ for (ListValue::const_iterator i(whitelist->begin());
+ i != whitelist->end(); ++i) {
+ if ((*i)->Equals(&email_value))
+ return true;
+ }
+ return false;
+}
+
} // namespace
ExistingUserController*
@@ -85,38 +97,66 @@ ExistingUserController::ExistingUserController(
background_window_(NULL),
background_view_(NULL),
selected_view_index_(kNotSelected),
+ num_login_attempts_(0),
bubble_(NULL) {
if (delete_scheduled_instance_)
delete_scheduled_instance_->Delete();
// Caclulate the max number of users from available screen size.
- size_t max_users = kMaxUsers;
- int screen_width = background_bounds.width();
- if (screen_width > 0) {
- max_users = std::max(static_cast<size_t>(2), std::min(kMaxUsers,
- static_cast<size_t>((screen_width - login::kUserImageSize)
- / (UserController::kUnselectedSize +
- UserController::kPadding))));
+ if (UserCrosSettingsProvider::cached_show_users_on_signin()) {
+ size_t max_users = kMaxUsers;
+ int screen_width = background_bounds.width();
+ if (screen_width > 0) {
+ max_users = std::max(static_cast<size_t>(2), std::min(kMaxUsers,
+ static_cast<size_t>((screen_width - login::kUserImageSize)
+ / (UserController::kUnselectedSize +
+ UserController::kPadding))));
+ }
+
+ size_t visible_users_count = std::min(users.size(), max_users - 1);
+ for (size_t i = 0; i < users.size(); ++i) {
+ if (controllers_.size() == visible_users_count)
+ break;
+
+ // TODO(xiyuan): Clean user profile whose email is not in whitelist.
+ if (UserCrosSettingsProvider::cached_allow_guest() ||
+ IsEmailInCachedWhitelist(users[i].email())) {
+ controllers_.push_back(new UserController(this, users[i]));
+ }
+ }
}
- size_t visible_users_count = std::min(users.size(), max_users - 1);
- for (size_t i = 0; i < visible_users_count; ++i)
- controllers_.push_back(new UserController(this, users[i]));
+ if (!controllers_.empty() && UserCrosSettingsProvider::cached_allow_bwsi())
+ controllers_.push_back(new UserController(this, true));
- // Add the view representing the guest user last.
- controllers_.push_back(new UserController(this));
+ // Add the view representing the new user.
+ controllers_.push_back(new UserController(this, false));
}
void ExistingUserController::Init() {
if (!background_window_) {
+ std::string url_string =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kScreenSaverUrl);
+
background_window_ = BackgroundView::CreateWindowContainingView(
background_bounds_,
+ GURL(url_string),
&background_view_);
+
+ if (!WizardController::IsDeviceRegistered()) {
+ background_view_->SetOobeProgressBarVisible(true);
+ background_view_->SetOobeProgress(chromeos::BackgroundView::SIGNIN);
+ }
+
background_window_->Show();
}
+ // If there's only new user pod, show BWSI link on it.
+ bool show_bwsi_link = controllers_.size() == 1;
for (size_t i = 0; i < controllers_.size(); ++i) {
(controllers_[i])->Init(static_cast<int>(i),
- static_cast<int>(controllers_.size()));
+ static_cast<int>(controllers_.size()),
+ show_bwsi_link);
}
EnableTooltipsIfNeeded(controllers_);
@@ -133,6 +173,28 @@ void ExistingUserController::OwnBackground(
DCHECK(!background_window_);
background_window_ = background_widget;
background_view_ = background_view;
+ background_view_->OnOwnerChanged();
+}
+
+void ExistingUserController::LoginNewUser(const std::string& username,
+ const std::string& password) {
+ SelectNewUser();
+ UserController* new_user = controllers_.back();
+ DCHECK(new_user->is_new_user());
+ if (!new_user->is_new_user())
+ return;
+ NewUserView* new_user_view = new_user->new_user_view();
+ new_user_view->SetUsername(username);
+
+ if (password.empty())
+ return;
+
+ new_user_view->SetPassword(password);
+ new_user_view->Login();
+}
+
+void ExistingUserController::SelectNewUser() {
+ SelectUser(controllers_.size() - 1);
}
ExistingUserController::~ExistingUserController() {
@@ -171,33 +233,47 @@ void ExistingUserController::Login(UserController* source,
std::vector<UserController*>::const_iterator i =
std::find(controllers_.begin(), controllers_.end(), source);
DCHECK(i != controllers_.end());
- selected_view_index_ = i - controllers_.begin();
-
- authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
- Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::AuthenticateToLogin,
- profile,
- controllers_[selected_view_index_]->user().email(),
- UTF16ToUTF8(password),
- login_token_,
- login_captcha_));
+
+ if (i == controllers_.begin() + selected_view_index_) {
+ num_login_attempts_++;
+ } else {
+ selected_view_index_ = i - controllers_.begin();
+ num_login_attempts_ = 0;
+ }
// Disable clicking on other windows.
SendSetLoginState(false);
+
+ // Use the same LoginPerformer for subsequent login as it has state
+ // such as CAPTCHA challenge token & corresponding user input.
+ if (!login_performer_.get() || num_login_attempts_ <= 1) {
+ login_performer_.reset(new LoginPerformer(this));
+ }
+ login_performer_->Login(controllers_[selected_view_index_]->user().email(),
+ UTF16ToUTF8(password));
+}
+
+void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
+ ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
+
+ // Reenable userview and use ClearAndEnablePassword to keep username on
+ // screen with the error bubble.
+ controllers_[selected_view_index_]->ClearAndEnablePassword();
+
+ // Reenable clicking on other windows.
+ SendSetLoginState(true);
}
void ExistingUserController::LoginOffTheRecord() {
- authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::LoginOffTheRecord));
+ // Check allow_bwsi in case this call is fired from key accelerator.
+ if (!UserCrosSettingsProvider::cached_allow_bwsi())
+ return;
// Disable clicking on other windows.
SendSetLoginState(false);
+
+ login_performer_.reset(new LoginPerformer(this));
+ login_performer_->LoginOffTheRecord();
}
void ExistingUserController::ClearErrors() {
@@ -213,8 +289,9 @@ void ExistingUserController::OnUserSelected(UserController* source) {
size_t new_selected_index = i - controllers_.begin();
if (new_selected_index != selected_view_index_ &&
selected_view_index_ != kNotSelected) {
- controllers_[selected_view_index_]->ClearAndEnablePassword();
- ClearCaptchaState();
+ controllers_[selected_view_index_]->ClearAndEnableFields();
+ login_performer_.reset(NULL);
+ num_login_attempts_ = 0;
}
selected_view_index_ = new_selected_index;
}
@@ -222,13 +299,15 @@ void ExistingUserController::OnUserSelected(UserController* source) {
void ExistingUserController::ActivateWizard(const std::string& screen_name) {
// WizardController takes care of deleting itself when done.
WizardController* controller = new WizardController();
- controller->Init(screen_name, background_bounds_);
- controller->Show();
// Give the background window to the controller.
controller->OwnBackground(background_window_, background_view_);
background_window_ = NULL;
+ controller->Init(screen_name, background_bounds_);
+ controller->set_start_url(start_url_);
+ controller->Show();
+
// And schedule us for deletion. We delay for a second as the window manager
// is doing an animation with our windows.
DCHECK(!delete_scheduled_instance_);
@@ -242,14 +321,18 @@ void ExistingUserController::RemoveUser(UserController* source) {
UserManager::Get()->RemoveUser(source->user().email());
- // We need to unmap entry windows, the windows will be unmapped in destructor.
controllers_.erase(controllers_.begin() + source->user_index());
- delete source;
EnableTooltipsIfNeeded(controllers_);
+
+ // Update user count before unmapping windows, otherwise window manager won't
+ // be in the right state.
int new_size = static_cast<int>(controllers_.size());
for (int i = 0; i < new_size; ++i)
controllers_[i]->UpdateUserCount(i, new_size);
+
+ // We need to unmap entry windows, the windows will be unmapped in destructor.
+ delete source;
}
void ExistingUserController::SelectUser(int index) {
@@ -261,9 +344,12 @@ void ExistingUserController::SelectUser(int index) {
}
}
-void ExistingUserController::OnLoginFailure(const std::string& error) {
- LOG(INFO) << "OnLoginFailure";
- ClearCaptchaState();
+void ExistingUserController::OnGoIncognitoButton() {
+ LoginOffTheRecord();
+}
+
+void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
+ std::string error = failure.GetErrorString();
// Check networking after trying to login in case user is
// cached locally or the local admin account.
@@ -273,28 +359,25 @@ void ExistingUserController::OnLoginFailure(const std::string& error) {
} else if (!network->Connected()) {
ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
} else {
- std::string error_code = LoginUtils::ExtractClientLoginParam(error,
- kError,
- kParamSuffix);
- std::string captcha_url;
- if (error_code == kCaptchaError)
- captcha_url = LoginUtils::ExtractClientLoginParam(error,
- kCaptchaUrlParam,
- kParamSuffix);
- if (captcha_url.empty()) {
- ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
+ if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
+ failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) {
+ if (!failure.error().captcha().image_url.is_empty()) {
+ CaptchaView* view =
+ new CaptchaView(failure.error().captcha().image_url);
+ view->set_delegate(this);
+ views::Window* window = views::Window::CreateChromeWindow(
+ GetNativeWindow(), gfx::Rect(), view);
+ window->SetIsAlwaysOnTop(true);
+ window->Show();
+ } else {
+ LOG(WARNING) << "No captcha image url was found?";
+ ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
+ }
} else {
- // Save token for next login retry.
- login_token_ = LoginUtils::ExtractClientLoginParam(error,
- kCaptchaTokenParam,
- kParamSuffix);
- CaptchaView* view =
- new CaptchaView(GURL(kCaptchaUrlPrefix + captcha_url));
- view->set_delegate(this);
- views::Window* window = views::Window::CreateChromeWindow(
- GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
+ if (controllers_[selected_view_index_]->is_new_user())
+ ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
+ else
+ ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
}
}
@@ -305,15 +388,8 @@ void ExistingUserController::OnLoginFailure(const std::string& error) {
}
void ExistingUserController::AppendStartUrlToCmdline() {
- if (start_url_.is_valid()) {
- CommandLine::ForCurrentProcess()->AppendLooseValue(
- UTF8ToWide(start_url_.spec()));
- }
-}
-
-void ExistingUserController::ClearCaptchaState() {
- login_token_.clear();
- login_captcha_.clear();
+ if (start_url_.is_valid())
+ CommandLine::ForCurrentProcess()->AppendArg(start_url_.spec());
}
gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
@@ -325,14 +401,31 @@ void ExistingUserController::ShowError(int error_id,
const std::string& details) {
ClearErrors();
std::wstring error_text = l10n_util::GetString(error_id);
- if (!details.empty())
- error_text += L"\n" + ASCIIToWide(details);
+ // TODO(dpolukhin): show detailed error info. |details| string contains
+ // low level error info that is not localized and even is not user friendly.
+ // For now just ignore it because error_text contains all required information
+ // for end users, developers can see details string in Chrome logs.
+
+ gfx::Rect bounds = controllers_[selected_view_index_]->GetScreenBounds();
+ BubbleBorder::ArrowLocation arrow;
+ if (controllers_[selected_view_index_]->is_new_user()) {
+ arrow = BubbleBorder::LEFT_TOP;
+ } else {
+ // Point info bubble arrow to cursor position (approximately).
+ bounds.set_width(kCursorOffset * 2);
+ arrow = BubbleBorder::BOTTOM_LEFT;
+ }
+ std::wstring help_link;
+ if (num_login_attempts_ > static_cast<size_t>(1))
+ help_link = l10n_util::GetString(IDS_CANT_ACCESS_ACCOUNT_BUTTON);
+
bubble_ = MessageBubble::Show(
controllers_[selected_view_index_]->controls_window(),
- controllers_[selected_view_index_]->GetScreenBounds(),
- BubbleBorder::BOTTOM_LEFT,
+ bounds,
+ arrow,
ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
error_text,
+ help_link,
this);
}
@@ -340,11 +433,14 @@ void ExistingUserController::OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& credentials) {
AppendStartUrlToCmdline();
- if (selected_view_index_ + 1 == controllers_.size()) {
+ if (selected_view_index_ + 1 == controllers_.size() &&
+ !UserManager::Get()->IsKnownUser(username)) {
// For new user login don't launch browser until we pass image screen.
- chromeos::LoginUtils::Get()->EnableBrowserLaunch(false);
+ LoginUtils::Get()->EnableBrowserLaunch(false);
LoginUtils::Get()->CompleteLogin(username, credentials);
- ActivateWizard(WizardController::kUserImageScreenName);
+ ActivateWizard(WizardController::IsDeviceRegistered() ?
+ WizardController::kUserImageScreenName :
+ WizardController::kRegistrationScreenName);
} else {
// Hide the login windows now.
WmIpc::Message message(WM_IPC_MESSAGE_WM_HIDE_LOGIN);
@@ -358,23 +454,22 @@ void ExistingUserController::OnLoginSuccess(const std::string& username,
}
void ExistingUserController::OnOffTheRecordLoginSuccess() {
- AppendStartUrlToCmdline();
- LoginUtils::Get()->CompleteOffTheRecordLogin();
+ if (WizardController::IsDeviceRegistered()) {
+ LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
+ } else {
+ // Postpone CompleteOffTheRecordLogin until registration completion.
+ ActivateWizard(WizardController::kRegistrationScreenName);
+ }
}
void ExistingUserController::OnPasswordChangeDetected(
const GaiaAuthConsumer::ClientLoginResult& credentials) {
// When signing in as a "New user" always remove old cryptohome.
if (selected_view_index_ == controllers_.size() - 1) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::ResyncEncryptedData,
- credentials));
+ login_performer_->ResyncEncryptedData();
return;
}
- cached_credentials_ = credentials;
PasswordChangedView* view = new PasswordChangedView(this);
views::Window* window = views::Window::CreateChromeWindow(GetNativeWindow(),
gfx::Rect(),
@@ -383,28 +478,38 @@ void ExistingUserController::OnPasswordChangeDetected(
window->Show();
}
+void ExistingUserController::OnHelpLinkActivated() {
+ DCHECK(login_performer_->error().state() != GoogleServiceAuthError::NONE);
+ if (!help_app_.get())
+ help_app_.reset(new HelpAppLauncher(GetNativeWindow()));
+ switch (login_performer_->error().state()) {
+ case(GoogleServiceAuthError::CONNECTION_FAILED):
+ help_app_->ShowHelpTopic(
+ HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE);
+ break;
+ case(GoogleServiceAuthError::ACCOUNT_DISABLED):
+ help_app_->ShowHelpTopic(
+ HelpAppLauncher::HELP_ACCOUNT_DISABLED);
+ break;
+ default:
+ help_app_->ShowHelpTopic(login_performer_->login_timed_out() ?
+ HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
+ HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
+ break;
+ }
+}
+
void ExistingUserController::OnCaptchaEntered(const std::string& captcha) {
- login_captcha_ = captcha;
+ login_performer_->set_captcha(captcha);
}
void ExistingUserController::RecoverEncryptedData(
const std::string& old_password) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::RecoverEncryptedData,
- old_password,
- cached_credentials_));
- cached_credentials_ = GaiaAuthConsumer::ClientLoginResult();
+ login_performer_->RecoverEncryptedData(old_password);
}
void ExistingUserController::ResyncEncryptedData() {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::ResyncEncryptedData,
- cached_credentials_));
- cached_credentials_ = GaiaAuthConsumer::ClientLoginResult();
+ login_performer_->ResyncEncryptedData();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index 856f7ca..6d97740 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -4,34 +4,33 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_EXISTING_USER_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EXISTING_USER_CONTROLLER_H_
+#pragma once
#include <string>
#include <vector>
-#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
#include "base/task.h"
#include "base/timer.h"
+#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/captcha_view.h"
-#include "chrome/browser/chromeos/login/login_status_consumer.h"
+#include "chrome/browser/chromeos/login/login_performer.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/password_changed_view.h"
-#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/user_controller.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/wm_message_listener.h"
-#include "chrome/browser/views/info_bubble.h"
-#include "chrome/common/net/gaia/gaia_auth_consumer.h"
#include "gfx/size.h"
namespace chromeos {
-class Authenticator;
-class BackgroundView;
+class HelpAppLauncher;
class MessageBubble;
// ExistingUserController is used to handle login when someone has already
// logged into the machine. When Init is invoked a UserController is created for
-// each of the Users's in the UserManager (including one for guest), and the
-// window manager is then told to show the windows. If the user clicks on the
-// guest entry the WizardWindow is swapped in.
+// each of the Users's in the UserManager (including one for new user and
+// one for BWSI login), and the window manager is then told to show the windows.
//
// To use ExistingUserController create an instance of it and invoke Init.
//
@@ -39,8 +38,9 @@ class MessageBubble;
// the user logs in (or chooses to see other settings).
class ExistingUserController : public WmMessageListener::Observer,
public UserController::Delegate,
- public LoginStatusConsumer,
- public InfoBubbleDelegate,
+ public BackgroundView::Delegate,
+ public LoginPerformer::Delegate,
+ public MessageBubbleDelegate,
public CaptchaView::Delegate,
public PasswordChangedView::Delegate {
public:
@@ -56,6 +56,13 @@ class ExistingUserController : public WmMessageListener::Observer,
void OwnBackground(views::Widget* background_widget,
chromeos::BackgroundView* background_view);
+ // Tries to login from new user pod with given user login and password.
+ // Called after creating new account.
+ void LoginNewUser(const std::string& username, const std::string& password);
+
+ // Selects new user pod.
+ void SelectNewUser();
+
private:
friend class DeleteTask<ExistingUserController>;
@@ -78,13 +85,17 @@ class ExistingUserController : public WmMessageListener::Observer,
virtual void AddStartUrl(const GURL& start_url) { start_url_ = start_url; }
virtual void SelectUser(int index);
- // LoginStatusConsumer:
- virtual void OnLoginFailure(const std::string& error);
+ // BackgroundView::Delegate
+ virtual void OnGoIncognitoButton();
+
+ // LoginPerformer::Delegate implementation:
+ virtual void OnLoginFailure(const LoginFailure& error);
virtual void OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& credentials);
virtual void OnOffTheRecordLoginSuccess();
virtual void OnPasswordChangeDetected(
const GaiaAuthConsumer::ClientLoginResult& credentials);
+ virtual void WhiteListCheckFailed(const std::string& email);
// Overridden from views::InfoBubbleDelegate.
virtual void InfoBubbleClosing(InfoBubble* info_bubble,
@@ -93,6 +104,7 @@ class ExistingUserController : public WmMessageListener::Observer,
}
virtual bool CloseOnEscape() { return true; }
virtual bool FadeInOnShow() { return false; }
+ virtual void OnHelpLinkActivated();
// CaptchaView::Delegate:
virtual void OnCaptchaEntered(const std::string& captcha);
@@ -104,9 +116,6 @@ class ExistingUserController : public WmMessageListener::Observer,
// Adds start url to command line.
void AppendStartUrlToCmdline();
- // Clears existing captcha state;
- void ClearCaptchaState();
-
// Returns corresponding native window.
gfx::NativeWindow GetNativeWindow() const;
@@ -128,12 +137,16 @@ class ExistingUserController : public WmMessageListener::Observer,
// The set of UserControllers.
std::vector<UserController*> controllers_;
- // Used for logging in.
- scoped_refptr<Authenticator> authenticator_;
+ // Used to execute login operations.
+ scoped_ptr<LoginPerformer> login_performer_;
// Index of selected view (user).
size_t selected_view_index_;
+ // Number of login attempts. Used to show help link when > 1 unsuccessful
+ // logins for the same user.
+ size_t num_login_attempts_;
+
// See comment in ProcessWmMessage.
base::OneShotTimer<ExistingUserController> delete_timer_;
@@ -145,17 +158,11 @@ class ExistingUserController : public WmMessageListener::Observer,
// it will be deleted on bubble closing.
MessageBubble* bubble_;
- // Token representing the specific CAPTCHA challenge.
- std::string login_token_;
-
- // String entered by the user as an answer to a CAPTCHA challenge.
- std::string login_captcha_;
-
// URL that will be opened on browser startup.
GURL start_url_;
- // Cached credentials data when password change is detected.
- GaiaAuthConsumer::ClientLoginResult cached_credentials_;
+ // Help application used for help dialogs.
+ scoped_ptr<HelpAppLauncher> help_app_;
DISALLOW_COPY_AND_ASSIGN(ExistingUserController);
};
diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc
index 94361be..f6e53b4 100644
--- a/chrome/browser/chromeos/login/google_authenticator.cc
+++ b/chrome/browser/chromeos/login/google_authenticator.cc
@@ -22,10 +22,12 @@
#include "chrome/browser/chromeos/login/auth_response_handler.h"
#include "chrome/browser/chromeos/login/authentication_notification_details.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
+#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/net/gaia/gaia_authenticator2.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_service.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -45,7 +47,7 @@ namespace chromeos {
const char GoogleAuthenticator::kLocalaccountFile[] = "localaccount";
// static
-const int GoogleAuthenticator::kClientLoginTimeoutMs = 5000;
+const int GoogleAuthenticator::kClientLoginTimeoutMs = 10000;
// static
const int GoogleAuthenticator::kLocalaccountRetryIntervalMs = 20;
@@ -57,21 +59,32 @@ GoogleAuthenticator::GoogleAuthenticator(LoginStatusConsumer* consumer)
try_again_(true),
checked_for_localaccount_(false) {
CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded());
+ // If not already owned, this is a no-op. If it is, this loads the owner's
+ // public key off of disk.
+ OwnershipService::GetSharedInstance()->StartLoadOwnerKeyAttempt();
}
GoogleAuthenticator::~GoogleAuthenticator() {}
void GoogleAuthenticator::CancelClientLogin() {
if (gaia_authenticator_->HasPendingFetch()) {
+ LOG(INFO) << "Canceling ClientLogin attempt.";
gaia_authenticator_->CancelRequest();
- OnLoginFailure("Login has timed out; please try again!");
+
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &GoogleAuthenticator::LoadLocalaccount,
+ std::string(kLocalaccountFile)));
+
+ CheckOffline(LoginFailure(LoginFailure::LOGIN_TIMED_OUT));
}
}
void GoogleAuthenticator::TryClientLogin() {
gaia_authenticator_->StartClientLogin(username_,
password_,
- GaiaAuthenticator2::kContactsService,
+ GaiaConstants::kContactsService,
login_token_,
login_captcha_);
ChromeThread::PostDelayedTask(
@@ -114,7 +127,7 @@ bool GoogleAuthenticator::AuthenticateToLogin(
gaia_authenticator_.reset(
new GaiaAuthenticator2(this,
- GaiaAuthenticator2::kChromeOSSource,
+ GaiaConstants::kChromeOSSource,
profile->GetRequestContext()));
// Will be used for retries.
PrepareClientLoginAttempt(password, login_token, login_captcha);
@@ -139,7 +152,7 @@ bool GoogleAuthenticator::AuthenticateToUnlock(const std::string& username,
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(this, &GoogleAuthenticator::CheckOffline,
- std::string("unlock failed")));
+ LoginFailure(LoginFailure::UNLOCK_FAILED)));
}
return true;
}
@@ -155,8 +168,9 @@ void GoogleAuthenticator::LoginOffTheRecord() {
Details<AuthenticationNotificationDetails>(&details));
consumer_->OnOffTheRecordLoginSuccess();
} else {
- LOG(ERROR) << "Could not mount tmpfs cryptohome: " << mount_error;
- consumer_->OnLoginFailure("Could not mount tmpfs cryptohome");
+ LOG(ERROR) << "Could not mount tmpfs: " << mount_error;
+ consumer_->OnLoginFailure(
+ LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS));
}
}
@@ -174,9 +188,9 @@ void GoogleAuthenticator::OnClientLoginSuccess(
}
void GoogleAuthenticator::OnClientLoginFailure(
- const GaiaAuthConsumer::GaiaAuthError& error) {
+ const GoogleServiceAuthError& error) {
- if (error.code == GaiaAuthConsumer::REQUEST_CANCELED) {
+ if (error.state() == GoogleServiceAuthError::REQUEST_CANCELED) {
if (try_again_) {
try_again_ = false;
LOG(ERROR) << "Login attempt canceled!?!? Trying again.";
@@ -188,7 +202,7 @@ void GoogleAuthenticator::OnClientLoginFailure(
ClearClientLoginAttempt();
- if (error.code == GaiaAuthConsumer::TWO_FACTOR) {
+ if (error.state() == GoogleServiceAuthError::TWO_FACTOR) {
LOG(WARNING) << "Two factor authenticated. Sync will not work.";
OnClientLoginSuccess(GaiaAuthConsumer::ClientLoginResult());
return;
@@ -200,12 +214,14 @@ void GoogleAuthenticator::OnClientLoginFailure(
&GoogleAuthenticator::LoadLocalaccount,
std::string(kLocalaccountFile)));
- if (error.code == GaiaAuthConsumer::NETWORK_ERROR) {
+ LoginFailure failure_details = LoginFailure::FromNetworkAuthFailure(error);
+
+ if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
// The fetch failed for network reasons, try offline login.
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(this, &GoogleAuthenticator::CheckOffline,
- net::ErrorToString(error.network_error)));
+ failure_details));
return;
}
@@ -214,7 +230,7 @@ void GoogleAuthenticator::OnClientLoginFailure(
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(this,
&GoogleAuthenticator::CheckLocalaccount,
- error.data));
+ failure_details));
}
void GoogleAuthenticator::OnLoginSuccess(
@@ -237,11 +253,11 @@ void GoogleAuthenticator::OnLoginSuccess(
mount_error == chromeos::kCryptohomeMountErrorKeyFailure) {
consumer_->OnPasswordChangeDetected(credentials);
} else {
- OnLoginFailure("Could not mount cryptohome");
+ OnLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME));
}
}
-void GoogleAuthenticator::CheckOffline(const std::string& error) {
+void GoogleAuthenticator::CheckOffline(const LoginFailure& error) {
LOG(INFO) << "Attempting offline login";
if (CrosLibrary::Get()->GetCryptohomeLibrary()->CheckKey(
username_.c_str(),
@@ -255,7 +271,7 @@ void GoogleAuthenticator::CheckOffline(const std::string& error) {
}
}
-void GoogleAuthenticator::CheckLocalaccount(const std::string& error) {
+void GoogleAuthenticator::CheckLocalaccount(const LoginFailure& error) {
{
AutoLock for_this_block(localaccount_lock_);
LOG(INFO) << "Checking localaccount";
@@ -271,25 +287,30 @@ void GoogleAuthenticator::CheckLocalaccount(const std::string& error) {
}
}
int mount_error = chromeos::kCryptohomeMountErrorNone;
- if (!localaccount_.empty() && localaccount_ == username_ &&
- CrosLibrary::Get()->GetCryptohomeLibrary()->MountForBwsi(&mount_error)) {
- LOG(WARNING) << "Logging in with localaccount: " << localaccount_;
- consumer_->OnLoginSuccess(username_, GaiaAuthConsumer::ClientLoginResult());
+ if (!localaccount_.empty() && localaccount_ == username_) {
+ if (CrosLibrary::Get()->GetCryptohomeLibrary()->MountForBwsi(
+ &mount_error)) {
+ LOG(WARNING) << "Logging in with localaccount: " << localaccount_;
+ consumer_->OnLoginSuccess(username_,
+ GaiaAuthConsumer::ClientLoginResult());
+ } else {
+ LOG(ERROR) << "Could not mount tmpfs for local account: " << mount_error;
+ OnLoginFailure(
+ LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS));
+ }
} else {
OnLoginFailure(error);
}
}
-void GoogleAuthenticator::OnLoginFailure(const std::string& error) {
+void GoogleAuthenticator::OnLoginFailure(const LoginFailure& error) {
// Send notification of failure
AuthenticationNotificationDetails details(false);
NotificationService::current()->Notify(
NotificationType::LOGIN_AUTHENTICATION,
NotificationService::AllSources(),
Details<AuthenticationNotificationDetails>(&details));
- LOG(WARNING) << "Login failed: " << error;
- // TODO(cmasone): what can we do to expose these OS/server-side error strings
- // in an internationalizable way?
+ LOG(WARNING) << "Login failed: " << error.GetErrorString();
consumer_->OnLoginFailure(error);
}
@@ -313,7 +334,7 @@ void GoogleAuthenticator::ResyncEncryptedData(
if (CrosLibrary::Get()->GetCryptohomeLibrary()->Remove(username_)) {
OnLoginSuccess(credentials);
} else {
- OnLoginFailure("Could not destroy your old data!");
+ OnLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED));
}
}
@@ -413,19 +434,4 @@ bool GoogleAuthenticator::BinaryToHex(const std::vector<unsigned char>& binary,
return true;
}
-// static
-std::string GoogleAuthenticator::Canonicalize(
- const std::string& email_address) {
- std::vector<std::string> parts;
- char at = '@';
- SplitString(email_address, at, &parts);
- DCHECK_EQ(parts.size(), 2U) << "email_address should have only one @";
- RemoveChars(parts[0], ".", &parts[0]);
- if (parts[0].find('+') != std::string::npos)
- parts[0].erase(parts[0].find('+'));
- std::string new_email = StringToLowerASCII(JoinString(parts, at));
- LOG(INFO) << "Canonicalized " << email_address << " to " << new_email;
- return new_email;
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h
index 2fae711..7c71952 100644
--- a/chrome/browser/chromeos/login/google_authenticator.h
+++ b/chrome/browser/chromeos/login/google_authenticator.h
@@ -4,15 +4,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_GOOGLE_AUTHENTICATOR_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_GOOGLE_AUTHENTICATOR_H_
+#pragma once
#include <string>
#include <vector>
#include "base/basictypes.h"
-#include "base/file_path.h"
#include "base/gtest_prod_util.h"
-#include "base/ref_counted.h"
-#include "base/sha2.h"
+#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
@@ -23,6 +22,8 @@
class Lock;
class Profile;
class GaiaAuthenticator2;
+class GoogleServiceAuthError;
+class LoginFailure;
namespace chromeos {
@@ -30,7 +31,6 @@ class GoogleAuthenticatorTest;
class LoginStatusConsumer;
class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer {
-
public:
explicit GoogleAuthenticator(LoginStatusConsumer* consumer);
virtual ~GoogleAuthenticator();
@@ -74,9 +74,9 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer {
// These methods must be called on the UI thread, as they make DBus calls
// and also call back to the login UI.
void OnLoginSuccess(const GaiaAuthConsumer::ClientLoginResult& credentials);
- void CheckOffline(const std::string& error);
- void CheckLocalaccount(const std::string& error);
- void OnLoginFailure(const std::string& error);
+ void CheckOffline(const LoginFailure& error);
+ void CheckLocalaccount(const LoginFailure& error);
+ void OnLoginFailure(const LoginFailure& error);
// Call these methods on the UI thread.
void RecoverEncryptedData(
@@ -85,15 +85,9 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer {
void ResyncEncryptedData(
const GaiaAuthConsumer::ClientLoginResult& credentials);
- // Perform basic canonicalization of |email_address|, taking into account
- // that gmail does not consider '.' or caps inside a username to matter.
- // For example, c.masone@gmail.com == cMaSone@gmail.com, per
- // http://mail.google.com/support/bin/answer.py?hl=en&ctx=mail&answer=10313#
- static std::string Canonicalize(const std::string& email_address);
-
// Callbacks from GaiaAuthenticator2
virtual void OnClientLoginFailure(
- const GaiaAuthConsumer::GaiaAuthError& error);
+ const GoogleServiceAuthError& error);
virtual void OnClientLoginSuccess(
const GaiaAuthConsumer::ClientLoginResult& credentials);
diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
index 3789feb..6762f88 100644
--- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/chromeos/login/google_authenticator.h"
+
#include <string>
#include <vector>
@@ -9,16 +11,16 @@
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
-#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
#include "chrome/browser/chromeos/cros/mock_library_loader.h"
#include "chrome/browser/chromeos/login/client_login_response_handler.h"
-#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/issue_response_handler.h"
#include "chrome/browser/chromeos/login/mock_auth_response_handler.h"
+#include "chrome/browser/chromeos/login/mock_url_fetchers.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h"
#include "chrome/common/net/url_fetcher.h"
@@ -43,7 +45,7 @@ class MockConsumer : public LoginStatusConsumer {
public:
MockConsumer() {}
~MockConsumer() {}
- MOCK_METHOD1(OnLoginFailure, void(const std::string& error));
+ MOCK_METHOD1(OnLoginFailure, void(const LoginFailure& error));
MOCK_METHOD2(OnLoginSuccess, void(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& result));
MOCK_METHOD0(OnOffTheRecordLoginSuccess, void(void));
@@ -133,6 +135,14 @@ class GoogleAuthenticatorTest : public ::testing::Test {
auth->SetLocalaccount("");
}
+ void CancelLogin(GoogleAuthenticator* auth) {
+ ChromeThread::PostTask(
+ ChromeThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(auth,
+ &GoogleAuthenticator::CancelClientLogin));
+ }
+
unsigned char fake_hash_[32];
std::string hash_ascii_;
std::string username_;
@@ -162,51 +172,6 @@ TEST_F(GoogleAuthenticatorTest, SaltToAscii) {
EXPECT_EQ("0a010000000000a0", auth->SaltAsAscii());
}
-TEST_F(GoogleAuthenticatorTest, EmailAddressNoOp) {
- const char lower_case[] = "user@what.com";
- EXPECT_EQ(lower_case, GoogleAuthenticator::Canonicalize(lower_case));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreCaps) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("user@what.com"),
- GoogleAuthenticator::Canonicalize("UsEr@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreDomainCaps) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("user@what.com"),
- GoogleAuthenticator::Canonicalize("UsEr@what.COM"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreOneUsernameDot) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("us.er@what.com"),
- GoogleAuthenticator::Canonicalize("UsEr@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreManyUsernameDots) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("u.ser@what.com"),
- GoogleAuthenticator::Canonicalize("Us.E.r@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreConsecutiveUsernameDots) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("use.r@what.com"),
- GoogleAuthenticator::Canonicalize("Us....E.r@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressDifferentOnesRejected) {
- EXPECT_NE(GoogleAuthenticator::Canonicalize("who@what.com"),
- GoogleAuthenticator::Canonicalize("Us....E.r@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnorePlusSuffix) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("user+cc@what.com"),
- GoogleAuthenticator::Canonicalize("user@what.com"));
-}
-
-TEST_F(GoogleAuthenticatorTest, EmailAddressIgnoreMultiPlusSuffix) {
- EXPECT_EQ(GoogleAuthenticator::Canonicalize("user+cc+bcc@what.com"),
- GoogleAuthenticator::Canonicalize("user@what.com"));
-}
-
TEST_F(GoogleAuthenticatorTest, ReadLocalaccount) {
FilePath tmp_file_path = FakeLocalaccountFile(bytes_as_ascii_);
@@ -218,7 +183,8 @@ TEST_F(GoogleAuthenticatorTest, ReadLocalaccount) {
TEST_F(GoogleAuthenticatorTest, ReadLocalaccountTrailingWS) {
FilePath tmp_file_path =
- FakeLocalaccountFile(StringPrintf("%s\n", bytes_as_ascii_.c_str()));
+ FakeLocalaccountFile(base::StringPrintf("%s\n",
+ bytes_as_ascii_.c_str()));
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL));
ReadLocalaccountFile(auth.get(), tmp_file_path.BaseName().value());
@@ -352,15 +318,14 @@ TEST_F(GoogleAuthenticatorTest, LoginNetFailure) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- int error_no = net::ERR_CONNECTION_RESET;
- std::string data(net::ErrorToString(error_no));
+ GoogleServiceAuthError error =
+ GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET);
- GaiaAuthConsumer::GaiaAuthError error;
- error.code = GaiaAuthConsumer::NETWORK_ERROR;
- error.network_error = error_no;
+ LoginFailure failure =
+ LoginFailure::FromNetworkAuthFailure(error);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginFailure(data))
+ EXPECT_CALL(consumer, OnLoginFailure(failure))
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_))
@@ -377,8 +342,8 @@ TEST_F(GoogleAuthenticatorTest, LoginDenied) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- GaiaAuthConsumer::GaiaAuthError error;
- error.code = GaiaAuthConsumer::PERMISSION_DENIED;
+ GoogleServiceAuthError client_error(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
MockConsumer consumer;
EXPECT_CALL(consumer, OnLoginFailure(_))
@@ -387,7 +352,61 @@ TEST_F(GoogleAuthenticatorTest, LoginDenied) {
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
PrepForLogin(auth.get());
- auth->OnClientLoginFailure(error);
+ auth->OnClientLoginFailure(client_error);
+ message_loop.RunAllPending();
+}
+
+TEST_F(GoogleAuthenticatorTest, LoginAccountDisabled) {
+ MessageLoopForUI message_loop;
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+
+ GoogleServiceAuthError client_error(
+ GoogleServiceAuthError::ACCOUNT_DISABLED);
+
+ MockConsumer consumer;
+ EXPECT_CALL(consumer, OnLoginFailure(_))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
+ PrepForLogin(auth.get());
+ auth->OnClientLoginFailure(client_error);
+ message_loop.RunAllPending();
+}
+
+TEST_F(GoogleAuthenticatorTest, LoginAccountDeleted) {
+ MessageLoopForUI message_loop;
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+
+ GoogleServiceAuthError client_error(
+ GoogleServiceAuthError::ACCOUNT_DELETED);
+
+ MockConsumer consumer;
+ EXPECT_CALL(consumer, OnLoginFailure(_))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
+ PrepForLogin(auth.get());
+ auth->OnClientLoginFailure(client_error);
+ message_loop.RunAllPending();
+}
+
+TEST_F(GoogleAuthenticatorTest, LoginServiceUnavailable) {
+ MessageLoopForUI message_loop;
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+
+ GoogleServiceAuthError client_error(
+ GoogleServiceAuthError::SERVICE_UNAVAILABLE);
+
+ MockConsumer consumer;
+ EXPECT_CALL(consumer, OnLoginFailure(_))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
+ PrepForLogin(auth.get());
+ auth->OnClientLoginFailure(client_error);
message_loop.RunAllPending();
}
@@ -395,22 +414,22 @@ TEST_F(GoogleAuthenticatorTest, CaptchaErrorOutputted) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- // TODO(chron): Swap out this captcha passing for actual captcha parsing.
- GaiaAuthConsumer::GaiaAuthError error;
- error.code = GaiaAuthConsumer::PERMISSION_DENIED;
- error.data = "Url=http://www.google.com/login/captcha\n"
- "Error=CaptchaRequired\n"
- "CaptchaToken=DQAAAGgA...dkI1LK9\n"
- "CaptchaUrl=Captcha?ctoken=...\n";
+ GoogleServiceAuthError auth_error =
+ GoogleServiceAuthError::FromCaptchaChallenge(
+ "CCTOKEN",
+ GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"),
+ GURL("http://www.google.com/login/captcha"));
+
+ LoginFailure failure = LoginFailure::FromNetworkAuthFailure(auth_error);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginFailure(error.data))
+ EXPECT_CALL(consumer, OnLoginFailure(failure))
.Times(1)
.RetiresOnSaturation();
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
PrepForLogin(auth.get());
- auth->OnClientLoginFailure(error);
+ auth->OnClientLoginFailure(auth_error);
message_loop.RunAllPending();
}
@@ -418,9 +437,8 @@ TEST_F(GoogleAuthenticatorTest, OfflineLogin) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- GaiaAuthConsumer::GaiaAuthError error;
- error.code = GaiaAuthConsumer::NETWORK_ERROR;
- error.network_error = net::ERR_CONNECTION_RESET;
+ GoogleServiceAuthError auth_error(
+ GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET));
MockConsumer consumer;
EXPECT_CALL(consumer, OnLoginSuccess(username_, result_))
@@ -435,7 +453,7 @@ TEST_F(GoogleAuthenticatorTest, OfflineLogin) {
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
PrepForLogin(auth.get());
- auth->OnClientLoginFailure(error);
+ auth->OnClientLoginFailure(auth_error);
message_loop.RunAllPending();
}
@@ -473,20 +491,37 @@ TEST_F(GoogleAuthenticatorTest, CheckLocalaccount) {
PrepForLogin(auth.get());
auth->SetLocalaccount(username_);
- auth->CheckLocalaccount(std::string());
+ auth->CheckLocalaccount(LoginFailure(LoginFailure::LOGIN_TIMED_OUT));
}
+namespace {
+
// Compatible with LoginStatusConsumer::OnLoginSuccess()
-static void Quit(const std::string& username,
- const GaiaAuthConsumer::ClientLoginResult& credentials) {
+static void OnSuccessQuit(
+ const std::string& username,
+ const GaiaAuthConsumer::ClientLoginResult& credentials) {
+ MessageLoop::current()->Quit();
+}
+
+static void OnSuccessQuitAndFail(
+ const std::string& username,
+ const GaiaAuthConsumer::ClientLoginResult& credentials) {
+ ADD_FAILURE() << "Login should NOT have succeeded!";
MessageLoop::current()->Quit();
}
+
// Compatible with LoginStatusConsumer::OnLoginFailure()
-static void QuitAndFail(const std::string& error) {
+static void OnFailQuit(const LoginFailure& error) {
+ MessageLoop::current()->Quit();
+}
+
+static void OnFailQuitAndFail(const LoginFailure& error) {
ADD_FAILURE() << "Login should have succeeded!";
MessageLoop::current()->Quit();
}
+} // anonymous namespace
+
TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) {
// This test checks the logic that governs asynchronously reading the
// localaccount name off disk and trying to authenticate against it
@@ -495,17 +530,15 @@ TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) {
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
MockConsumer consumer;
- ON_CALL(consumer, OnLoginSuccess(username_, _))
- .WillByDefault(Invoke(Quit));
EXPECT_CALL(consumer, OnLoginSuccess(username_, _))
- .Times(1)
+ .WillOnce(Invoke(OnSuccessQuit))
.RetiresOnSaturation();
EXPECT_CALL(*mock_library_, MountForBwsi(_))
.WillOnce(Return(true))
.RetiresOnSaturation();
// Enable the test to terminate (and fail), even if the login fails.
ON_CALL(consumer, OnLoginFailure(_))
- .WillByDefault(Invoke(QuitAndFail));
+ .WillByDefault(Invoke(OnFailQuitAndFail));
// Manually prep for login, so that localaccount isn't set for us.
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
@@ -518,7 +551,7 @@ TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) {
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(auth.get(),
&GoogleAuthenticator::CheckLocalaccount,
- std::string("fail")));
+ LoginFailure(LoginFailure::LOGIN_TIMED_OUT)));
message_loop.RunAllPending();
// The foregoing has now rescheduled itself in a few ms because we don't
// yet have the localaccount loaded off disk.
@@ -537,8 +570,6 @@ TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) {
TEST_F(GoogleAuthenticatorTest, FullLogin) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- GURL source(AuthResponseHandler::kTokenAuthUrl);
- URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_));
MockConsumer consumer;
@@ -549,15 +580,13 @@ TEST_F(GoogleAuthenticatorTest, FullLogin) {
.WillOnce(Return(true))
.RetiresOnSaturation();
- ON_CALL(*mock_library_, GetSystemSalt())
- .WillByDefault(Return(salt_v));
EXPECT_CALL(*mock_library_, GetSystemSalt())
- .Times(1)
+ .WillOnce(Return(salt_v))
.RetiresOnSaturation();
TestingProfile profile;
- MockFactory factory;
+ MockFactory<MockFetcher> factory;
URLFetcher::set_factory(&factory);
scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
@@ -568,4 +597,109 @@ TEST_F(GoogleAuthenticatorTest, FullLogin) {
message_loop.RunAllPending();
}
+TEST_F(GoogleAuthenticatorTest, CancelLogin) {
+ MessageLoop message_loop(MessageLoop::TYPE_UI);
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+ chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_));
+
+ MockConsumer consumer;
+ // The expected case.
+ EXPECT_CALL(consumer, OnLoginFailure(_))
+ .WillOnce(Invoke(OnFailQuit))
+ .RetiresOnSaturation();
+
+ // A failure case, but we still want the test to finish gracefully.
+ ON_CALL(consumer, OnLoginSuccess(username_, _))
+ .WillByDefault(Invoke(OnSuccessQuitAndFail));
+
+ // Stuff we expect to happen along the way.
+ EXPECT_CALL(*mock_library_, GetSystemSalt())
+ .WillOnce(Return(salt_v))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_library_, CheckKey(username_, _))
+ .WillOnce(Return(false))
+ .RetiresOnSaturation();
+
+ TestingProfile profile;
+
+ // This is how we inject fake URLFetcher objects, with a factory.
+ // This factory creates fake URLFetchers that Start() a fake fetch attempt
+ // and then come back on the UI thread after a small delay. They expect to
+ // be canceled before they come back, and the test will fail if they are not.
+ MockFactory<ExpectCanceledFetcher> factory;
+ URLFetcher::set_factory(&factory);
+
+ scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
+
+ // For when |auth| tries to load the localaccount file.
+ ChromeThread file_thread(ChromeThread::FILE);
+ file_thread.Start();
+
+ // Start an authentication attempt, which will kick off a URL "fetch" that
+ // we expect to cancel before it completes.
+ auth->AuthenticateToLogin(
+ &profile, username_, hash_ascii_, std::string(), std::string());
+
+ // Post a task to cancel the login attempt.
+ CancelLogin(auth.get());
+
+ URLFetcher::set_factory(NULL);
+
+ // Run the UI thread until we exit it gracefully.
+ message_loop.Run();
+}
+
+TEST_F(GoogleAuthenticatorTest, CancelLoginAlreadyGotLocalaccount) {
+ MessageLoop message_loop(MessageLoop::TYPE_UI);
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+ chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_));
+
+ MockConsumer consumer;
+ // The expected case.
+ EXPECT_CALL(consumer, OnLoginFailure(_))
+ .WillOnce(Invoke(OnFailQuit))
+ .RetiresOnSaturation();
+
+ // A failure case, but we still want the test to finish gracefully.
+ ON_CALL(consumer, OnLoginSuccess(username_, _))
+ .WillByDefault(Invoke(OnSuccessQuitAndFail));
+
+ // Stuff we expect to happen along the way.
+ EXPECT_CALL(*mock_library_, GetSystemSalt())
+ .WillOnce(Return(salt_v))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_library_, CheckKey(username_, _))
+ .WillOnce(Return(false))
+ .RetiresOnSaturation();
+
+ TestingProfile profile;
+
+ // This is how we inject fake URLFetcher objects, with a factory.
+ // This factory creates fake URLFetchers that Start() a fake fetch attempt
+ // and then come back on the UI thread after a small delay. They expect to
+ // be canceled before they come back, and the test will fail if they are not.
+ MockFactory<ExpectCanceledFetcher> factory;
+ URLFetcher::set_factory(&factory);
+
+ scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer));
+
+ // This time, instead of allowing |auth| to go get the localaccount file
+ // itself, we simulate the case where the file is already loaded, which
+ // happens when this isn't the first login since chrome started.
+ ReadLocalaccountFile(auth.get(), "");
+
+ // Start an authentication attempt, which will kick off a URL "fetch" that
+ // we expect to cancel before it completes.
+ auth->AuthenticateToLogin(
+ &profile, username_, hash_ascii_, std::string(), std::string());
+
+ // Post a task to cancel the login attempt.
+ CancelLogin(auth.get());
+
+ URLFetcher::set_factory(NULL);
+
+ // Run the UI thread until we exit it gracefully.
+ message_loop.Run();
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc
index 4ea9ed4..d2da133 100644
--- a/chrome/browser/chromeos/login/helper.cc
+++ b/chrome/browser/chromeos/login/helper.cc
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/chromeos/login/helper.h"
+
#include "app/resource_bundle.h"
+#include "chrome/browser/google/google_util.h"
#include "gfx/canvas_skia.h"
+#include "googleurl/src/gurl.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/controls/throbber.h"
@@ -23,6 +27,9 @@ const int kThrobberStartDelayMs = 500;
const SkColor kBackgroundCenterColor = SkColorSetRGB(41, 50, 67);
const SkColor kBackgroundEdgeColor = SK_ColorBLACK;
+const char kAccountRecoveryHelpUrl[] =
+ "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
+
class BackgroundPainter : public views::Painter {
public:
BackgroundPainter() {}
@@ -87,5 +94,9 @@ gfx::Rect CalculateScreenBounds(const gfx::Size& size) {
return bounds;
}
+GURL GetAccountRecoveryHelpUrl() {
+ return google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl));
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/helper.h b/chrome/browser/chromeos/login/helper.h
index a98d2f2..4e7de2a 100644
--- a/chrome/browser/chromeos/login/helper.h
+++ b/chrome/browser/chromeos/login/helper.h
@@ -6,9 +6,17 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_HELPER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_HELPER_H_
+#pragma once
#include "third_party/skia/include/core/SkColor.h"
+class GURL;
+
+namespace gfx {
+class Rect;
+class Size;
+} // namespace gfx
+
namespace views {
class Painter;
class Throbber;
@@ -30,6 +38,9 @@ views::Painter* CreateBackgroundPainter();
// |size| is not empty. Otherwise the whole monitor is occupied.
gfx::Rect CalculateScreenBounds(const gfx::Size& size);
+// Returns URL used for account recovery.
+GURL GetAccountRecoveryHelpUrl();
+
// Define the constants in |login| namespace to avoid potential
// conflict with other chromeos components.
namespace login {
@@ -41,7 +52,7 @@ enum Command {
};
// Gap between edge and image view, and image view and controls.
-const int kBorderSize = 4;
+const int kBorderSize = 6;
// The size of user image.
const int kUserImageSize = 256;
@@ -52,6 +63,15 @@ const SkColor kBackgroundColor = SK_ColorWHITE;
// Text color on the login controls.
const SkColor kTextColor = SK_ColorWHITE;
+// Default size of the OOBE screen. Includes 10px shadow from each side.
+// See rounded_rect_painter.cc for border definitions.
+const int kWizardScreenWidth = 700;
+const int kWizardScreenHeight = 416;
+
+const int kScreenCornerRadius = 10;
+const int kUserCornerRadius = 5;
+
+
} // namespace login
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/image_decoder.h b/chrome/browser/chromeos/login/image_decoder.h
index fdb9e1c..02ad1ce 100644
--- a/chrome/browser/chromeos/login/image_decoder.h
+++ b/chrome/browser/chromeos/login/image_decoder.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_IMAGE_DECODER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_IMAGE_DECODER_H_
+#pragma once
#include <vector>
diff --git a/chrome/browser/chromeos/login/image_downloader.cc b/chrome/browser/chromeos/login/image_downloader.cc
index dfcd797..367e27e 100644
--- a/chrome/browser/chromeos/login/image_downloader.cc
+++ b/chrome/browser/chromeos/login/image_downloader.cc
@@ -6,6 +6,8 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/profile_manager.h"
@@ -30,7 +32,7 @@ ImageDownloader::ImageDownloader(ImageDecoder::Delegate* delegate,
ProfileManager::GetDefaultProfile()->GetRequestContext());
if (!auth_token.empty()) {
image_fetcher_->set_extra_request_headers(
- StringPrintf(kAuthorizationHeader, auth_token.c_str()));
+ base::StringPrintf(kAuthorizationHeader, auth_token.c_str()));
}
image_fetcher_->Start();
}
diff --git a/chrome/browser/chromeos/login/image_downloader.h b/chrome/browser/chromeos/login/image_downloader.h
index 61d773c..06193bf 100644
--- a/chrome/browser/chromeos/login/image_downloader.h
+++ b/chrome/browser/chromeos/login/image_downloader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_IMAGE_DOWNLOADER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_IMAGE_DOWNLOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/issue_response_handler.cc b/chrome/browser/chromeos/login/issue_response_handler.cc
index bfc1ae2..54abf99 100644
--- a/chrome/browser/chromeos/login/issue_response_handler.cc
+++ b/chrome/browser/chromeos/login/issue_response_handler.cc
@@ -23,9 +23,8 @@ URLFetcher* IssueResponseHandler::Handle(
const std::string& to_process,
URLFetcher::Delegate* catcher) {
LOG(INFO) << "Handling IssueAuthToken response";
- token_url_.assign(StringPrintf("%s%s",
- AuthResponseHandler::kTokenAuthUrl,
- to_process.c_str()));
+ token_url_.assign(base::StringPrintf("%s%s",
+ AuthResponseHandler::kTokenAuthUrl, to_process.c_str()));
URLFetcher* fetcher =
new URLFetcher(GURL(token_url_), URLFetcher::GET, catcher);
fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
diff --git a/chrome/browser/chromeos/login/issue_response_handler.h b/chrome/browser/chromeos/login/issue_response_handler.h
index 4741c80..e724111 100644
--- a/chrome/browser/chromeos/login/issue_response_handler.h
+++ b/chrome/browser/chromeos/login/issue_response_handler.h
@@ -4,10 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_
+#pragma once
#include <string>
-#include "base/logging.h"
+#include "base/basictypes.h"
#include "chrome/browser/chromeos/login/auth_response_handler.h"
class URLRequestContextGetter;
diff --git a/chrome/browser/chromeos/login/language_switch_menu.cc b/chrome/browser/chromeos/login/language_switch_menu.cc
index d93e8fe..5f5d8c6 100644
--- a/chrome/browser/chromeos/login/language_switch_menu.cc
+++ b/chrome/browser/chromeos/login/language_switch_menu.cc
@@ -4,14 +4,15 @@
#include "chrome/browser/chromeos/login/language_switch_menu.h"
-#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "views/widget/widget_gtk.h"
@@ -69,18 +70,9 @@ std::wstring LanguageSwitchMenu::GetCurrentLocaleName() const {
language_list_->GetIndexFromLocale(locale));
};
-// Currently, views::Menu is implemented directly with the Gtk
-// widgets. So we use native gtk callbacks to get its future size.
-int LanguageSwitchMenu::GetFirstLevelMenuWidth() const {
- DCHECK(menu_ != NULL);
- GtkRequisition box_size;
- gtk_widget_size_request(menu_->GetNativeMenu(), &box_size);
- return box_size.width;
-}
-
void LanguageSwitchMenu::SetFirstLevelMenuWidth(int width) {
DCHECK(menu_ != NULL);
- gtk_widget_set_size_request(menu_->GetNativeMenu(), width, -1);
+ menu_->SetMinimumWidth(width);
}
// static
@@ -97,12 +89,13 @@ void LanguageSwitchMenu::SwitchLanguage(const std::string& locale) {
prefs->SavePersistentPrefs();
// Switch the locale.
- ResourceBundle::ReloadSharedInstance(UTF8ToWide(locale));
+ ResourceBundle::ReloadSharedInstance(locale);
// Enable the keyboard layouts that are necessary for the new locale.
- chromeos::input_method::EnableInputMethods(
- locale, chromeos::input_method::kKeyboardLayoutsOnly,
- kHardwareKeyboardLayout);
+ input_method::EnableInputMethods(
+ locale, input_method::kKeyboardLayoutsOnly,
+ CrosLibrary::Get()->GetKeyboardLibrary()->
+ GetHardwareKeyboardLayoutName());
// The following line does not seem to affect locale anyhow. Maybe in
// future..
diff --git a/chrome/browser/chromeos/login/language_switch_menu.h b/chrome/browser/chromeos/login/language_switch_menu.h
index 849d537..a3db06e 100644
--- a/chrome/browser/chromeos/login/language_switch_menu.h
+++ b/chrome/browser/chromeos/login/language_switch_menu.h
@@ -4,16 +4,17 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LANGUAGE_SWITCH_MENU_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_LANGUAGE_SWITCH_MENU_H_
+#pragma once
#include <string>
#include "app/menus/simple_menu_model.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/language_combobox_model.h"
+#include "testing/gtest/include/gtest/gtest_prod.h"
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/view_menu_delegate.h"
#include "views/view.h"
-#include "testing/gtest/include/gtest/gtest_prod.h"
class WizardControllerTest_SwitchLanguage_Test;
@@ -32,8 +33,7 @@ class LanguageSwitchMenu : public views::ViewMenuDelegate,
// Returns current locale name to be placed on the language menu-button.
std::wstring GetCurrentLocaleName() const;
- // Returns original width of the first level menu to be shown when called.
- int GetFirstLevelMenuWidth() const;
+ // Sets the minimum width of the first level menu to be shown.
void SetFirstLevelMenuWidth(int width);
void set_menu_offset(int delta_x, int delta_y) {
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index dd89fb3..85a99ba 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -6,7 +6,6 @@
#include "base/time.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
-#include "chrome/browser/profile_manager.h"
#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
#include "chrome/browser/chromeos/cros/mock_input_method_library.h"
#include "chrome/browser/chromeos/cros/mock_keyboard_library.h"
@@ -14,13 +13,14 @@
#include "chrome/browser/chromeos/cros/mock_network_library.h"
#include "chrome/browser/chromeos/cros/mock_power_library.h"
#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
-#include "chrome/browser/chromeos/cros/mock_synaptics_library.h"
#include "chrome/browser/chromeos/cros/mock_system_library.h"
+#include "chrome/browser/chromeos/cros/mock_touchpad_library.h"
+#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
using ::testing::_;
@@ -50,8 +50,10 @@ class LoginTestBase : public InProcessBrowserTest {
testApi_->SetPowerLibrary(&mock_power_library_, false);
EXPECT_CALL(mock_power_library_, battery_time_to_empty())
.WillRepeatedly((Return(base::TimeDelta::FromMinutes(42))));
+ EXPECT_CALL(mock_power_library_, battery_time_to_full())
+ .WillRepeatedly((Return(base::TimeDelta::FromMinutes(24))));
- testApi_->SetSynapticsLibrary(&mock_synaptics_library_, false);
+ testApi_->SetTouchpadLibrary(&mock_touchpad_library_, false);
testApi_->SetCryptohomeLibrary(&mock_cryptohome_library_, false);
testApi_->SetScreenLockLibrary(&mock_screen_lock_library_, false);
testApi_->SetSystemLibrary(&mock_system_library_, false);
@@ -65,7 +67,7 @@ class LoginTestBase : public InProcessBrowserTest {
NiceMock<MockNetworkLibrary> mock_network_library_;
NiceMock<MockPowerLibrary> mock_power_library_;
NiceMock<MockScreenLockLibrary> mock_screen_lock_library_;
- NiceMock<MockSynapticsLibrary> mock_synaptics_library_;
+ NiceMock<MockTouchpadLibrary> mock_touchpad_library_;
NiceMock<MockSystemLibrary> mock_system_library_;
ImePropertyList ime_properties_;
chromeos::CrosLibrary::TestApi* testApi_;
@@ -81,9 +83,8 @@ class LoginUserTest : public LoginTestBase {
}
virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitchWithValue(
- switches::kLoginUser, "TestUser@gmail.com");
- command_line->AppendSwitchWithValue(switches::kLoginProfile, "user");
+ command_line->AppendSwitchASCII(switches::kLoginUser, "TestUser@gmail.com");
+ command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
command_line->AppendSwitch(switches::kNoFirstRun);
}
};
@@ -96,7 +97,7 @@ class LoginProfileTest : public LoginTestBase {
}
virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitchWithValue(switches::kLoginProfile, "user");
+ command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
command_line->AppendSwitch(switches::kNoFirstRun);
}
};
diff --git a/chrome/browser/chromeos/login/login_html_dialog.cc b/chrome/browser/chromeos/login/login_html_dialog.cc
index a895626..a05c7de 100644
--- a/chrome/browser/chromeos/login/login_html_dialog.cc
+++ b/chrome/browser/chromeos/login/login_html_dialog.cc
@@ -4,18 +4,35 @@
#include "chrome/browser/chromeos/login/login_html_dialog.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/profile_manager.h"
-#include "chrome/browser/views/browser_dialogs.h"
+#include "chrome/browser/views/html_dialog_view.h"
#include "gfx/native_widget_types.h"
+#include "gfx/rect.h"
#include "gfx/size.h"
#include "views/window/window.h"
namespace chromeos {
namespace {
+// Default width/height ratio of screen size.
+const float kDefaultWidthRatio = 0.8;
+const float kDefaultHeightRatio = 0.8;
-const int kDefaultWidth = 800;
-const int kDefaultHeight = 600;
+// Custom HtmlDialogView with disabled context menu.
+class HtmlDialogWithoutContextMenuView : public HtmlDialogView {
+ public:
+ HtmlDialogWithoutContextMenuView(Profile* profile,
+ HtmlDialogUIDelegate* delegate)
+ : HtmlDialogView(profile, delegate) {}
+ virtual ~HtmlDialogWithoutContextMenuView() {}
+
+ // TabContentsDelegate implementation.
+ bool HandleContextMenu(const ContextMenuParams& params) {
+ // Disable context menu.
+ return true;
+ }
+};
} // namespace
@@ -30,6 +47,9 @@ LoginHtmlDialog::LoginHtmlDialog(Delegate* delegate,
parent_window_(parent_window),
title_(title),
url_(url) {
+ gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size(0, 0)));
+ width_ = static_cast<int>(kDefaultWidthRatio * screen_bounds.width());
+ height_ = static_cast<int>(kDefaultHeightRatio * screen_bounds.height());
}
LoginHtmlDialog::~LoginHtmlDialog() {
@@ -37,9 +57,18 @@ LoginHtmlDialog::~LoginHtmlDialog() {
}
void LoginHtmlDialog::Show() {
- browser::ShowHtmlDialogView(parent_window_,
- ProfileManager::GetDefaultProfile(),
- this);
+ HtmlDialogWithoutContextMenuView* html_view =
+ new HtmlDialogWithoutContextMenuView(ProfileManager::GetDefaultProfile(),
+ this);
+ views::Window::CreateChromeWindow(parent_window_, gfx::Rect(), html_view);
+ html_view->InitDialog();
+ html_view->window()->Show();
+}
+
+void LoginHtmlDialog::SetDialogSize(int width, int height) {
+ DCHECK(width >= 0 && height >= 0);
+ width_ = width;
+ height_ = height;
}
///////////////////////////////////////////////////////////////////////////////
@@ -57,7 +86,7 @@ void LoginHtmlDialog::OnCloseContents(TabContents* source,
}
void LoginHtmlDialog::GetDialogSize(gfx::Size* size) const {
- size->SetSize(kDefaultWidth, kDefaultHeight);
+ size->SetSize(width_, height_);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_html_dialog.h b/chrome/browser/chromeos/login/login_html_dialog.h
index 81c6628..367bb56 100644
--- a/chrome/browser/chromeos/login/login_html_dialog.h
+++ b/chrome/browser/chromeos/login/login_html_dialog.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_HTML_DIALOG_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_HTML_DIALOG_H_
+#pragma once
#include <string>
@@ -34,6 +35,11 @@ class LoginHtmlDialog : public HtmlDialogUIDelegate {
// Shows created dialog.
void Show();
+ // Overrides default width/height for dialog.
+ void SetDialogSize(int width, int height);
+
+ void set_url(const GURL& url) { url_ = url; }
+
protected:
// HtmlDialogUIDelegate implementation.
virtual bool IsDialogModal() const { return true; }
@@ -54,6 +60,10 @@ class LoginHtmlDialog : public HtmlDialogUIDelegate {
std::wstring title_;
GURL url_;
+ // Dialog display size.
+ int width_;
+ int height_;
+
DISALLOW_COPY_AND_ASSIGN(LoginHtmlDialog);
};
diff --git a/chrome/browser/chromeos/login/login_screen.cc b/chrome/browser/chromeos/login/login_screen.cc
index 9e1d886..6f34d0e 100644
--- a/chrome/browser/chromeos/login/login_screen.cc
+++ b/chrome/browser/chromeos/login/login_screen.cc
@@ -17,12 +17,14 @@
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/authentication_notification_details.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/notification_service.h"
+#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
namespace chromeos {
@@ -41,7 +43,7 @@ LoginScreen::~LoginScreen() {
}
NewUserView* LoginScreen::AllocateView() {
- return new NewUserView(this, true);
+ return new NewUserView(this, true, true);
}
void LoginScreen::OnLogin(const std::string& username,
@@ -73,7 +75,8 @@ void LoginScreen::ClearErrors() {
bubble_->Close();
}
-void LoginScreen::OnLoginFailure(const std::string& error) {
+void LoginScreen::OnLoginFailure(const LoginFailure& failure) {
+ const std::string error = failure.GetErrorString();
LOG(INFO) << "LoginManagerView: OnLoginFailure() " << error;
NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
@@ -84,7 +87,7 @@ void LoginScreen::OnLoginFailure(const std::string& error) {
} else if (!network->Connected()) {
ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
} else {
- ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
+ ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
}
view()->ClearAndEnablePassword();
@@ -100,28 +103,32 @@ void LoginScreen::OnLoginSuccess(const std::string& username,
void LoginScreen::OnOffTheRecordLoginSuccess() {
delegate()->GetObserver(this)->OnExit(ScreenObserver::LOGIN_GUEST_SELECTED);
- AppendStartUrlToCmdline();
- LoginUtils::Get()->CompleteOffTheRecordLogin();
+}
+
+void LoginScreen::OnHelpLinkActivated() {
+ AddStartUrl(GetAccountRecoveryHelpUrl());
+ OnLoginOffTheRecord();
}
void LoginScreen::AppendStartUrlToCmdline() {
- if (start_url_.is_valid()) {
- CommandLine::ForCurrentProcess()->AppendLooseValue(
- UTF8ToWide(start_url_.spec()));
- }
+ if (start_url_.is_valid())
+ CommandLine::ForCurrentProcess()->AppendArg(start_url_.spec());
}
void LoginScreen::ShowError(int error_id, const std::string& details) {
ClearErrors();
std::wstring error_text = l10n_util::GetString(error_id);
- if (!details.empty())
- error_text += L"\n" + ASCIIToWide(details);
+ // TODO(dpolukhin): show detailed error info. |details| string contains
+ // low level error info that is not localized and even is not user friendly.
+ // For now just ignore it because error_text contains all required information
+ // for end users, developers can see details string in Chrome logs.
bubble_ = MessageBubble::Show(
view()->GetWidget(),
view()->GetPasswordBounds(),
BubbleBorder::LEFT_TOP,
ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
error_text,
+ l10n_util::GetString(IDS_CANT_ACCESS_ACCOUNT_BUTTON),
this);
}
diff --git a/chrome/browser/chromeos/login/login_screen.h b/chrome/browser/chromeos/login/login_screen.h
index 3b3645c..59bcd0e 100644
--- a/chrome/browser/chromeos/login/login_screen.h
+++ b/chrome/browser/chromeos/login/login_screen.h
@@ -4,15 +4,16 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SCREEN_H_
+#pragma once
#include <string>
#include "base/ref_counted.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/new_user_view.h"
#include "chrome/browser/chromeos/login/view_screen.h"
-#include "chrome/browser/views/info_bubble.h"
namespace chromeos {
@@ -21,7 +22,7 @@ class MessageBubble;
class LoginScreen : public ViewScreen<NewUserView>,
public NewUserView::Delegate,
public LoginStatusConsumer,
- public InfoBubbleDelegate {
+ public MessageBubbleDelegate {
public:
explicit LoginScreen(WizardScreenDelegate* delegate);
virtual ~LoginScreen();
@@ -37,9 +38,10 @@ class LoginScreen : public ViewScreen<NewUserView>,
virtual void OnCreateAccount();
virtual void AddStartUrl(const GURL& start_url) { start_url_ = start_url; }
virtual void ClearErrors();
+ virtual void NavigateAway() {}
// Overridden from LoginStatusConsumer.
- virtual void OnLoginFailure(const std::string& error);
+ virtual void OnLoginFailure(const LoginFailure& error);
virtual void OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& credentials);
virtual void OnOffTheRecordLoginSuccess();
@@ -51,6 +53,7 @@ class LoginScreen : public ViewScreen<NewUserView>,
}
virtual bool CloseOnEscape() { return true; }
virtual bool FadeInOnShow() { return false; }
+ virtual void OnHelpLinkActivated();
private:
// ViewScreen<NewUserView>:
diff --git a/chrome/browser/chromeos/login/login_screen_browsertest.cc b/chrome/browser/chromeos/login/login_screen_browsertest.cc
index 3184426..35425e3 100644
--- a/chrome/browser/chromeos/login/login_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_screen_browsertest.cc
@@ -28,21 +28,31 @@ const char kPassword[] = "test_password";
class LoginScreenTest : public WizardInProcessBrowserTest {
public:
- LoginScreenTest(): WizardInProcessBrowserTest("login") {
+ LoginScreenTest(): WizardInProcessBrowserTest("login"),
+ mock_cryptohome_library_(NULL),
+ mock_login_library_(NULL),
+ mock_network_library_(NULL) {
}
protected:
+ MockCryptohomeLibrary *mock_cryptohome_library_;
+ MockLoginLibrary *mock_login_library_;
+ MockNetworkLibrary *mock_network_library_;
+
virtual void SetUpInProcessBrowserTestFixture() {
WizardInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
- InitStatusAreaMocks();
- SetStatusAreaMocksExpectations();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->SetStatusAreaMocksExpectations();
+
+ mock_network_library_ = cros_mock_->mock_network_library();
mock_login_library_ = new MockLoginLibrary();
EXPECT_CALL(*mock_login_library_, EmitLoginPromptReady())
.Times(1);
- test_api()->SetLoginLibrary(mock_login_library_, true);
+ cros_mock_->test_api()->SetLoginLibrary(mock_login_library_, true);
- InitMockCryptohomeLibrary();
+ cros_mock_->InitMockCryptohomeLibrary();
+ mock_cryptohome_library_ = cros_mock_->mock_cryptohome_library();
EXPECT_CALL(*mock_cryptohome_library_, IsMounted())
.Times(AnyNumber())
.WillRepeatedly((Return(true)));
@@ -51,12 +61,10 @@ class LoginScreenTest : public WizardInProcessBrowserTest {
virtual void TearDownInProcessBrowserTestFixture() {
WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
- test_api()->SetLoginLibrary(NULL, false);
+ cros_mock_->test_api()->SetLoginLibrary(NULL, false);
}
private:
- MockLoginLibrary* mock_login_library_;
-
DISALLOW_COPY_AND_ASSIGN(LoginScreenTest);
};
@@ -77,10 +85,6 @@ IN_PROC_BROWSER_TEST_F(LoginScreenTest, TestBasic) {
controller()->set_observer(mock_screen_observer.get());
NewUserView* login = controller()->GetLoginScreen()->view();
- // NOTE: When adding new controls check RecreateNativeControls()
- // that |sign_in_button_| is added with correct index.
- // See kSignInButtonFocusOrderIndex constant.
- EXPECT_EQ(9, login->GetChildViewCount());
login->SetUsername(kUsername);
login->SetPassword(kPassword);
diff --git a/chrome/browser/chromeos/login/login_status_consumer.h b/chrome/browser/chromeos/login/login_status_consumer.h
index 1fa0104..b762e38 100644
--- a/chrome/browser/chromeos/login/login_status_consumer.h
+++ b/chrome/browser/chromeos/login/login_status_consumer.h
@@ -4,19 +4,95 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_STATUS_CONSUMER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_STATUS_CONSUMER_H_
+#pragma once
#include <string>
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/gaia/google_service_auth_error.h"
+#include "net/base/net_errors.h"
namespace chromeos {
+class LoginFailure {
+ public:
+ enum FailureReason {
+ NONE,
+ COULD_NOT_MOUNT_CRYPTOHOME,
+ COULD_NOT_MOUNT_TMPFS,
+ DATA_REMOVAL_FAILED, // Could not destroy your old data
+ LOGIN_TIMED_OUT,
+ UNLOCK_FAILED,
+ NETWORK_AUTH_FAILED, // Could not authenticate against Google
+ };
+
+ explicit LoginFailure(FailureReason reason)
+ : reason_(reason),
+ error_(GoogleServiceAuthError::NONE) {
+ DCHECK(reason != NETWORK_AUTH_FAILED);
+ }
+
+ inline bool operator==(const LoginFailure &b) const {
+ if (reason_ != b.reason_) {
+ return false;
+ }
+ if (reason_ == NETWORK_AUTH_FAILED) {
+ return error_ == b.error_;
+ }
+ return true;
+ }
+
+ static LoginFailure FromNetworkAuthFailure(
+ const GoogleServiceAuthError& error) {
+ return LoginFailure(NETWORK_AUTH_FAILED, error);
+ }
+
+ static LoginFailure None() {
+ return LoginFailure(NONE);
+ }
+
+ const std::string GetErrorString() const {
+ switch (reason_) {
+ case DATA_REMOVAL_FAILED:
+ return "Could not destroy your old data.";
+ case COULD_NOT_MOUNT_CRYPTOHOME:
+ return "Could not mount cryptohome.";
+ case COULD_NOT_MOUNT_TMPFS:
+ return "Could not mount tmpfs.";
+ case LOGIN_TIMED_OUT:
+ return "Login timed out. Please try again.";
+ case UNLOCK_FAILED:
+ return "Unlock failed.";
+ case NETWORK_AUTH_FAILED:
+ if (error_.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
+ return net::ErrorToString(error_.network_error());
+ }
+ return "Google authentication failed.";
+ default:
+ NOTREACHED();
+ return std::string();
+ }
+ }
+
+ const GoogleServiceAuthError& error() const { return error_; }
+ const FailureReason& reason() const { return reason_; }
+
+ private:
+ LoginFailure(FailureReason reason, GoogleServiceAuthError error)
+ : reason_(reason),
+ error_(error) {
+ }
+
+ FailureReason reason_;
+ GoogleServiceAuthError error_;
+};
+
// An interface that defines the callbacks for objects that the
// Authenticator class will call to report the success/failure of
// authentication for Chromium OS.
class LoginStatusConsumer {
public:
virtual ~LoginStatusConsumer() {}
- virtual void OnLoginFailure(const std::string& error) = 0;
+ virtual void OnLoginFailure(const LoginFailure& error) = 0;
virtual void OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& credentials) = 0;
virtual void OnOffTheRecordLoginSuccess() {}
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index d8a9fbf..30bed68 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -8,32 +8,33 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/lock.h"
-#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
+#include "base/string_util.h"
#include "base/time.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/login_library.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/external_cookie_handler.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
+#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/user_image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
-#include "chrome/common/logging_chrome.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/url_request_context_getter.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
@@ -43,7 +44,6 @@ namespace chromeos {
namespace {
-static char kIncognitoUser[] = "incognito";
// Prefix for Auth token received from ClientLogin request.
const char kAuthPrefix[] = "Auth=";
@@ -52,15 +52,10 @@ const char kAuthSuffix[] = "\n";
} // namespace
-class LoginUtilsImpl : public LoginUtils,
- public NotificationObserver {
+class LoginUtilsImpl : public LoginUtils {
public:
LoginUtilsImpl()
: browser_launch_enabled_(true) {
- registrar_.Add(
- this,
- NotificationType::LOGIN_USER_CHANGED,
- NotificationService::AllSources());
}
// Invoked after the user has successfully logged in. This launches a browser
@@ -70,7 +65,7 @@ class LoginUtilsImpl : public LoginUtils,
// Invoked after the tmpfs is successfully mounted.
// Launches a browser in the off the record (incognito) mode.
- virtual void CompleteOffTheRecordLogin();
+ virtual void CompleteOffTheRecordLogin(const GURL& start_url);
// Creates and returns the authenticator to use. The caller owns the returned
// Authenticator and must delete it when done.
@@ -86,17 +81,7 @@ class LoginUtilsImpl : public LoginUtils,
// Returns auth token for 'cp' Contacts service.
virtual const std::string& GetAuthToken() const { return auth_token_; }
- // NotificationObserver implementation.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
private:
- // Attempt to connect to the preferred network if available.
- void ConnectToPreferredNetwork();
-
- NotificationRegistrar registrar_;
-
// Indicates if DoBrowserLaunch will actually launch the browser or not.
bool browser_launch_enabled_;
@@ -137,8 +122,8 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username,
if (CrosLibrary::Get()->EnsureLoaded())
CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, "");
+ bool first_login = !UserManager::Get()->IsKnownUser(username);
UserManager::Get()->UserLoggedIn(username);
- ConnectToPreferredNetwork();
// Now launch the initial browser window.
FilePath user_data_dir;
@@ -153,8 +138,23 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username,
*(CommandLine::ForCurrentProcess()),
logging::DELETE_OLD_LOG_FILE);
- // Supply credentials for sync and others to use
- profile->GetTokenService()->SetClientLoginResult(credentials);
+ // Supply credentials for sync and others to use. Load tokens from disk.
+ TokenService* token_service = profile->GetTokenService();
+ token_service->Initialize(GaiaConstants::kChromeOSSource,
+ profile);
+ token_service->LoadTokensFromDB();
+ token_service->UpdateCredentials(credentials);
+ if (token_service->AreCredentialsValid()) {
+ token_service->StartFetchingTokens();
+ }
+
+ // Set the CrOS user by getting this constructor run with the
+ // user's email on first retrieval.
+ profile->GetProfileSyncService(username);
+
+ // Attempt to take ownership; this will fail if device is already owned.
+ OwnershipService::GetSharedInstance()->StartTakeOwnershipAttempt(
+ UserManager::Get()->logged_in_user().email());
// Take the credentials passed in and try to exchange them for
// full-fledged Google authentication cookies. This is
@@ -165,21 +165,77 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username,
CookieFetcher* cf = new CookieFetcher(profile);
cf->AttemptFetch(credentials.data);
auth_token_ = credentials.token;
+
+ static const char kFallbackInputMethodLocale[] = "en-US";
+ if (first_login) {
+ std::string locale(g_browser_process->GetApplicationLocale());
+ // Add input methods based on the application locale when the user first
+ // logs in. For instance, if the user chooses Japanese as the UI
+ // language at the first login, we'll add input methods associated with
+ // Japanese, such as mozc.
+ if (locale != kFallbackInputMethodLocale) {
+ StringPrefMember language_preload_engines;
+ language_preload_engines.Init(prefs::kLanguagePreloadEngines,
+ profile->GetPrefs(), NULL);
+ StringPrefMember language_preferred_languages;
+ language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
+ profile->GetPrefs(), NULL);
+
+ std::string preload_engines(language_preload_engines.GetValue());
+ std::vector<std::string> input_method_ids;
+ input_method::GetInputMethodIdsFromLanguageCode(
+ locale, input_method::kAllInputMethods, &input_method_ids);
+ if (!input_method_ids.empty()) {
+ if (!preload_engines.empty())
+ preload_engines += ',';
+ preload_engines += input_method_ids[0];
+ }
+ language_preload_engines.SetValue(preload_engines);
+
+ // Add the UI language to the preferred languages the user first logs in.
+ std::string preferred_languages(locale);
+ preferred_languages += ",";
+ preferred_languages += kFallbackInputMethodLocale;
+ language_preferred_languages.SetValue(preferred_languages);
+ }
+ }
}
-void LoginUtilsImpl::CompleteOffTheRecordLogin() {
+void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
LOG(INFO) << "Completing off the record login";
- if (CrosLibrary::Get()->EnsureLoaded())
- CrosLibrary::Get()->GetLoginLibrary()->StartSession(kIncognitoUser, "");
-
- // Incognito flag is not set by default.
- CommandLine::ForCurrentProcess()->AppendSwitch(switches::kIncognito);
-
UserManager::Get()->OffTheRecordUserLoggedIn();
- ConnectToPreferredNetwork();
- LoginUtils::DoBrowserLaunch(
- ProfileManager::GetDefaultProfile()->GetOffTheRecordProfile());
+
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ // For BWSI we ask session manager to restart Chrome with --bwsi flag.
+ // We keep only some of the arguments of this process.
+ static const char* kForwardSwitches[] = {
+ switches::kLoggingLevel,
+ switches::kEnableLogging,
+ switches::kUserDataDir,
+ switches::kScrollPixels,
+ switches::kEnableGView,
+ switches::kNoFirstRun,
+ switches::kLoginProfile
+ };
+ const CommandLine& browser_command_line =
+ *CommandLine::ForCurrentProcess();
+ CommandLine command_line(browser_command_line.GetProgram());
+ command_line.CopySwitchesFrom(browser_command_line,
+ kForwardSwitches,
+ arraysize(kForwardSwitches));
+ command_line.AppendSwitch(switches::kBWSI);
+ command_line.AppendSwitch(switches::kIncognito);
+ command_line.AppendSwitch(switches::kEnableTabbedOptions);
+ command_line.AppendSwitchASCII(
+ switches::kLoginUser,
+ UserManager::Get()->logged_in_user().email());
+ if (start_url.is_valid())
+ command_line.AppendArg(start_url.spec());
+ CrosLibrary::Get()->GetLoginLibrary()->RestartJob(
+ getpid(),
+ command_line.command_line_string());
+ }
}
Authenticator* LoginUtilsImpl::CreateAuthenticator(
@@ -195,18 +251,6 @@ bool LoginUtilsImpl::IsBrowserLaunchEnabled() const {
return browser_launch_enabled_;
}
-void LoginUtilsImpl::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NotificationType::LOGIN_USER_CHANGED)
- base::OpenPersistentNSSDB();
-}
-
-void LoginUtilsImpl::ConnectToPreferredNetwork() {
- CrosLibrary::Get()->GetNetworkLibrary()->
- ConnectToPreferredNetworkIfAvailable();
-}
-
LoginUtils* LoginUtils::Get() {
return Singleton<LoginUtilsWrapper>::get()->get();
}
@@ -229,23 +273,9 @@ void LoginUtils::DoBrowserLaunch(Profile* profile) {
int return_code;
browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(),
profile,
- std::wstring(),
+ FilePath(),
true,
&return_code);
}
-std::string LoginUtils::ExtractClientLoginParam(
- const std::string& credentials,
- const std::string& param_prefix,
- const std::string& param_suffix) {
- size_t start = credentials.find(param_prefix);
- if (start == std::string::npos)
- return std::string();
- start += param_prefix.size();
- size_t end = credentials.find(param_suffix, start);
- if (end == std::string::npos)
- return std::string();
- return credentials.substr(start, end - start);
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h
index 757fd21..b23c60d 100644
--- a/chrome/browser/chromeos/login/login_utils.h
+++ b/chrome/browser/chromeos/login/login_utils.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_UTILS_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_UTILS_H_
+#pragma once
#include <string>
-#include <vector>
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+class GURL;
class Profile;
namespace chromeos {
@@ -30,13 +31,6 @@ class LoginUtils {
// Task posted to the UI thread.
static void DoBrowserLaunch(Profile* profile);
- // Extracts specified param from given ClientLogin response.
- // Returns the param value if found, empty string otherwise.
- // Ex. prefix: "Auth=", suffix: "\n"
- static std::string ExtractClientLoginParam(const std::string& credentials,
- const std::string& param_prefix,
- const std::string& param_suffix);
-
virtual ~LoginUtils() {}
// Invoked after the user has successfully logged in. This launches a browser
@@ -45,8 +39,9 @@ class LoginUtils {
const GaiaAuthConsumer::ClientLoginResult& credentials) = 0;
// Invoked after the tmpfs is successfully mounted.
- // Launches a browser in the off the record (incognito) mode.
- virtual void CompleteOffTheRecordLogin() = 0;
+ // Asks session manager to restart Chrome in Browse Without Sign In mode.
+ // |start_url| is url for launched browser to open.
+ virtual void CompleteOffTheRecordLogin(const GURL& start_url) = 0;
// Creates and returns the authenticator to use. The caller owns the returned
// Authenticator and must delete it when done.
diff --git a/chrome/browser/chromeos/login/message_bubble.cc b/chrome/browser/chromeos/login/message_bubble.cc
index 3c69f89..82cb775 100644
--- a/chrome/browser/chromeos/login/message_bubble.cc
+++ b/chrome/browser/chromeos/login/message_bubble.cc
@@ -19,10 +19,17 @@ namespace chromeos {
static const int kBorderSize = 4;
static const int kMaxLabelWidth = 250;
-MessageBubble::MessageBubble(views::WidgetGtk::Type type, views::Widget* parent,
- SkBitmap* image, const std::wstring& text, bool grab_enabled)
+MessageBubble::MessageBubble(views::WidgetGtk::Type type,
+ views::Widget* parent,
+ SkBitmap* image,
+ const std::wstring& text,
+ const std::wstring& help,
+ bool grab_enabled,
+ MessageBubbleDelegate* delegate)
: InfoBubble(type),
parent_(parent),
+ help_link_(NULL),
+ message_delegate_(delegate),
grab_enabled_(grab_enabled) {
using views::GridLayout;
@@ -38,6 +45,12 @@ MessageBubble::MessageBubble(views::WidgetGtk::Type type, views::Widget* parent,
column_set->AddPaddingColumn(0, kBorderSize);
column_set->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
GridLayout::USE_PREF, 0, 0);
+ if (!help.empty()) {
+ column_set = layout->AddColumnSet(1);
+ column_set->AddPaddingColumn(0, kBorderSize + image->width());
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 1,
+ GridLayout::USE_PREF, 0, 0);
+ }
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -60,6 +73,13 @@ MessageBubble::MessageBubble(views::WidgetGtk::Type type, views::Widget* parent,
close_button_->SetImage(views::CustomButton::BS_PUSHED,
rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
layout->AddView(close_button_);
+
+ if (!help.empty()) {
+ layout->StartRowWithPadding(0, 1, 0, kBorderSize);
+ help_link_ = new views::Link(help);
+ help_link_->SetController(this);
+ layout->AddView(help_link_);
+ }
}
void MessageBubble::ButtonPressed(views::Button* sender,
@@ -71,16 +91,26 @@ void MessageBubble::ButtonPressed(views::Button* sender,
}
}
+void MessageBubble::LinkActivated(views::Link* source, int event_flags) {
+ if (source == help_link_) {
+ if (message_delegate_)
+ message_delegate_->OnHelpLinkActivated();
+ } else {
+ NOTREACHED() << "Unknown view";
+ }
+}
+
// static
MessageBubble* MessageBubble::Show(views::Widget* parent,
const gfx::Rect& position_relative_to,
BubbleBorder::ArrowLocation arrow_location,
SkBitmap* image,
const std::wstring& text,
- InfoBubbleDelegate* delegate) {
+ const std::wstring& help,
+ MessageBubbleDelegate* delegate) {
// The bubble will be destroyed when it is closed.
MessageBubble* bubble = new MessageBubble(
- views::WidgetGtk::TYPE_WINDOW, parent, image, text, true);
+ views::WidgetGtk::TYPE_WINDOW, parent, image, text, help, true, delegate);
bubble->Init(parent, position_relative_to, arrow_location,
bubble->text_->GetParent(), delegate);
return bubble;
@@ -93,10 +123,11 @@ MessageBubble* MessageBubble::ShowNoGrab(
BubbleBorder::ArrowLocation arrow_location,
SkBitmap* image,
const std::wstring& text,
- InfoBubbleDelegate* delegate) {
+ const std::wstring& help,
+ MessageBubbleDelegate* delegate) {
// The bubble will be destroyed when it is closed.
MessageBubble* bubble = new MessageBubble(
- views::WidgetGtk::TYPE_CHILD, parent, image, text, false);
+ views::WidgetGtk::TYPE_CHILD, parent, image, text, help, false, delegate);
bubble->Init(parent, position_relative_to, arrow_location,
bubble->text_->GetParent(), delegate);
return bubble;
diff --git a/chrome/browser/chromeos/login/message_bubble.h b/chrome/browser/chromeos/login/message_bubble.h
index d265ac1..f29ecf8 100644
--- a/chrome/browser/chromeos/login/message_bubble.h
+++ b/chrome/browser/chromeos/login/message_bubble.h
@@ -4,9 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MESSAGE_BUBBLE_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_MESSAGE_BUBBLE_H_
+#pragma once
#include "chrome/browser/views/info_bubble.h"
#include "views/controls/button/button.h"
+#include "views/controls/link.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
@@ -20,9 +22,16 @@ class Label;
namespace chromeos {
+class MessageBubbleDelegate : public InfoBubbleDelegate {
+ public:
+ // Called when the user clicked on help link.
+ virtual void OnHelpLinkActivated() = 0;
+};
+
// MessageBubble is used to show error and info messages on OOBE screens.
class MessageBubble : public InfoBubble,
- public views::ButtonListener {
+ public views::ButtonListener,
+ public views::LinkController {
public:
// Create and show bubble. position_relative_to must be in screen coordinates.
static MessageBubble* Show(views::Widget* parent,
@@ -30,7 +39,8 @@ class MessageBubble : public InfoBubble,
BubbleBorder::ArrowLocation arrow_location,
SkBitmap* image,
const std::wstring& text,
- InfoBubbleDelegate* delegate);
+ const std::wstring& help,
+ MessageBubbleDelegate* delegate);
// Create and show bubble which does not grab pointer. This creates
// a TYPE_CHILD WidgetGtk and |position_relative_to| must be in parent's
@@ -40,7 +50,8 @@ class MessageBubble : public InfoBubble,
BubbleBorder::ArrowLocation arrow_location,
SkBitmap* image,
const std::wstring& text,
- InfoBubbleDelegate* delegate);
+ const std::wstring& help,
+ MessageBubbleDelegate* delegate);
// Overridden from WidgetGtk.
virtual void Close();
@@ -52,23 +63,32 @@ class MessageBubble : public InfoBubble,
}
protected:
- // views::ButtonListener implmenets.
+ // Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const views::Event& event);
+ // Overridden from views::LinkController:
+ virtual void LinkActivated(views::Link* source, int event_flags);
+
// Overridden from WidgetGtk.
virtual void IsActiveChanged();
virtual void DoGrab();
private:
MessageBubble(views::WidgetGtk::Type type,
- views::Widget* parent, SkBitmap* image,
- const std::wstring& text, bool grab_enabled);
+ views::Widget* parent,
+ SkBitmap* image,
+ const std::wstring& text,
+ const std::wstring& help,
+ bool grab_enabled,
+ MessageBubbleDelegate* delegate);
views::Widget* parent_;
views::ImageView* icon_;
views::Label* text_;
views::ImageButton* close_button_;
+ views::Link* help_link_;
+ MessageBubbleDelegate* message_delegate_;
bool grab_enabled_;
DISALLOW_COPY_AND_ASSIGN(MessageBubble);
diff --git a/chrome/browser/chromeos/login/mock_auth_response_handler.h b/chrome/browser/chromeos/login/mock_auth_response_handler.h
index 81c33b2..db4651a 100644
--- a/chrome/browser/chromeos/login/mock_auth_response_handler.h
+++ b/chrome/browser/chromeos/login/mock_auth_response_handler.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_
+#pragma once
#include "chrome/browser/chromeos/login/auth_response_handler.h"
diff --git a/chrome/browser/chromeos/login/mock_authenticator.h b/chrome/browser/chromeos/login/mock_authenticator.h
index 788708a..31a8542 100644
--- a/chrome/browser/chromeos/login/mock_authenticator.h
+++ b/chrome/browser/chromeos/login/mock_authenticator.h
@@ -4,11 +4,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTHENTICATOR_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTHENTICATOR_H_
+#pragma once
#include <string>
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "testing/gtest/include/gtest/gtest.h"
class Profile;
@@ -43,11 +46,13 @@ class MockAuthenticator : public Authenticator {
GaiaAuthConsumer::ClientLoginResult()));
return true;
} else {
+ GoogleServiceAuthError error(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
NewRunnableMethod(this,
&MockAuthenticator::OnLoginFailure,
- std::string("Login failed")));
+ LoginFailure::FromNetworkAuthFailure(error)));
return false;
}
}
@@ -68,8 +73,8 @@ class MockAuthenticator : public Authenticator {
consumer_->OnLoginSuccess(expected_username_, credentials);
}
- void OnLoginFailure(const std::string& data) {
- consumer_->OnLoginFailure(data);
+ void OnLoginFailure(const LoginFailure& failure) {
+ consumer_->OnLoginFailure(failure);
LOG(INFO) << "Posting a QuitTask to UI thread";
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE, new MessageLoop::QuitTask);
@@ -106,7 +111,7 @@ class MockLoginUtils : public LoginUtils {
EXPECT_EQ(expected_username_, username);
}
- virtual void CompleteOffTheRecordLogin() {
+ virtual void CompleteOffTheRecordLogin(const GURL& start_url) {
}
virtual Authenticator* CreateAuthenticator(LoginStatusConsumer* consumer) {
diff --git a/chrome/browser/chromeos/login/mock_screen_observer.h b/chrome/browser/chromeos/login/mock_screen_observer.h
index 1df4106..951c045 100644
--- a/chrome/browser/chromeos/login/mock_screen_observer.h
+++ b/chrome/browser/chromeos/login/mock_screen_observer.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_SCREEN_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_SCREEN_OBSERVER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/mock_update_screen.h b/chrome/browser/chromeos/login/mock_update_screen.h
index 2e6beb2..ad34cb8 100644
--- a/chrome/browser/chromeos/login/mock_update_screen.h
+++ b/chrome/browser/chromeos/login/mock_update_screen.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_UPDATE_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_UPDATE_SCREEN_H_
+#pragma once
#include "chrome/browser/chromeos/login/update_screen.h"
#include "chrome/browser/chromeos/login/view_screen.h"
diff --git a/chrome/browser/chromeos/login/network_screen.cc b/chrome/browser/chromeos/login/network_screen.cc
index 2851966..9b4414d 100644
--- a/chrome/browser/chromeos/login/network_screen.cc
+++ b/chrome/browser/chromeos/login/network_screen.cc
@@ -5,12 +5,17 @@
#include "chrome/browser/chromeos/login/network_screen.h"
#include "app/l10n_util.h"
-#include "base/utf_string_conversions.h"
+#include "app/resource_bundle.h"
#include "base/logging.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/network_selection_view.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
+#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "views/widget/widget.h"
#include "views/window/window.h"
@@ -20,6 +25,10 @@ namespace {
// Time in seconds for connection timeout.
const int kConnectionTimeoutSec = 15;
+// Considering 10px shadow from each side & welcome title height at 30px.
+const int kWelcomeScreenWidth = 580;
+const int kWelcomeScreenHeight = 335;
+
} // namespace
namespace chromeos {
@@ -27,15 +36,13 @@ namespace chromeos {
///////////////////////////////////////////////////////////////////////////////
// NetworkScreen, public:
-NetworkScreen::NetworkScreen(WizardScreenDelegate* delegate, bool is_out_of_box)
- : ViewScreen<NetworkSelectionView>(delegate),
+NetworkScreen::NetworkScreen(WizardScreenDelegate* delegate)
+ : ViewScreen<NetworkSelectionView>(delegate,
+ kWelcomeScreenWidth,
+ kWelcomeScreenHeight),
is_network_subscribed_(false),
- wifi_disabled_(false),
- is_out_of_box_(is_out_of_box),
- is_waiting_for_connect_(false),
continue_pressed_(false),
- ethernet_preselected_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
+ bubble_(NULL) {
}
NetworkScreen::~NetworkScreen() {
@@ -44,60 +51,12 @@ NetworkScreen::~NetworkScreen() {
}
////////////////////////////////////////////////////////////////////////////////
-// ComboboxModel implementation:
-
-int NetworkScreen::GetItemCount() {
- // Item with index = 0 is either "no networks are available" or
- // "no selection".
- // If WiFi is disabled adding extra item to enable it.
- return static_cast<int>(networks_.GetNetworkCount()) + 1 +
- (wifi_disabled_ ? 1 : 0);
-}
-
-std::wstring NetworkScreen::GetItemAt(int index) {
- if (index == 0) {
- return networks_.IsEmpty() ?
- l10n_util::GetString(IDS_STATUSBAR_NO_NETWORKS_MESSAGE) :
- l10n_util::GetString(IDS_NETWORK_SELECTION_NONE);
- }
- if (wifi_disabled_ &&
- index == static_cast<int>(networks_.GetNetworkCount()) + 1) {
- return l10n_util::GetStringF(
- IDS_STATUSBAR_NETWORK_DEVICE_ENABLE,
- l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
- }
- NetworkList::NetworkItem* network =
- networks_.GetNetworkAt(index - 1);
- return network ? UTF16ToWide(network->label) : std::wstring();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// views::Combobox::Listener implementation:
-
-void NetworkScreen::ItemChanged(views::Combobox* sender,
- int prev_index,
- int new_index) {
- view()->EnableContinue(new_index > 0);
- // Corner case: item with index 0 is "No selection". Just select it.
- if (new_index == prev_index || new_index <= 0 || prev_index < 0)
- return;
-
- if (wifi_disabled_ &&
- new_index == static_cast<int>(networks_.GetNetworkCount()) + 1) {
- view()->EnableContinue(false);
- MessageLoop::current()->PostTask(FROM_HERE,
- task_factory_.NewRunnableMethod(&NetworkScreen::EnableWiFi));
- return;
- }
-
- if (networks_.IsEmpty())
- return;
+// NetworkScreen, NetworkScreenDelegate implementation:
- // Connect to network as early as possible.
- const NetworkList::NetworkItem* network =
- networks_.GetNetworkAt(new_index - 1);
- MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
- &NetworkScreen::ConnectToNetwork, network->network_type, network->label));
+void NetworkScreen::ClearErrors() {
+ // bubble_ will be set to NULL in callback.
+ if (bubble_)
+ bubble_->Close();
}
///////////////////////////////////////////////////////////////////////////////
@@ -105,24 +64,13 @@ void NetworkScreen::ItemChanged(views::Combobox* sender,
void NetworkScreen::ButtonPressed(views::Button* sender,
const views::Event& event) {
- // Proceed only when selected network is connected.
- const NetworkList::NetworkItem* network = GetSelectedNetwork();
- if (!network)
- return;
- if (networks_.IsNetworkConnected(network->network_type, network->label)) {
- MessageLoop::current()->PostTask(FROM_HERE,
- task_factory_.NewRunnableMethod(&NetworkScreen::NotifyOnConnection));
+ ClearErrors();
+ NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
+ if (network && network->Connected()) {
+ NotifyOnConnection();
} else {
continue_pressed_ = true;
- if (is_waiting_for_connect_) {
- ShowConnectingStatus();
- } else {
- MessageLoop::current()->PostTask(
- FROM_HERE,
- task_factory_.NewRunnableMethod(&NetworkScreen::ConnectToNetwork,
- network->network_type,
- network->label));
- }
+ WaitForConnection(network_id_);
}
}
@@ -130,58 +78,7 @@ void NetworkScreen::ButtonPressed(views::Button* sender,
// NetworkLibrary::Observer implementation:
void NetworkScreen::NetworkChanged(NetworkLibrary* network_lib) {
- if (!view())
- return;
-
- // TODO(nkostylev): Reuse network menu button - http://crosbug.com/4133
- wifi_disabled_ = !chromeos::CrosLibrary::Get()->
- GetNetworkLibrary()->wifi_enabled();
-
- // Save network selection in case it would be available after refresh.
- NetworkList::NetworkType network_type = NetworkList::NETWORK_EMPTY;
- string16 network_id;
- const NetworkList::NetworkItem* selected_network = GetSelectedNetwork();
- if (selected_network) {
- network_type = selected_network->network_type;
- network_id = selected_network->label;
- }
- networks_.NetworkChanged(network_lib);
- if (is_waiting_for_connect_ &&
- networks_.IsNetworkConnected(connecting_network_.network_type,
- connecting_network_.label)) {
- // Stop waiting & don't update spinner status.
- StopWaitingForConnection(false);
- if (continue_pressed_) {
- MessageLoop::current()->PostTask(FROM_HERE,
- task_factory_.NewRunnableMethod(&NetworkScreen::NotifyOnConnection));
- return;
- }
- }
- view()->NetworkModelChanged();
- // Prefer Ethernet when it's connected (only once).
- if (!ethernet_preselected_ &&
- networks_.IsNetworkConnected(NetworkList::NETWORK_ETHERNET, string16())) {
- ethernet_preselected_ = true;
- SelectNetwork(NetworkList::NETWORK_ETHERNET, string16());
- } else {
- SelectNetwork(network_type, network_id);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NetworkLibrary::Observer implementation:
-
-void NetworkScreen::OnDialogAccepted() {
- const NetworkList::NetworkItem* network = GetSelectedNetwork();
- if (network)
- WaitForConnection(network);
-}
-
-void NetworkScreen::OnDialogCancelled() {
- if (view()) {
- view()->EnableContinue(false);
- view()->SetSelectedNetworkItem(0);
- }
+ UpdateStatus(network_lib);
}
///////////////////////////////////////////////////////////////////////////////
@@ -196,6 +93,15 @@ NetworkSelectionView* NetworkScreen::AllocateView() {
return new NetworkSelectionView(this);
}
+///////////////////////////////////////////////////////////////////////////////
+// NetworkScreen, views::InfoBubbleDelegate implementation:
+
+void NetworkScreen::OnHelpLinkActivated() {
+ if (!help_app_.get())
+ help_app_.reset(new HelpAppLauncher(view()->GetNativeWindow()));
+ help_app_->ShowHelpTopic(HelpAppLauncher::HELP_CONNECTIVITY);
+}
+
////////////////////////////////////////////////////////////////////////////////
// NetworkScreen, public:
@@ -209,37 +115,6 @@ void NetworkScreen::Refresh() {
////////////////////////////////////////////////////////////////////////////////
// NetworkScreen, private:
-void NetworkScreen::ConnectToNetwork(NetworkList::NetworkType type,
- const string16& id) {
- const NetworkList::NetworkItem* network =
- networks_.GetNetworkById(type, id);
- if (network &&
- !networks_.IsNetworkConnected(type, id)) {
- if (NetworkList::NETWORK_WIFI == network->network_type) {
- if (network->wifi_network.encrypted()) {
- OpenPasswordDialog(network->wifi_network);
- return;
- } else {
- WaitForConnection(network);
- chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
- ConnectToWifiNetwork(network->wifi_network,
- std::string(), std::string(), std::string());
- }
- } else if (NetworkList::NETWORK_CELLULAR == network->network_type) {
- WaitForConnection(network);
- chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
- ConnectToCellularNetwork(network->cellular_network);
- }
- }
-}
-
-void NetworkScreen::EnableWiFi() {
- if (CrosLibrary::Get()->EnsureLoaded()) {
- chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
- EnableWifiNetworkDevice(true);
- }
-}
-
void NetworkScreen::SubscribeNetworkNotification() {
if (!is_network_subscribed_) {
is_network_subscribed_ = true;
@@ -254,13 +129,6 @@ void NetworkScreen::UnsubscribeNetworkNotification() {
}
}
-NetworkList::NetworkItem* NetworkScreen::GetSelectedNetwork() {
- if (!view())
- return NULL;
-
- return networks_.GetNetworkAt(view()->GetSelectedNetworkItem() - 1);
-}
-
void NetworkScreen::NotifyOnConnection() {
// TODO(nkostylev): Check network connectivity.
UnsubscribeNetworkNotification();
@@ -269,62 +137,71 @@ void NetworkScreen::NotifyOnConnection() {
}
void NetworkScreen::OnConnectionTimeout() {
- continue_pressed_ = false;
- // TODO(nkostylev): Notify on connection error.
- if (is_waiting_for_connect_) {
- // Stop waiting & show selection combobox.
- StopWaitingForConnection(true);
- }
-}
-
-void NetworkScreen::OpenPasswordDialog(WifiNetwork network) {
- NetworkConfigView* dialog = new NetworkConfigView(network, true);
- dialog->set_delegate(this);
- dialog->set_browser_mode(false);
- views::Window* window = views::Window::CreateChromeWindow(
- view()->GetNativeWindow(), gfx::Rect(), dialog);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- dialog->SetLoginTextfieldFocus();
-}
+ StopWaitingForConnection(network_id_);
+ // Show error bubble.
+ ClearErrors();
+ views::View* network_control = view()->GetNetworkControlView();
+ bubble_ = MessageBubble::Show(
+ network_control->GetWidget(),
+ network_control->GetScreenBounds(),
+ BubbleBorder::LEFT_TOP,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
+ l10n_util::GetStringF(IDS_NETWORK_SELECTION_ERROR,
+ l10n_util::GetString(IDS_PRODUCT_OS_NAME),
+ UTF16ToWide(network_id_)),
+ l10n_util::GetString(IDS_NETWORK_SELECTION_ERROR_HELP),
+ this);
+}
+
+void NetworkScreen::UpdateStatus(NetworkLibrary* network) {
+ if (!view() || !network)
+ return;
-void NetworkScreen::SelectNetwork(NetworkList::NetworkType type,
- const string16& id) {
- int index = networks_.GetNetworkIndexById(type, id);
- if (index >= 0) {
- view()->SetSelectedNetworkItem(index + 1);
+ if (network->ethernet_connected()) {
+ StopWaitingForConnection(
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET));
+ } else if (network->wifi_connected()) {
+ StopWaitingForConnection(ASCIIToUTF16(network->wifi_name()));
+ } else if (network->cellular_connected()) {
+ StopWaitingForConnection(ASCIIToUTF16(network->cellular_name()));
+ } else if (network->ethernet_connecting()) {
+ WaitForConnection(
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET));
+ } else if (network->wifi_connecting()) {
+ WaitForConnection(ASCIIToUTF16(network->wifi_name()));
+ } else if (network->cellular_connecting()) {
+ WaitForConnection(ASCIIToUTF16(network->cellular_name()));
} else {
- view()->SetSelectedNetworkItem(0);
+ view()->EnableContinue(network->Connected());
}
}
-void NetworkScreen::ShowConnectingStatus() {
- view()->ShowConnectingStatus(is_waiting_for_connect_,
- connecting_network_.label);
-}
+void NetworkScreen::StopWaitingForConnection(const string16& network_id) {
+ NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
+ bool is_connected = network && network->Connected();
+ if (is_connected && continue_pressed_) {
+ NotifyOnConnection();
+ return;
+ }
+
+ continue_pressed_ = false;
+ connection_timer_.Stop();
-void NetworkScreen::StopWaitingForConnection(bool show_combobox) {
- if (connection_timer_.IsRunning())
- connection_timer_.Stop();
- is_waiting_for_connect_ = false;
- connecting_network_.network_type = NetworkList::NETWORK_EMPTY;
- connecting_network_.label.clear();
- if (show_combobox)
- ShowConnectingStatus();
+ network_id_ = network_id;
+ view()->ShowConnectingStatus(false, network_id_);
+ view()->EnableContinue(is_connected);
}
-void NetworkScreen::WaitForConnection(const NetworkList::NetworkItem* network) {
- is_waiting_for_connect_ = true;
- DCHECK(network);
- connecting_network_.network_type = network->network_type;
- connecting_network_.label = network->label;
- if (connection_timer_.IsRunning())
- connection_timer_.Stop();
+void NetworkScreen::WaitForConnection(const string16& network_id) {
+ connection_timer_.Stop();
connection_timer_.Start(base::TimeDelta::FromSeconds(kConnectionTimeoutSec),
this,
&NetworkScreen::OnConnectionTimeout);
- if (continue_pressed_)
- ShowConnectingStatus();
+
+ network_id_ = network_id;
+ view()->ShowConnectingStatus(true, network_id_);
+
+ view()->EnableContinue(false);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/network_screen.h b/chrome/browser/chromeos/login/network_screen.h
index e7d00cb..860e901 100644
--- a/chrome/browser/chromeos/login/network_screen.h
+++ b/chrome/browser/chromeos/login/network_screen.h
@@ -4,14 +4,16 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_H_
+#pragma once
-#include <string>
-
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
#include "base/task.h"
#include "base/timer.h"
#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
+#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/view_screen.h"
#include "chrome/browser/chromeos/network_list.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
@@ -20,39 +22,28 @@ class WizardScreenDelegate;
namespace chromeos {
+class HelpAppLauncher;
class NetworkSelectionView;
class NetworkScreen : public ViewScreen<NetworkSelectionView>,
- public NetworkScreenDelegate,
- public NetworkConfigView::Delegate {
+ public MessageBubbleDelegate,
+ public NetworkScreenDelegate {
public:
- NetworkScreen(WizardScreenDelegate* delegate, bool is_out_of_box);
+ explicit NetworkScreen(WizardScreenDelegate* delegate);
virtual ~NetworkScreen();
// NetworkScreenDelegate implementation:
+ virtual void ClearErrors();
virtual LanguageSwitchMenu* language_switch_menu() {
return &language_switch_menu_;
}
-
- // ComboboxModel implementation:
- virtual int GetItemCount();
- virtual std::wstring GetItemAt(int index);
-
- // views::Combobox::Listener implementation:
- virtual void ItemChanged(views::Combobox* sender,
- int prev_index,
- int new_index);
+ virtual gfx::Size size() const { return GetScreenSize(); }
// views::ButtonListener implementation:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
// NetworkLibrary::Observer implementation:
virtual void NetworkChanged(NetworkLibrary* network_lib);
- virtual void NetworkTraffic(NetworkLibrary* cros, int traffic_type) {}
-
- // NetworkConfigView::Delegate implementation:
- virtual void OnDialogAccepted();
- virtual void OnDialogCancelled();
protected:
// Subscribes NetworkScreen to the network change notification,
@@ -60,15 +51,18 @@ class NetworkScreen : public ViewScreen<NetworkSelectionView>,
void Refresh();
private:
+ FRIEND_TEST(NetworkScreenTest, Timeout);
+
// ViewScreen implementation:
virtual void CreateView();
virtual NetworkSelectionView* AllocateView();
- // Connects to network if needed and updates screen state.
- void ConnectToNetwork(NetworkList::NetworkType type, const string16& id);
-
- // Enables WiFi device.
- void EnableWiFi();
+ // Overridden from views::InfoBubbleDelegate.
+ virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape) { bubble_ = NULL; }
+ virtual bool CloseOnEscape() { return true; }
+ virtual bool FadeInOnShow() { return false; }
+ virtual void OnHelpLinkActivated();
// Subscribes to network change notifications.
void SubscribeNetworkNotification();
@@ -76,63 +70,43 @@ class NetworkScreen : public ViewScreen<NetworkSelectionView>,
// Unsubscribes from network change notifications.
void UnsubscribeNetworkNotification();
- // Returns currently selected network in the combobox.
- NetworkList::NetworkItem* GetSelectedNetwork();
-
// Notifies wizard on successful connection.
void NotifyOnConnection();
// Called by |connection_timer_| when connection to the network timed out.
void OnConnectionTimeout();
- // Opens password dialog for the encrypted networks.
- void OpenPasswordDialog(WifiNetwork network);
-
- // Selects network by type and id.
- void SelectNetwork(NetworkList::NetworkType type,
- const string16& id);
-
- // Switches connecting status based on |is_waiting_for_connect_|.
- void ShowConnectingStatus();
+ // Update UI based on current network status.
+ void UpdateStatus(NetworkLibrary* network);
// Stops waiting for network to connect.
- // If |show_combobox| is false, spinner is left on screen. Used on exit.
- void StopWaitingForConnection(bool show_combobox);
+ void StopWaitingForConnection(const string16& network_id);
// Starts waiting for network connection. Shows spinner.
- void WaitForConnection(const NetworkList::NetworkItem* network);
+ void WaitForConnection(const string16& network_id);
// True if subscribed to network change notification.
bool is_network_subscribed_;
- // Networks model, contains current state of available networks.
- NetworkList networks_;
-
- // True if WiFi is currently disabled.
- bool wifi_disabled_;
-
- // True if full OOBE flow should be shown.
- bool is_out_of_box_;
-
- // True if we're waiting for the selected network being connected.
- bool is_waiting_for_connect_;
+ // ID of the the network that we are waiting for.
+ string16 network_id_;
- // True if "Continue" button was pressed.
- // Set only when there's a network selected.
+ // True if user pressed continue button so we should proceed with OOBE
+ // as soon as we are connected.
bool continue_pressed_;
- // True if Ethernet was already preselected in combobox.
- bool ethernet_preselected_;
-
// Timer for connection timeout.
base::OneShotTimer<NetworkScreen> connection_timer_;
- // Network which we're connecting to.
- NetworkList::NetworkItem connecting_network_;
-
- ScopedRunnableMethodFactory<NetworkScreen> task_factory_;
LanguageSwitchMenu language_switch_menu_;
+ // Pointer to shown message bubble. We don't need to delete it because
+ // it will be deleted on bubble closing.
+ MessageBubble* bubble_;
+
+ // Help application used for help dialogs.
+ scoped_ptr<HelpAppLauncher> help_app_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkScreen);
};
diff --git a/chrome/browser/chromeos/login/network_screen_browsertest.cc b/chrome/browser/chromeos/login/network_screen_browsertest.cc
index e31bac8..43fa5b7 100644
--- a/chrome/browser/chromeos/login/network_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/network_screen_browsertest.cc
@@ -8,22 +8,24 @@
#include "app/l10n_util.h"
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
-#include "base/string_util.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/mock_login_library.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/login/network_selection_view.h"
-#include "chrome/browser/chromeos/login/network_screen.h"
#include "chrome/browser/chromeos/login/mock_screen_observer.h"
+#include "chrome/browser/chromeos/login/network_screen.h"
+#include "chrome/browser/chromeos/login/network_selection_view.h"
#include "chrome/browser/chromeos/login/view_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
#include "chrome/browser/chromeos/login/wizard_screen.h"
#include "chrome/test/ui_test_utils.h"
#include "grit/generated_resources.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "views/controls/button/text_button.h"
#include "views/controls/combobox/combobox.h"
@@ -42,28 +44,19 @@ class DummyButtonListener : public views::ButtonListener {
const views::Event& event) {}
};
-class DummyComboboxModel : public ComboboxModel {
- public:
- virtual int GetItemCount() { return 2; }
-
- virtual std::wstring GetItemAt(int index) {
- return L"Item " + IntToWString(index);
- }
-};
-
class NetworkScreenTest : public WizardInProcessBrowserTest {
public:
- NetworkScreenTest(): WizardInProcessBrowserTest("network") {
- cellular_.set_name("Cellular network");
- wifi_.set_name("WiFi network");
+ NetworkScreenTest(): WizardInProcessBrowserTest("network"),
+ mock_login_library_(NULL),
+ mock_network_library_(NULL) {
}
protected:
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
-
+ cros_mock_->InitStatusAreaMocks();
+ mock_network_library_ = cros_mock_->mock_network_library();
mock_login_library_ = new MockLoginLibrary();
- test_api()->SetLoginLibrary(mock_login_library_, true);
+ cros_mock_->test_api()->SetLoginLibrary(mock_login_library_, true);
EXPECT_CALL(*mock_login_library_, EmitLoginPromptReady())
.Times(1);
@@ -71,99 +64,40 @@ class NetworkScreenTest : public WizardInProcessBrowserTest {
// Status bar expectations are defined with RetiresOnSaturation() so
// these mocks will be active once status bar is initialized.
EXPECT_CALL(*mock_network_library_, ethernet_connected())
- .Times(1)
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_network_library_, ethernet_connecting())
- .Times(1)
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_network_library_, wifi_enabled())
- .Times(1)
- .WillOnce((Return(true)));
- EXPECT_CALL(*mock_network_library_, wifi_networks())
- .Times(1)
- .WillOnce((ReturnRef(wifi_networks_)));
- EXPECT_CALL(*mock_network_library_, cellular_networks())
- .Times(1)
- .WillOnce((ReturnRef(cellular_networks_)));
- EXPECT_CALL(*mock_network_library_, AddObserver(_))
- .Times(1);
- EXPECT_CALL(*mock_network_library_, RemoveObserver(_))
- .Times(1);
-
- SetStatusAreaMocksExpectations();
- }
-
- virtual void TearDownInProcessBrowserTestFixture() {
- CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
- test_api()->SetLoginLibrary(NULL, false);
- }
-
- void NetworkChangedExpectations(bool wifi_enabled) {
- EXPECT_CALL(*mock_network_library_, wifi_enabled())
- .Times(1)
- .WillOnce((Return(wifi_enabled)));
- }
-
- void EthernetExpectations(bool connected, bool connecting) {
- EXPECT_CALL(*mock_network_library_, ethernet_connected())
- .Times(1)
- .WillRepeatedly((Return(connected)));
+ .Times(3)
+ .WillRepeatedly(Return(false));
EXPECT_CALL(*mock_network_library_, ethernet_connecting())
.Times(1)
- .WillRepeatedly((Return(connecting)));
- }
-
- void WifiExpectations(bool connected, bool connecting) {
+ .WillRepeatedly(Return(false));
EXPECT_CALL(*mock_network_library_, wifi_connected())
- .Times(1)
- .WillOnce((Return(connected)));
+ .Times(3)
+ .WillRepeatedly(Return(false));
EXPECT_CALL(*mock_network_library_, wifi_connecting())
- .Times(1)
- .WillOnce((Return(connecting)));
- }
-
- void SetupWifiNetwork(bool connected, bool connecting) {
- wifi_networks_.clear();
- wifi_.set_connected(connected);
- wifi_.set_connecting(connecting);
- wifi_networks_.push_back(wifi_);
- }
-
- void SetupCellularNetwork(bool connected, bool connecting) {
- cellular_networks_.clear();
- cellular_.set_connected(connected);
- cellular_.set_connecting(connecting);
- cellular_networks_.push_back(cellular_);
- }
-
- void CellularExpectations(bool connected, bool connecting) {
+ .Times(3)
+ .WillRepeatedly(Return(false));
EXPECT_CALL(*mock_network_library_, cellular_connected())
- .Times(1)
- .WillOnce((Return(connected)));
+ .Times(3)
+ .WillRepeatedly(Return(false));
EXPECT_CALL(*mock_network_library_, cellular_connecting())
- .Times(1)
- .WillOnce((Return(connecting)));
- }
-
- void WifiCellularNetworksExpectations() {
- EXPECT_CALL(*mock_network_library_, wifi_networks())
- .Times(1)
- .WillOnce((ReturnRef(wifi_networks_)));
- EXPECT_CALL(*mock_network_library_, cellular_networks())
- .Times(1)
- .WillOnce((ReturnRef(cellular_networks_)));
- }
+ .Times(3)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .Times(3)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_network_library_, Connecting())
+ .Times(2)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_network_library_, AddObserver(_))
+ .Times(2);
+ EXPECT_CALL(*mock_network_library_, RemoveObserver(_))
+ .Times(2);
- void WifiSsidExpectation(const std::string& ssid) {
- EXPECT_CALL(*mock_network_library_, wifi_name())
- .Times(1)
- .WillOnce((ReturnRef(ssid)));
+ cros_mock_->SetStatusAreaMocksExpectations();
}
- void CellularNameExpectation(const std::string& name) {
- EXPECT_CALL(*mock_network_library_, cellular_name())
- .Times(1)
- .WillOnce((ReturnRef(name)));
+ virtual void TearDownInProcessBrowserTestFixture() {
+ CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
+ cros_mock_->test_api()->SetLoginLibrary(NULL, false);
}
void EmulateContinueButtonExit(NetworkScreen* network_screen) {
@@ -172,6 +106,8 @@ class NetworkScreenTest : public WizardInProcessBrowserTest {
EXPECT_CALL(*mock_screen_observer,
OnExit(ScreenObserver::NETWORK_CONNECTED))
.Times(1);
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .WillOnce(Return(true));
controller()->set_observer(mock_screen_observer.get());
DummyButtonListener button_listener;
views::TextButton button(&button_listener, L"Button");
@@ -184,18 +120,13 @@ class NetworkScreenTest : public WizardInProcessBrowserTest {
}
MockLoginLibrary* mock_login_library_;
-
- CellularNetworkVector cellular_networks_;
- WifiNetworkVector wifi_networks_;
-
- CellularNetwork cellular_;
- WifiNetwork wifi_;
+ MockNetworkLibrary* mock_network_library_;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
};
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Basic) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Ethernet) {
ASSERT_TRUE(controller());
NetworkScreen* network_screen = controller()->GetNetworkScreen();
ASSERT_TRUE(network_screen != NULL);
@@ -203,328 +134,148 @@ IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Basic) {
NetworkSelectionView* network_view = network_screen->view();
ASSERT_TRUE(network_view != NULL);
- ASSERT_EQ(1, network_screen->GetItemCount());
- EXPECT_EQ(l10n_util::GetString(IDS_STATUSBAR_NO_NETWORKS_MESSAGE),
- network_screen->GetItemAt(0));
-}
+ EXPECT_FALSE(network_view->IsContinueEnabled());
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, EnableWifi) {
- ASSERT_TRUE(controller());
- NetworkScreen* network_screen = controller()->GetNetworkScreen();
- ASSERT_TRUE(network_screen != NULL);
- ASSERT_EQ(network_screen, controller()->current_screen());
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
-
- // WiFi is disabled.
- NetworkChangedExpectations(false);
- EthernetExpectations(false, false);
- WifiCellularNetworksExpectations();
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(l10n_util::GetString(IDS_STATUSBAR_NO_NETWORKS_MESSAGE),
- network_screen->GetItemAt(0));
- EXPECT_EQ(l10n_util::GetStringF(IDS_STATUSBAR_NETWORK_DEVICE_ENABLE,
- l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_WIFI)),
- network_screen->GetItemAt(1));
-
- // Emulate "Enable Wifi" item press.
- EXPECT_CALL(*mock_network_library_, EnableWifiNetworkDevice(true))
- .Times(1);
- DummyComboboxModel combobox_model;
- views::Combobox combobox(&combobox_model);
- network_screen->ItemChanged(&combobox, 0, 1);
- network_view->SetSelectedNetworkItem(1);
- ui_test_utils::RunAllPendingInMessageLoop();
- ASSERT_EQ(network_screen, controller()->current_screen());
-}
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, cellular_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, ethernet_connecting())
+ .WillOnce((Return(true)));
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, NetworksConnectedNotSelected) {
- ASSERT_TRUE(controller());
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
- NetworkScreen* network_screen = controller()->GetNetworkScreen();
- ASSERT_TRUE(network_screen != NULL);
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+ EXPECT_TRUE(network_view->IsConnecting());
- EthernetExpectations(true, false);
- WifiCellularNetworksExpectations();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- // Ethernet is preselected once.
- EXPECT_EQ(1, network_view->GetSelectedNetworkItem());
- ASSERT_EQ(network_screen, controller()->current_screen());
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
- network_screen->GetItemAt(1));
-
- // Ethernet - disconnected, WiFi & Cellular - connected.
- EthernetExpectations(false, false);
- SetupWifiNetwork(true, false);
- WifiExpectations(true, false);
- SetupCellularNetwork(true, false);
- CellularExpectations(true, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- CellularNameExpectation(cellular_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(network_screen, controller()->current_screen());
- ASSERT_EQ(3, network_screen->GetItemCount());
- EXPECT_EQ(ASCIIToWide(wifi_.name()), network_screen->GetItemAt(1));
- EXPECT_EQ(ASCIIToWide(cellular_.name()), network_screen->GetItemAt(2));
-
- // Ethernet, WiFi & Cellular - connected.
- EthernetExpectations(true, false);
- WifiExpectations(true, false);
- CellularExpectations(true, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- CellularNameExpectation(cellular_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(network_screen, controller()->current_screen());
- ASSERT_EQ(4, network_screen->GetItemCount());
- EXPECT_EQ(l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
- network_screen->GetItemAt(1));
- EXPECT_EQ(ASCIIToWide(wifi_.name()), network_screen->GetItemAt(2));
- EXPECT_EQ(ASCIIToWide(cellular_.name()), network_screen->GetItemAt(3));
- // Ethernet is only preselected once.
- EXPECT_EQ(0, network_view->GetSelectedNetworkItem());
-}
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .WillOnce(Return(true));
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, EthernetSelected) {
- ASSERT_TRUE(controller());
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
- NetworkScreen* network_screen = controller()->GetNetworkScreen();
- ASSERT_TRUE(network_screen != NULL);
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
-
- // Emulate connecting to Ethernet.
- EthernetExpectations(false, true);
- WifiCellularNetworksExpectations();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
- network_screen->GetItemAt(1));
- ASSERT_EQ(network_screen, controller()->current_screen());
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_TRUE(network_view->IsContinueEnabled());
- // Emulate combobox selection - nothing happens.
- DummyComboboxModel combobox_model;
- views::Combobox combobox(&combobox_model);
- network_screen->ItemChanged(&combobox, 0, 1);
- network_view->SetSelectedNetworkItem(1);
- ui_test_utils::RunAllPendingInMessageLoop();
- ASSERT_EQ(network_screen, controller()->current_screen());
-
- // Emulate connected Ethernet - it should be preselected.
- EthernetExpectations(true, false);
- WifiCellularNetworksExpectations();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(1, network_view->GetSelectedNetworkItem());
- ASSERT_EQ(network_screen, controller()->current_screen());
-
- // "Continue" button with connected network should proceed to next screen.
EmulateContinueButtonExit(network_screen);
}
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, WifiSelected) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Wifi) {
ASSERT_TRUE(controller());
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
NetworkScreen* network_screen = controller()->GetNetworkScreen();
ASSERT_TRUE(network_screen != NULL);
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
-
- EthernetExpectations(false, false);
- SetupWifiNetwork(false, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(std::string());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(ASCIIToWide(wifi_.name()), network_screen->GetItemAt(1));
-
- DummyComboboxModel combobox_model;
- views::Combobox combobox(&combobox_model);
-
- // Emulate combobox selection.
- EthernetExpectations(false, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(std::string());
- network_screen->ItemChanged(&combobox, 0, 1);
- network_view->SetSelectedNetworkItem(1);
- EXPECT_CALL(*mock_network_library_,
- ConnectToWifiNetwork(A<WifiNetwork>(), std::string(),
- std::string(), std::string()))
- .Times(1);
- ui_test_utils::RunAllPendingInMessageLoop();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
-
- // Emulate connecting to WiFi network.
- EthernetExpectations(false, false);
- SetupWifiNetwork(false, true);
- WifiExpectations(false, true);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
ASSERT_EQ(network_screen, controller()->current_screen());
- // Emulate connected WiFi network.
- EthernetExpectations(false, false);
- SetupWifiNetwork(true, false);
- WifiExpectations(true, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ui_test_utils::RunAllPendingInMessageLoop();
- ASSERT_EQ(network_screen, controller()->current_screen());
+ NetworkSelectionView* network_view = network_screen->view();
+ ASSERT_TRUE(network_view != NULL);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, cellular_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, ethernet_connecting())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connecting())
+ .WillOnce((Return(true)));
+ std::string wifi_name = "wifi";
+ EXPECT_CALL(*mock_network_library_, wifi_name())
+ .WillOnce(ReturnRef(wifi_name));
+
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+ EXPECT_TRUE(network_view->IsConnecting());
+
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .WillOnce(Return(true));
+
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_TRUE(network_view->IsContinueEnabled());
- // "Continue" button with connected network should proceed to next screen.
EmulateContinueButtonExit(network_screen);
}
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, CellularSelected) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Cellular) {
ASSERT_TRUE(controller());
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
NetworkScreen* network_screen = controller()->GetNetworkScreen();
ASSERT_TRUE(network_screen != NULL);
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
-
- EthernetExpectations(false, false);
- SetupCellularNetwork(false, false);
- WifiCellularNetworksExpectations();
- CellularNameExpectation(std::string());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
- EXPECT_EQ(ASCIIToWide(cellular_.name()), network_screen->GetItemAt(1));
-
- DummyComboboxModel combobox_model;
- views::Combobox combobox(&combobox_model);
-
- // Emulate combobox selection.
- EthernetExpectations(false, false);
- WifiCellularNetworksExpectations();
- CellularNameExpectation(std::string());
- network_screen->ItemChanged(&combobox, 0, 1);
- network_view->SetSelectedNetworkItem(1);
- EXPECT_CALL(*mock_network_library_, ConnectToCellularNetwork(_))
- .Times(1);
- ui_test_utils::RunAllPendingInMessageLoop();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
-
- // Emulate connecting to cellular network.
- EthernetExpectations(false, false);
- SetupCellularNetwork(false, true);
- CellularExpectations(false, true);
- WifiCellularNetworksExpectations();
- CellularNameExpectation(cellular_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
ASSERT_EQ(network_screen, controller()->current_screen());
- // Emulate connected cellular network.
- EthernetExpectations(false, false);
- SetupCellularNetwork(true, false);
- CellularExpectations(true, false);
- WifiCellularNetworksExpectations();
- CellularNameExpectation(cellular_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ui_test_utils::RunAllPendingInMessageLoop();
- ASSERT_EQ(network_screen, controller()->current_screen());
+ NetworkSelectionView* network_view = network_screen->view();
+ ASSERT_TRUE(network_view != NULL);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, cellular_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, ethernet_connecting())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connecting())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, cellular_connecting())
+ .WillOnce((Return(true)));
+ std::string cellular_name = "3G";
+ EXPECT_CALL(*mock_network_library_, cellular_name())
+ .WillOnce(ReturnRef(cellular_name));
+
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+ EXPECT_TRUE(network_view->IsConnecting());
+
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .WillOnce(Return(true));
+
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_TRUE(network_view->IsContinueEnabled());
- // "Continue" button with connected network should proceed to next screen.
EmulateContinueButtonExit(network_screen);
}
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, WifiWaiting) {
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Timeout) {
ASSERT_TRUE(controller());
- NetworkLibrary* network_library =
- chromeos::CrosLibrary::Get()->GetNetworkLibrary();
NetworkScreen* network_screen = controller()->GetNetworkScreen();
ASSERT_TRUE(network_screen != NULL);
- NetworkSelectionView* network_view = network_screen->view();
- ASSERT_TRUE(network_view != NULL);
-
- EthernetExpectations(false, false);
- SetupWifiNetwork(false, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(std::string());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
-
- DummyComboboxModel combobox_model;
- views::Combobox combobox(&combobox_model);
-
- // Emulate combobox selection.
- EthernetExpectations(false, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(std::string());
- network_screen->ItemChanged(&combobox, 0, 1);
- network_view->SetSelectedNetworkItem(1);
- EXPECT_CALL(*mock_network_library_,
- ConnectToWifiNetwork(A<WifiNetwork>(), std::string(),
- std::string(), std::string()))
- .Times(1);
- ui_test_utils::RunAllPendingInMessageLoop();
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ASSERT_EQ(2, network_screen->GetItemCount());
-
- // Emulate connecting to WiFi network.
- EthernetExpectations(false, false);
- SetupWifiNetwork(false, true);
- WifiExpectations(false, true);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
-
- // Continue but wait for connection.
- scoped_ptr<MockScreenObserver>
- mock_screen_observer(new MockScreenObserver());
- EXPECT_CALL(*mock_screen_observer,
- OnExit(ScreenObserver::NETWORK_CONNECTED))
- .Times(1);
- controller()->set_observer(mock_screen_observer.get());
- DummyButtonListener button_listener;
- views::TextButton button(&button_listener, L"Button");
- views::MouseEvent event(views::Event::ET_MOUSE_RELEASED,
- 0, 0,
- views::Event::EF_LEFT_BUTTON_DOWN);
- network_screen->ButtonPressed(&button, event);
- ui_test_utils::RunAllPendingInMessageLoop();
ASSERT_EQ(network_screen, controller()->current_screen());
- // Emulate connected WiFi network.
- EthernetExpectations(false, false);
- SetupWifiNetwork(true, false);
- WifiExpectations(true, false);
- WifiCellularNetworksExpectations();
- WifiSsidExpectation(wifi_.name());
- NetworkChangedExpectations(true);
- network_screen->NetworkChanged(network_library);
- ui_test_utils::RunAllPendingInMessageLoop();
- controller()->set_observer(NULL);
+ NetworkSelectionView* network_view = network_screen->view();
+ ASSERT_TRUE(network_view != NULL);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+
+ EXPECT_CALL(*mock_network_library_, ethernet_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, cellular_connected())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, ethernet_connecting())
+ .WillOnce((Return(false)));
+ EXPECT_CALL(*mock_network_library_, wifi_connecting())
+ .WillOnce((Return(true)));
+ std::string wifi_name = "wifi";
+ EXPECT_CALL(*mock_network_library_, wifi_name())
+ .WillOnce(ReturnRef(wifi_name));
+ EXPECT_CALL(*mock_network_library_, Connected())
+ .WillOnce(Return(false));
+
+ network_screen->NetworkChanged(mock_network_library_);
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+ EXPECT_TRUE(network_view->IsConnecting());
+
+ network_screen->OnConnectionTimeout();
+ EXPECT_FALSE(network_view->IsContinueEnabled());
+ EXPECT_FALSE(network_view->IsConnecting());
+
+ // Close infobubble with error message - it makes test stable.
+ network_screen->ClearErrors();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/network_screen_delegate.h b/chrome/browser/chromeos/login/network_screen_delegate.h
index a0c911a..683c71b 100644
--- a/chrome/browser/chromeos/login/network_screen_delegate.h
+++ b/chrome/browser/chromeos/login/network_screen_delegate.h
@@ -4,24 +4,32 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_DELEGATE_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SCREEN_DELEGATE_H_
+#pragma once
#include "app/combobox_model.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "views/controls/button/button.h"
#include "views/controls/combobox/combobox.h"
+namespace gfx {
+class Size;
+} // namespace gfx
+
namespace chromeos {
class LanguageSwitchMenu;
// Interface that NetworkScreen exposes to the NetworkSelectionView.
-class NetworkScreenDelegate : public ComboboxModel,
- public views::Combobox::Listener,
- public views::ButtonListener,
+class NetworkScreenDelegate : public views::ButtonListener,
public NetworkLibrary::Observer {
public:
+ // Cleares all error notifications.
+ virtual void ClearErrors() = 0;
+
virtual LanguageSwitchMenu* language_switch_menu() = 0;
+ virtual gfx::Size size() const = 0;
+
protected:
virtual ~NetworkScreenDelegate() {}
};
diff --git a/chrome/browser/chromeos/login/network_selection_view.cc b/chrome/browser/chromeos/login/network_selection_view.cc
index 2e206a1..4b80b9c 100644
--- a/chrome/browser/chromeos/login/network_selection_view.cc
+++ b/chrome/browser/chromeos/login/network_selection_view.cc
@@ -11,16 +11,21 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
+#include "chrome/browser/chromeos/status/network_dropdown_button.h"
+#include "gfx/size.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/native_button.h"
-#include "views/controls/combobox/combobox.h"
#include "views/controls/label.h"
#include "views/controls/throbber.h"
+#include "views/grid_layout.h"
+#include "views/standard_layout.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"
#include "views/window/non_client_view.h"
@@ -28,64 +33,242 @@
#include "views/window/window_gtk.h"
using views::Background;
+using views::GridLayout;
using views::Label;
-using views::SmoothedThrobber;
using views::View;
using views::Widget;
using views::WidgetGtk;
namespace {
-const int kWelcomeLabelY = 170;
-const int kContinueButtonSpacingX = 30;
-const int kSpacing = 25;
-const int kHorizontalSpacing = 25;
-const int kSelectionBoxWidthMin = 200;
+enum kLayoutColumnsets {
+ STANDARD_ROW,
+ THROBBER_ROW,
+};
+
+enum kContentsLayoutColumnsets {
+ WELCOME_ROW,
+ CONTENTS_ROW,
+};
+
+// Grid layout constants.
+const int kBorderSize = 10;
+const int kWelcomeTitlePadding = 10;
+const int kPaddingColumnWidth = 55;
+const int kMediumPaddingColumnWidth = 20;
+const int kControlPaddingRow = 15;
+
+// Fixed size for language/network controls height.
const int kSelectionBoxHeight = 29;
-const int kSelectionBoxSpacing = 7;
// Menu button is drawn using our custom icons in resources. See
// TextButtonBorder::Paint() for details. So this offset compensate
// horizontal size, eaten by those icons.
-const int kMenuButtonHorizontalOffset = 1;
+const int kMenuHorizontalOffset = -1;
// Vertical addition to the menu window to make it appear exactly below
// MenuButton.
-const int kMenuButtonVerticalOffset = 3;
+const int kMenuVerticalOffset = 3;
-const SkColor kWelcomeColor = 0xFF1D6AB1;
+// Offset that compensates menu width so that it matches
+// menu button visual width when being in pushed state.
+const int kMenuWidthOffset = 6;
-const int kThrobberFrameMs = 60;
-const int kThrobberStartDelayMs = 500;
+const SkColor kWelcomeColor = 0xFFCDD3D6;
} // namespace
namespace chromeos {
+// NetworkDropdownButton with custom accelerator enabled.
+class NetworkControlWithAccelerators : public NetworkDropdownButton {
+ public:
+ NetworkControlWithAccelerators(bool browser_mode,
+ gfx::NativeWindow parent_window,
+ NetworkScreenDelegate* delegate)
+ : NetworkDropdownButton(browser_mode, parent_window),
+ delegate_(delegate),
+ accel_clear_errors_(views::Accelerator(app::VKEY_ESCAPE,
+ false, false, false)) {
+ AddAccelerator(accel_clear_errors_);
+ }
+
+ // Overridden from View:
+ bool AcceleratorPressed(const views::Accelerator& accel) {
+ if (accel == accel_clear_errors_) {
+ delegate_->ClearErrors();
+ return true;
+ }
+ return false;
+ }
+
+ // Overridden from MenuButton:
+ virtual bool Activate() {
+ delegate_->ClearErrors();
+ return MenuButton::Activate();
+ }
+
+ private:
+ NetworkScreenDelegate* delegate_;
+
+ // ESC accelerator for closing error info bubble.
+ views::Accelerator accel_clear_errors_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkControlWithAccelerators);
+};
+
+// MenuButton with custom processing on focus events.
+class NotifyingMenuButton : public views::MenuButton {
+ public:
+ NotifyingMenuButton(views::ButtonListener* listener,
+ const std::wstring& text,
+ views::ViewMenuDelegate* menu_delegate,
+ bool show_menu_marker,
+ NetworkScreenDelegate* delegate)
+ : MenuButton(listener, text, menu_delegate, show_menu_marker),
+ delegate_(delegate) {}
+
+ // Overridden from View:
+ virtual void DidGainFocus() {
+ delegate_->ClearErrors();
+ }
+
+ private:
+ NetworkScreenDelegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotifyingMenuButton);
+};
+
NetworkSelectionView::NetworkSelectionView(NetworkScreenDelegate* delegate)
- : network_combobox_(NULL),
+ : contents_view_(NULL),
languages_menubutton_(NULL),
welcome_label_(NULL),
select_language_label_(NULL),
select_network_label_(NULL),
connecting_network_label_(NULL),
+ network_dropdown_(NULL),
continue_button_(NULL),
- throbber_(NULL),
+ throbber_(CreateDefaultSmoothedThrobber()),
+ proxy_settings_link_(NULL),
delegate_(delegate) {
}
NetworkSelectionView::~NetworkSelectionView() {
- network_combobox_->set_listener(NULL);
- network_combobox_ = NULL;
throbber_->Stop();
throbber_ = NULL;
}
+void NetworkSelectionView::AddControlsToLayout(const gfx::Size& size,
+ views::GridLayout* contents_layout) {
+ if (IsConnecting()) {
+ const int v_padding = (size.height() -
+ throbber_->GetPreferredSize().height()) / 2;
+ contents_layout->AddPaddingRow(0, v_padding);
+ contents_layout->StartRow(0, THROBBER_ROW);
+ contents_layout->AddView(connecting_network_label_);
+ contents_layout->AddView(throbber_);
+ contents_layout->AddPaddingRow(0, v_padding);
+ } else {
+ const int v_padding = (size.height() -
+ 3 * kControlPaddingRow - 2 * kSelectionBoxHeight -
+ proxy_settings_link_->GetPreferredSize().height() -
+ continue_button_->GetPreferredSize().height()) / 2;
+ contents_layout->AddPaddingRow(0, v_padding);
+ contents_layout->StartRow(0, STANDARD_ROW);
+ contents_layout->AddView(select_language_label_);
+ contents_layout->AddView(languages_menubutton_, 1, 1,
+ GridLayout::FILL, GridLayout::FILL,
+ languages_menubutton_->GetPreferredSize().width(),
+ kSelectionBoxHeight);
+ contents_layout->AddPaddingRow(0, kControlPaddingRow);
+ contents_layout->StartRow(0, STANDARD_ROW);
+ contents_layout->AddView(select_network_label_);
+ contents_layout->AddView(network_dropdown_, 1, 1,
+ GridLayout::FILL, GridLayout::FILL,
+ network_dropdown_->GetPreferredSize().width(),
+ kSelectionBoxHeight);
+ contents_layout->AddPaddingRow(0, kControlPaddingRow);
+ contents_layout->StartRow(0, STANDARD_ROW);
+ contents_layout->SkipColumns(1);
+ contents_layout->AddView(proxy_settings_link_, 1, 1,
+ GridLayout::LEADING, GridLayout::CENTER);
+ contents_layout->AddPaddingRow(0, kControlPaddingRow);
+ contents_layout->StartRow(0, STANDARD_ROW);
+ contents_layout->SkipColumns(1);
+ contents_layout->AddView(continue_button_, 1, 1,
+ GridLayout::LEADING, GridLayout::CENTER);
+ contents_layout->AddPaddingRow(0, v_padding);
+ }
+}
+
+void NetworkSelectionView::InitLayout() {
+ gfx::Size screen_size = delegate_->size();
+ const int widest_label = std::max(
+ select_language_label_->GetPreferredSize().width(),
+ select_network_label_->GetPreferredSize().width());
+ const int dropdown_width = screen_size.width() - 2 * kBorderSize -
+ 2 * kPaddingColumnWidth - kMediumPaddingColumnWidth - widest_label;
+ delegate_->language_switch_menu()->SetFirstLevelMenuWidth(
+ dropdown_width - kMenuWidthOffset);
+
+ // Define layout and column set for entire screen (welcome + screen).
+ views::GridLayout* screen_layout = new views::GridLayout(this);
+ SetLayoutManager(screen_layout);
+ views::ColumnSet* column_set = screen_layout->AddColumnSet(WELCOME_ROW);
+ const int welcome_width = screen_size.width() - 2 * kWelcomeTitlePadding -
+ 2 * kBorderSize;
+ column_set->AddPaddingColumn(0, kWelcomeTitlePadding + kBorderSize);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, welcome_width, welcome_width);
+ column_set->AddPaddingColumn(0, kWelcomeTitlePadding + kBorderSize);
+ column_set = screen_layout->AddColumnSet(CONTENTS_ROW);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, screen_size.width(), screen_size.width());
+ screen_layout->StartRow(0, WELCOME_ROW);
+ screen_layout->AddView(welcome_label_);
+ screen_layout->StartRow(0, CONTENTS_ROW);
+ screen_layout->AddView(contents_view_);
+
+ // Welcome label size might have been changed after adding to grid layout.
+ // Screen size includes welcome label height & border on each side.
+ screen_size.set_height(screen_size.height() - 2 * kBorderSize -
+ welcome_label_->GetPreferredSize().height());
+
+ // Define layout and column set for screen contents.
+ views::GridLayout* contents_layout = new views::GridLayout(contents_view_);
+ contents_view_->SetLayoutManager(contents_layout);
+
+ column_set = contents_layout->AddColumnSet(STANDARD_ROW);
+ column_set->AddPaddingColumn(0, kPaddingColumnWidth);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
+ GridLayout::FIXED, widest_label, widest_label);
+ column_set->AddPaddingColumn(0, kMediumPaddingColumnWidth);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, dropdown_width, dropdown_width);
+ column_set->AddPaddingColumn(1, kPaddingColumnWidth);
+
+ const int h_padding = (screen_size.width() - 2 * kBorderSize -
+ connecting_network_label_->GetPreferredSize().width() -
+ throbber_->GetPreferredSize().width()) / 2;
+ column_set = contents_layout->AddColumnSet(THROBBER_ROW);
+ column_set->AddPaddingColumn(0, h_padding);
+ column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, h_padding);
+
+ AddControlsToLayout(screen_size, contents_layout);
+}
+
void NetworkSelectionView::Init() {
+ contents_view_ = new views::View();
+
// Use rounded rect background.
views::Painter* painter = CreateWizardPainter(
&BorderDefinition::kScreenBorder);
- set_background(
+ contents_view_->set_background(
views::Background::CreateBackgroundPainter(true, painter));
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -100,41 +283,36 @@ void NetworkSelectionView::Init() {
select_language_label_ = new views::Label();
select_language_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+ languages_menubutton_ = new NotifyingMenuButton(
+ NULL, std::wstring(), delegate_->language_switch_menu(), true, delegate_);
+ languages_menubutton_->SetFocusable(true);
+ languages_menubutton_->SetNormalHasBorder(true);
+ // Menu is positioned by bottom right corner of the MenuButton.
+ delegate_->language_switch_menu()->set_menu_offset(kMenuHorizontalOffset,
+ kMenuVerticalOffset);
+
select_network_label_ = new views::Label();
select_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
+ network_dropdown_ = new NetworkControlWithAccelerators(false,
+ GetNativeWindow(),
+ delegate_);
+ network_dropdown_->SetNormalHasBorder(true);
+ network_dropdown_->SetFocusable(true);
+
connecting_network_label_ = new views::Label();
connecting_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
connecting_network_label_->SetVisible(false);
- throbber_ = new views::SmoothedThrobber(kThrobberFrameMs);
- throbber_->SetFrames(
- ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
- throbber_->set_start_delay_ms(kThrobberStartDelayMs);
- AddChildView(throbber_);
-
- network_combobox_ = new views::Combobox(delegate_);
- network_combobox_->set_listener(delegate_);
-
- languages_menubutton_ = new views::MenuButton(
- NULL, std::wstring(), delegate_->language_switch_menu(), true);
- languages_menubutton_->SetFocusable(true);
- languages_menubutton_->SetNormalHasBorder(true);
- delegate_->language_switch_menu()->set_menu_offset(
- kMenuButtonHorizontalOffset, kMenuButtonVerticalOffset);
-
- AddChildView(welcome_label_);
- AddChildView(select_language_label_);
- AddChildView(select_network_label_);
- AddChildView(connecting_network_label_);
- AddChildView(languages_menubutton_);
- AddChildView(network_combobox_);
+ proxy_settings_link_ = new views::Link();
+ proxy_settings_link_->SetController(this);
+ proxy_settings_link_->SetVisible(true);
+ proxy_settings_link_->SetFocusable(true);
UpdateLocalizedStrings();
}
void NetworkSelectionView::UpdateLocalizedStrings() {
- RecreateNativeControls();
languages_menubutton_->SetText(
delegate_->language_switch_menu()->GetCurrentLocaleName());
welcome_label_->SetText(l10n_util::GetStringF(IDS_NETWORK_SELECTION_TITLE,
@@ -143,130 +321,42 @@ void NetworkSelectionView::UpdateLocalizedStrings() {
l10n_util::GetString(IDS_LANGUAGE_SELECTION_SELECT));
select_network_label_->SetText(
l10n_util::GetString(IDS_NETWORK_SELECTION_SELECT));
- continue_button_->SetLabel(
- l10n_util::GetString(IDS_NETWORK_SELECTION_CONTINUE_BUTTON));
+ proxy_settings_link_->SetText(
+ l10n_util::GetString(IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON));
+ RecreateNativeControls();
UpdateConnectingNetworkLabel();
+ network_dropdown_->Refresh();
+ InitLayout();
}
////////////////////////////////////////////////////////////////////////////////
// views::View: implementation:
-void NetworkSelectionView::ChildPreferredSizeChanged(View* child) {
- Layout();
- SchedulePaint();
-}
-
-void NetworkSelectionView::LocaleChanged() {
+void NetworkSelectionView::OnLocaleChanged() {
UpdateLocalizedStrings();
- NetworkModelChanged();
- // Explicitly set selected item - index 0 is a localized string.
- if (GetSelectedNetworkItem() <= 0 &&
- delegate_->GetItemCount() > 0) {
- SetSelectedNetworkItem(0);
- }
+ // Proxy settings dialog contains localized title. Zap it.
+ proxy_settings_dialog_.reset(NULL);
+
Layout();
SchedulePaint();
}
-gfx::Size NetworkSelectionView::GetPreferredSize() {
- return gfx::Size(width(), height());
-}
-
-void NetworkSelectionView::Layout() {
- gfx::Insets insets = GetInsets();
- int max_width = this->width() - insets.width() - 2 * kHorizontalSpacing;
- welcome_label_->SizeToFit(max_width);
- int y = kWelcomeLabelY;
- y -= welcome_label_->GetPreferredSize().height() / 2;
-
- welcome_label_->SetBounds(
- (width() - welcome_label_->GetPreferredSize().width()) / 2,
- y,
- welcome_label_->GetPreferredSize().width(),
- welcome_label_->GetPreferredSize().height());
- y += welcome_label_->GetPreferredSize().height() + kSpacing;
-
- // Use menu preffered size to calculate boxes width accordingly.
- int box_width = delegate_->language_switch_menu()->GetFirstLevelMenuWidth() +
- kMenuButtonHorizontalOffset * 2;
- const int widest_label = std::max(
- select_language_label_->GetPreferredSize().width(),
- select_network_label_->GetPreferredSize().width());
- if (box_width < kSelectionBoxWidthMin) {
- box_width = kSelectionBoxWidthMin;
- delegate_->language_switch_menu()->SetFirstLevelMenuWidth(
- box_width - kMenuButtonHorizontalOffset * 2);
- } else if (widest_label + box_width + 2 * kHorizontalSpacing > width()) {
- box_width = width() - widest_label - 2 * kHorizontalSpacing;
- }
- const int labels_x = (width() - widest_label - box_width) / 2;
- select_language_label_->SetBounds(
- labels_x,
- y,
- select_language_label_->GetPreferredSize().width(),
- select_language_label_->GetPreferredSize().height());
-
- const int selection_box_x = labels_x + widest_label + kHorizontalSpacing;
- const int label_y_offset =
- (kSelectionBoxHeight -
- select_language_label_->GetPreferredSize().height()) / 2;
- languages_menubutton_->SetBounds(selection_box_x, y - label_y_offset,
- box_width, kSelectionBoxHeight);
-
- y += kSelectionBoxHeight + kSelectionBoxSpacing;
- select_network_label_->SetBounds(
- labels_x,
- y,
- select_network_label_->GetPreferredSize().width(),
- select_network_label_->GetPreferredSize().height());
-
- connecting_network_label_->SetBounds(
- kHorizontalSpacing,
- y,
- width() - kHorizontalSpacing * 2,
- connecting_network_label_->GetPreferredSize().height());
-
- throbber_->SetBounds(
- width() / 2 + connecting_network_label_->GetPreferredSize().width() / 2 +
- kHorizontalSpacing,
- y + (connecting_network_label_->GetPreferredSize().height() -
- throbber_->GetPreferredSize().height()) / 2,
- throbber_->GetPreferredSize().width(),
- throbber_->GetPreferredSize().height());
-
- network_combobox_->SetBounds(selection_box_x, y - label_y_offset,
- box_width, kSelectionBoxHeight);
-
- y = height() - continue_button_->GetPreferredSize().height() - kSpacing;
- continue_button_->SetBounds(
- width() - kContinueButtonSpacingX -
- continue_button_->GetPreferredSize().width(),
- y,
- continue_button_->GetPreferredSize().width(),
- continue_button_->GetPreferredSize().height());
-
- // Need to refresh combobox layout explicitly.
- network_combobox_->Layout();
- continue_button_->Layout();
+void NetworkSelectionView::ViewHierarchyChanged(bool is_add,
+ View* parent,
+ View* child) {
+ if (is_add && this == child)
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
}
////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, public:
-int NetworkSelectionView::GetSelectedNetworkItem() const {
- return network_combobox_->selected_item();
-}
-
-void NetworkSelectionView::SetSelectedNetworkItem(int index) {
- network_combobox_->SetSelectedItem(index);
-}
-
-gfx::NativeWindow NetworkSelectionView::GetNativeWindow() {
+gfx::NativeWindow NetworkSelectionView::GetNativeWindow() const {
return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
}
-void NetworkSelectionView::NetworkModelChanged() {
- network_combobox_->ModelChanged();
+views::View* NetworkSelectionView::GetNetworkControlView() const {
+ return network_dropdown_;
}
void NetworkSelectionView::ShowConnectingStatus(bool connecting,
@@ -276,32 +366,62 @@ void NetworkSelectionView::ShowConnectingStatus(bool connecting,
select_language_label_->SetVisible(!connecting);
languages_menubutton_->SetVisible(!connecting);
select_network_label_->SetVisible(!connecting);
- network_combobox_->SetVisible(!connecting);
+ network_dropdown_->SetVisible(!connecting);
continue_button_->SetVisible(!connecting);
+ proxy_settings_link_->SetVisible(!connecting);
connecting_network_label_->SetVisible(connecting);
+ InitLayout();
Layout();
if (connecting) {
throbber_->Start();
+ network_dropdown_->CancelMenu();
} else {
throbber_->Stop();
}
}
+bool NetworkSelectionView::IsConnecting() const {
+ return connecting_network_label_->IsVisible();
+}
+
void NetworkSelectionView::EnableContinue(bool enabled) {
if (continue_button_)
continue_button_->SetEnabled(enabled);
}
+bool NetworkSelectionView::IsContinueEnabled() const {
+ return continue_button_ && continue_button_->IsEnabled();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// views::LinkController implementation:
+
+void NetworkSelectionView::LinkActivated(views::Link* source, int) {
+ if (source == proxy_settings_link_) {
+ if (!proxy_settings_dialog_.get()) {
+ static const char kProxySettingsURL[] = "chrome://settings/proxy";
+ proxy_settings_dialog_.reset(new LoginHtmlDialog(
+ this,
+ GetNativeWindow(),
+ l10n_util::GetString(IDS_OPTIONS_PROXY_TAB_LABEL),
+ GURL(kProxySettingsURL)));
+ }
+ proxy_settings_dialog_->Show();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, private:
void NetworkSelectionView::RecreateNativeControls() {
// There is no way to get native button preferred size after the button was
// sized so delete and recreate the button on text update.
+ bool is_continue_enabled = IsContinueEnabled();
delete continue_button_;
- continue_button_ = new views::NativeButton(delegate_, std::wstring());
- continue_button_->SetEnabled(false);
- AddChildView(continue_button_);
+ continue_button_ = new views::NativeButton(
+ delegate_,
+ l10n_util::GetString(IDS_NETWORK_SELECTION_CONTINUE_BUTTON));
+ continue_button_->SetEnabled(is_continue_enabled);
}
void NetworkSelectionView::UpdateConnectingNetworkLabel() {
diff --git a/chrome/browser/chromeos/login/network_selection_view.h b/chrome/browser/chromeos/login/network_selection_view.h
index 5843e33..b089ff8 100644
--- a/chrome/browser/chromeos/login/network_selection_view.h
+++ b/chrome/browser/chromeos/login/network_selection_view.h
@@ -4,28 +4,39 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SELECTION_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_NETWORK_SELECTION_VIEW_H_
+#pragma once
-#include <string>
-
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/chromeos/login/login_html_dialog.h"
#include "views/controls/button/menu_button.h"
+#include "views/controls/link.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window_delegate.h"
+namespace gfx {
+class Size;
+} // namespace gfx
+
namespace views {
class Combobox;
+class GridLayout;
class Label;
class NativeButton;
-class SmoothedThrobber;
+class Throbber;
} // namespace views
namespace chromeos {
+class NetworkDropdownButton;
class NetworkScreenDelegate;
class ScreenObserver;
// View for the network selection/initial welcome screen.
-class NetworkSelectionView : public views::View {
+class NetworkSelectionView : public views::View,
+ public views::LinkController,
+ public LoginHtmlDialog::Delegate {
public:
explicit NetworkSelectionView(NetworkScreenDelegate* delegate);
virtual ~NetworkSelectionView();
@@ -36,31 +47,47 @@ class NetworkSelectionView : public views::View {
// Update strings from the resources. Executed on language change.
void UpdateLocalizedStrings();
- // views::View: implementation:
- virtual gfx::Size GetPreferredSize();
- virtual void Layout();
-
- // Gets/Sets the selected item in the network combobox.
- int GetSelectedNetworkItem() const;
- void SetSelectedNetworkItem(int index);
+ // Returns top level native window for the view.
+ gfx::NativeWindow GetNativeWindow() const;
- gfx::NativeWindow GetNativeWindow();
-
- // Inform the network combobox that its model changed.
- void NetworkModelChanged();
+ // Returns network control view.
+ views::View* GetNetworkControlView() const;
// Shows network connecting status or network selection otherwise.
void ShowConnectingStatus(bool connecting, const string16& network_id);
+ // Returns true if only throbber is visible, the view is in waiting status.
+ bool IsConnecting() const;
+
// Sets whether continue control is enabled.
void EnableContinue(bool enabled);
+ // Returns whether continue button is enabled.
+ bool IsContinueEnabled() const;
+
+ // views::LinkController implementation.
+ virtual void LinkActivated(views::Link* source, int);
+
protected:
// Overridden from views::View.
- virtual void ChildPreferredSizeChanged(View* child);
- virtual void LocaleChanged();
+ virtual void OnLocaleChanged();
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
+ // LoginHtmlDialog::Delegate implementation:
+ virtual void OnDialogClosed() {}
private:
+ // Add screen controls to the contents layout specified.
+ // Based on state (connecting to the network or not)
+ // different controls are added.
+ void AddControlsToLayout(const gfx::Size& size,
+ views::GridLayout* contents_layout);
+
+ // Initializes grid layout of the screen. Called on language change too.
+ void InitLayout();
+
// Delete and recreate native controls that
// fail to update preferred size after string update.
void RecreateNativeControls();
@@ -68,15 +95,19 @@ class NetworkSelectionView : public views::View {
// Updates text on label with currently connecting network.
void UpdateConnectingNetworkLabel();
- // Dialog controls.
- views::Combobox* network_combobox_;
+ // View that contains defines screen contents.
+ views::View* contents_view_;
+
+ // Screen controls.
views::MenuButton* languages_menubutton_;
views::Label* welcome_label_;
views::Label* select_language_label_;
views::Label* select_network_label_;
views::Label* connecting_network_label_;
+ NetworkDropdownButton* network_dropdown_;
views::NativeButton* continue_button_;
- views::SmoothedThrobber* throbber_;
+ views::Throbber* throbber_;
+ views::Link* proxy_settings_link_;
// NetworkScreen delegate.
NetworkScreenDelegate* delegate_;
@@ -84,6 +115,9 @@ class NetworkSelectionView : public views::View {
// Id of the network that is in process of connecting.
string16 network_id_;
+ // Dialog used for to launch proxy settings.
+ scoped_ptr<LoginHtmlDialog> proxy_settings_dialog_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkSelectionView);
};
diff --git a/chrome/browser/chromeos/login/new_user_view.cc b/chrome/browser/chromeos/login/new_user_view.cc
index 397821d..ae97457 100644
--- a/chrome/browser/chromeos/login/new_user_view.cc
+++ b/chrome/browser/chromeos/login/new_user_view.cc
@@ -10,20 +10,22 @@
#include <algorithm>
#include <vector>
+#include "app/keyboard_codes.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/callback.h"
#include "base/command_line.h"
-#include "base/keyboard_codes.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/process_util.h"
-#include "base/utf_string_conversions.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
-#include "chrome/browser/google_util.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
+#include "grit/app_resources.h"
+#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
@@ -37,20 +39,15 @@ using views::WidgetGtk;
namespace {
-// NOTE: When adding new controls check RecreateNativeControls()
-// that |sign_in_button_| is added with correct index.
-const int kSignInButtonFocusOrderIndex = 3;
const int kTextfieldWidth = 286;
+const int kSplitterHeight = 1;
const int kRowPad = 7;
const int kColumnPad = 7;
-const int kLanguagesMenuWidth = 200;
const int kLanguagesMenuHeight = 30;
+const SkColor kLanguagesMenuTextColor = 0xFF999999;
const SkColor kErrorColor = 0xFF8F384F;
const char kDefaultDomain[] = "@gmail.com";
-const char kAccountRecoveryHelpUrl[] =
- "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
-
// Textfield that adds domain to the entered username if focus is lost and
// username doesn't have full domain.
class UsernameField : public views::Textfield {
@@ -76,23 +73,33 @@ class UsernameField : public views::Textfield {
namespace chromeos {
-NewUserView::NewUserView(Delegate* delegate, bool need_border)
+NewUserView::NewUserView(Delegate* delegate,
+ bool need_border,
+ bool need_browse_without_signin)
: username_field_(NULL),
password_field_(NULL),
title_label_(NULL),
+ title_hint_label_(NULL),
+ splitter_(NULL),
sign_in_button_(NULL),
create_account_link_(NULL),
- cant_access_account_link_(NULL),
browse_without_signin_link_(NULL),
languages_menubutton_(NULL),
throbber_(NULL),
- accel_focus_user_(views::Accelerator(base::VKEY_U, false, false, true)),
- accel_focus_pass_(views::Accelerator(base::VKEY_P, false, false, true)),
+ accel_focus_pass_(views::Accelerator(app::VKEY_P, false, false, true)),
+ accel_focus_user_(views::Accelerator(app::VKEY_U, false, false, true)),
+ accel_login_off_the_record_(
+ views::Accelerator(app::VKEY_B, false, false, true)),
+ accel_enable_accessibility_(WizardAccessibilityHelper::GetAccelerator()),
delegate_(delegate),
ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)),
focus_delayed_(false),
login_in_process_(false),
- need_border_(need_border) {
+ need_border_(need_border),
+ need_browse_without_signin_(need_browse_without_signin),
+ need_create_account_(false),
+ languages_menubutton_order_(-1),
+ sign_in_button_order_(-1) {
}
NewUserView::~NewUserView() {
@@ -105,14 +112,12 @@ void NewUserView::Init() {
views::Painter* painter = CreateWizardPainter(
&BorderDefinition::kScreenBorder);
set_background(views::Background::CreateBackgroundPainter(true, painter));
- } else {
- set_background(views::Background::CreateSolidBackground(
- BorderDefinition::kScreenBorder.top_color));
}
// Set up fonts.
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
gfx::Font title_font = rb.GetFont(ResourceBundle::MediumBoldFont);
+ gfx::Font title_hint_font = rb.GetFont(ResourceBundle::BoldFont);
title_label_ = new views::Label();
title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
@@ -120,6 +125,18 @@ void NewUserView::Init() {
title_label_->SetMultiLine(true);
AddChildView(title_label_);
+ title_hint_label_ = new views::Label();
+ title_hint_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ title_hint_label_->SetFont(title_hint_font);
+ title_hint_label_->SetColor(SK_ColorGRAY);
+ title_hint_label_->SetMultiLine(true);
+ AddChildView(title_hint_label_);
+
+ splitter_ = new views::View();
+ splitter_->set_background(
+ views::Background::CreateSolidBackground(SK_ColorGRAY));
+ AddChildView(splitter_);
+
username_field_ = new UsernameField();
AddChildView(username_field_);
@@ -129,18 +146,24 @@ void NewUserView::Init() {
throbber_ = CreateDefaultSmoothedThrobber();
AddChildView(throbber_);
- InitLink(&create_account_link_);
- InitLink(&cant_access_account_link_);
- InitLink(&browse_without_signin_link_);
-
language_switch_menu_.InitLanguageMenu();
- languages_menubutton_ = new views::MenuButton(
- NULL, std::wstring(), &language_switch_menu_, true);
- languages_menubutton_->SetFocusable(true);
+
+ RecreatePeculiarControls();
+
+ AddChildView(sign_in_button_);
+ if (need_create_account_) {
+ InitLink(&create_account_link_);
+ }
+ if (need_browse_without_signin_) {
+ InitLink(&browse_without_signin_link_);
+ }
AddChildView(languages_menubutton_);
+ // Set up accelerators.
AddAccelerator(accel_focus_user_);
AddAccelerator(accel_focus_pass_);
+ AddAccelerator(accel_login_off_the_record_);
+ AddAccelerator(accel_enable_accessibility_);
UpdateLocalizedStrings();
RequestFocus();
@@ -151,55 +174,100 @@ void NewUserView::Init() {
if (!CrosLibrary::Get()->EnsureLoaded()) {
EnableInputControls(false);
}
+
+ // The 'Sign in' button should be disabled when there is no text in the
+ // username and password fields.
+ sign_in_button_->SetEnabled(false);
}
bool NewUserView::AcceleratorPressed(const views::Accelerator& accelerator) {
if (accelerator == accel_focus_user_) {
username_field_->RequestFocus();
- return true;
- }
-
- if (accelerator == accel_focus_pass_) {
+ } else if (accelerator == accel_focus_pass_) {
password_field_->RequestFocus();
- return true;
+ } else if (accelerator == accel_login_off_the_record_) {
+ delegate_->OnLoginOffTheRecord();
+ } else if (accelerator == accel_enable_accessibility_) {
+ WizardAccessibilityHelper::GetInstance()->EnableAccessibility(this);
+ } else {
+ return false;
}
-
- return false;
+ return true;
}
-void NewUserView::RecreateNativeControls() {
+void NewUserView::RecreatePeculiarControls() {
+ // PreferredSize reported by MenuButton (and TextField) is not able
+ // to shrink, only grow; so recreate on text change.
+ delete languages_menubutton_;
+ languages_menubutton_ = new views::MenuButton(
+ NULL, std::wstring(), &language_switch_menu_, true);
+ languages_menubutton_->set_menu_marker(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_MENU_DROPARROW_SHARP));
+ languages_menubutton_->SetEnabledColor(kLanguagesMenuTextColor);
+ languages_menubutton_->SetFocusable(true);
+
// There is no way to get native button preferred size after the button was
// sized so delete and recreate the button on text update.
delete sign_in_button_;
sign_in_button_ = new views::NativeButton(this, std::wstring());
- // Add button after label, user & password fields.
- DCHECK(GetChildViewCount() >= kSignInButtonFocusOrderIndex);
- AddChildView(kSignInButtonFocusOrderIndex, sign_in_button_);
+ UpdateSignInButtonState();
+
if (!CrosLibrary::Get()->EnsureLoaded())
sign_in_button_->SetEnabled(false);
}
-void NewUserView::UpdateLocalizedStrings() {
- RecreateNativeControls();
+void NewUserView::UpdateSignInButtonState() {
+ bool enabled = !username_field_->text().empty() &&
+ !password_field_->text().empty();
+ sign_in_button_->SetEnabled(enabled);
+}
- title_label_->SetText(l10n_util::GetString(IDS_LOGIN_TITLE));
+void NewUserView::AddChildView(View* view) {
+ // languages_menubutton_ and sign_in_button_ are recreated on text change,
+ // so we restore their original position in layout.
+ if (view == languages_menubutton_) {
+ if (languages_menubutton_order_ < 0) {
+ languages_menubutton_order_ = GetChildViewCount();
+ }
+ views::View::AddChildView(languages_menubutton_order_, view);
+ } else if (view == sign_in_button_) {
+ if (sign_in_button_order_ < 0) {
+ sign_in_button_order_ = GetChildViewCount();
+ }
+ views::View::AddChildView(sign_in_button_order_, view);
+ } else {
+ views::View::AddChildView(view);
+ }
+}
+
+void NewUserView::UpdateLocalizedStrings() {
+ title_label_->SetText(l10n_util::GetStringF(
+ IDS_LOGIN_TITLE, l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
+ title_hint_label_->SetText(l10n_util::GetString(IDS_LOGIN_TITLE_HINT));
username_field_->set_text_to_display_when_empty(
l10n_util::GetStringUTF16(IDS_LOGIN_USERNAME));
password_field_->set_text_to_display_when_empty(
l10n_util::GetStringUTF16(IDS_LOGIN_PASSWORD));
sign_in_button_->SetLabel(l10n_util::GetString(IDS_LOGIN_BUTTON));
- create_account_link_->SetText(
- l10n_util::GetString(IDS_CREATE_ACCOUNT_BUTTON));
- cant_access_account_link_->SetText(
- l10n_util::GetString(IDS_CANT_ACCESS_ACCOUNT_BUTTON));
- browse_without_signin_link_->SetText(
- l10n_util::GetString(IDS_BROWSE_WITHOUT_SIGNING_IN_BUTTON));
+ if (need_create_account_) {
+ create_account_link_->SetText(
+ l10n_util::GetString(IDS_CREATE_ACCOUNT_BUTTON));
+ }
+ if (need_browse_without_signin_) {
+ browse_without_signin_link_->SetText(
+ l10n_util::GetString(IDS_BROWSE_WITHOUT_SIGNING_IN_BUTTON));
+ }
delegate_->ClearErrors();
languages_menubutton_->SetText(language_switch_menu_.GetCurrentLocaleName());
}
-void NewUserView::LocaleChanged() {
+void NewUserView::OnLocaleChanged() {
+ RecreatePeculiarControls();
UpdateLocalizedStrings();
+ AddChildView(sign_in_button_);
+ AddChildView(languages_menubutton_);
+
Layout();
SchedulePaint();
}
@@ -217,6 +285,7 @@ void NewUserView::ViewHierarchyChanged(bool is_add,
MessageLoop::current()->PostTask(FROM_HERE,
focus_grabber_factory_.NewRunnableMethod(
&NewUserView::FocusFirstField));
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
}
}
@@ -265,32 +334,49 @@ void NewUserView::Layout() {
// Place language selection in top right corner.
int x = std::max(0,
- this->width() - insets.right() - kLanguagesMenuWidth - kColumnPad);
+ this->width() - insets.right() -
+ languages_menubutton_->GetPreferredSize().width() - kColumnPad);
int y = insets.top() + kRowPad;
int width = std::min(this->width() - insets.width() - 2 * kColumnPad,
- kLanguagesMenuWidth);
+ languages_menubutton_->GetPreferredSize().width());
int height = kLanguagesMenuHeight;
languages_menubutton_->SetBounds(x, y, width, height);
+ y += height + kRowPad;
width = std::min(this->width() - insets.width() - 2 * kColumnPad,
kTextfieldWidth);
x = (this->width() - width) / 2;
int max_width = this->width() - x - insets.right();
title_label_->SizeToFit(max_width);
+ title_hint_label_->SizeToFit(max_width);
+
+ // Top align title and title hint.
+ y += setViewBounds(title_label_, x, y, max_width, false);
+ y += setViewBounds(title_hint_label_, x, y, max_width, false);
+ int title_end = y;
+
+ // Center align all other controls.
+ int create_account_link_height = need_create_account_ ?
+ create_account_link_->GetPreferredSize().height() : 0;
+ int browse_without_signin_link_height = need_browse_without_signin_ ?
+ browse_without_signin_link_->GetPreferredSize().height() : 0;
- height = title_label_->GetPreferredSize().height() +
- username_field_->GetPreferredSize().height() +
+ height = username_field_->GetPreferredSize().height() +
password_field_->GetPreferredSize().height() +
sign_in_button_->GetPreferredSize().height() +
- create_account_link_->GetPreferredSize().height() +
- cant_access_account_link_->GetPreferredSize().height() +
- browse_without_signin_link_->GetPreferredSize().height() +
- 4 * kRowPad;
- y = (this->height() - height) / 2;
+ create_account_link_height +
+ browse_without_signin_link_height +
+ 5 * kRowPad;
+ y += (this->height() - y - height) / 2;
+
+ int corner_radius = need_border_ ? login::kScreenCornerRadius : 0;
+ splitter_->SetBounds(insets.left() - corner_radius / 2,
+ title_end + (y - title_end) / 2,
+ this->width() - insets.width() + corner_radius,
+ kSplitterHeight);
- y += (setViewBounds(title_label_, x, y, max_width, false) + kRowPad);
y += (setViewBounds(username_field_, x, y, width, true) + kRowPad);
- y += (setViewBounds(password_field_, x, y, width, true) + kRowPad);
+ y += (setViewBounds(password_field_, x, y, width, true) + 3 * kRowPad);
int throbber_y = y;
y += (setViewBounds(sign_in_button_, x, y, width, false) + kRowPad);
setViewBounds(throbber_,
@@ -299,10 +385,13 @@ void NewUserView::Layout() {
throbber_->GetPreferredSize().height()) / 2,
width,
false);
- y += setViewBounds(create_account_link_, x, y, max_width, false);
- y += setViewBounds(cant_access_account_link_, x, y, max_width, false);
- y += setViewBounds(browse_without_signin_link_, x, y, max_width, false);
+ if (need_create_account_) {
+ y += setViewBounds(create_account_link_, x, y, max_width, false);
+ }
+ if (need_browse_without_signin_) {
+ y += setViewBounds(browse_without_signin_link_, x, y, max_width, false);
+ }
SchedulePaint();
}
@@ -338,8 +427,8 @@ void NewUserView::Login() {
}
// Sign in button causes a login attempt.
-void NewUserView::ButtonPressed(
- views::Button* sender, const views::Event& event) {
+void NewUserView::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
DCHECK(sender == sign_in_button_);
Login();
}
@@ -349,12 +438,6 @@ void NewUserView::LinkActivated(views::Link* source, int event_flags) {
delegate_->OnCreateAccount();
} else if (source == browse_without_signin_link_) {
delegate_->OnLoginOffTheRecord();
- } else if (source == cant_access_account_link_) {
- // TODO(nkostylev): Display offline help when network is not connected.
- // http://crosbug.com/3874
- delegate_->AddStartUrl(
- google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl)));
- delegate_->OnLoginOffTheRecord();
}
}
@@ -366,12 +449,21 @@ void NewUserView::ClearAndEnablePassword() {
throbber_->Stop();
}
+void NewUserView::ClearAndEnableFields() {
+ login_in_process_ = false;
+ EnableInputControls(true);
+ SetUsername(std::string());
+ SetPassword(std::string());
+ username_field_->RequestFocus();
+ throbber_->Stop();
+}
+
gfx::Rect NewUserView::GetPasswordBounds() const {
- gfx::Rect screen_bounds(password_field_->bounds());
- gfx::Point origin(screen_bounds.origin());
- views::View::ConvertPointToScreen(password_field_->GetParent(), &origin);
- screen_bounds.set_origin(origin);
- return screen_bounds;
+ return password_field_->GetScreenBounds();
+}
+
+gfx::Rect NewUserView::GetUsernameBounds() const {
+ return username_field_->GetScreenBounds();
}
void NewUserView::StopThrobber() {
@@ -383,26 +475,39 @@ bool NewUserView::HandleKeystroke(views::Textfield* s,
if (!CrosLibrary::Get()->EnsureLoaded() || login_in_process_)
return false;
- if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
+ if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
Login();
// Return true so that processing ends
return true;
- } else {
- delegate_->ClearErrors();
- return false;
+ } else if (keystroke.GetKeyboardCode() == app::VKEY_LEFT) {
+ if (s == username_field_ &&
+ username_field_->text().empty() &&
+ password_field_->text().empty()) {
+ delegate_->NavigateAway();
+ return true;
+ }
}
+ delegate_->ClearErrors();
// Return false so that processing does not end
return false;
}
+void NewUserView::ContentsChanged(views::Textfield* sender,
+ const string16& new_contents) {
+ UpdateSignInButtonState();
+}
+
void NewUserView::EnableInputControls(bool enabled) {
languages_menubutton_->SetEnabled(enabled);
username_field_->SetEnabled(enabled);
password_field_->SetEnabled(enabled);
sign_in_button_->SetEnabled(enabled);
- create_account_link_->SetEnabled(enabled);
- cant_access_account_link_->SetEnabled(enabled);
- browse_without_signin_link_->SetEnabled(enabled);
+ if (need_create_account_) {
+ create_account_link_->SetEnabled(enabled);
+ }
+ if (need_browse_without_signin_) {
+ browse_without_signin_link_->SetEnabled(enabled);
+ }
}
void NewUserView::InitLink(views::Link** link) {
diff --git a/chrome/browser/chromeos/login/new_user_view.h b/chrome/browser/chromeos/login/new_user_view.h
index bd3b20b..758d587 100644
--- a/chrome/browser/chromeos/login/new_user_view.h
+++ b/chrome/browser/chromeos/login/new_user_view.h
@@ -4,13 +4,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_NEW_USER_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_NEW_USER_VIEW_H_
+#pragma once
#include <string>
-#include <vector>
-#include "base/gtest_prod_util.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "views/accelerator.h"
#include "views/controls/button/button.h"
@@ -54,10 +51,16 @@ class NewUserView : public views::View,
// User started typing so clear all error messages.
virtual void ClearErrors() = 0;
+
+ // User tries to navigate away from NewUserView pod.
+ virtual void NavigateAway() = 0;
};
// If |need_border| is true, RoundedRect border and background are required.
- NewUserView(Delegate* delegate, bool need_border);
+ NewUserView(Delegate* delegate,
+ bool need_border,
+ bool need_browse_without_signin);
+
virtual ~NewUserView();
// Initialize view layout.
@@ -69,12 +72,18 @@ class NewUserView : public views::View,
// Resets password text and sets the enabled state of the password.
void ClearAndEnablePassword();
+ // Resets password and username text and focuses on username.
+ void ClearAndEnableFields();
+
// Stops throbber shown during login.
void StopThrobber();
// Returns bounds of password field in screen coordinates.
gfx::Rect GetPasswordBounds() const;
+ // Returns bounds of username field in screen coordinates.
+ gfx::Rect GetUsernameBounds() const;
+
// Overridden from views::View:
virtual gfx::Size GetPreferredSize();
virtual void Layout();
@@ -92,7 +101,7 @@ class NewUserView : public views::View,
virtual bool HandleKeystroke(views::Textfield* sender,
const views::Textfield::Keystroke& keystroke);
virtual void ContentsChanged(views::Textfield* sender,
- const string16& new_contents) {}
+ const string16& new_contents);
// Overridden from views::ButtonListener.
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
@@ -104,12 +113,14 @@ class NewUserView : public views::View,
protected:
// views::View overrides:
- virtual void ViewHierarchyChanged(bool is_add, views::View *parent,
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View *parent,
views::View *child);
virtual void NativeViewHierarchyChanged(bool attached,
gfx::NativeView native_view,
views::RootView* root_view);
- virtual void LocaleChanged();
+ virtual void OnLocaleChanged();
+ void AddChildView(View* view);
private:
// Enables/disables input controls (textfields, buttons).
@@ -120,24 +131,33 @@ class NewUserView : public views::View,
void InitLink(views::Link** link);
// Delete and recreate native controls that fail to update preferred size
- // after string update.
- void RecreateNativeControls();
+ // after text/locale update.
+ void RecreatePeculiarControls();
+
+ // Enable or disable the |sign_in_button_| based on the contents of the
+ // |username_field_| and |password_field_|. If there is text in both the
+ // button is enabled, otherwise it's disabled.
+ void UpdateSignInButtonState();
// Screen controls.
- // NOTE: When adding new controls check RecreateNativeControls()
- // that |sign_in_button_| is added with correct index.
+ // NOTE: sign_in_button_ and languages_menubutton_ are handled with
+ // special care: they are recreated on any text/locale change
+ // because they are not resized properly.
views::Textfield* username_field_;
views::Textfield* password_field_;
views::Label* title_label_;
+ views::Label* title_hint_label_;
+ views::View* splitter_;
views::NativeButton* sign_in_button_;
views::Link* create_account_link_;
- views::Link* cant_access_account_link_;
views::Link* browse_without_signin_link_;
views::MenuButton* languages_menubutton_;
views::Throbber* throbber_;
- views::Accelerator accel_focus_user_;
views::Accelerator accel_focus_pass_;
+ views::Accelerator accel_focus_user_;
+ views::Accelerator accel_login_off_the_record_;
+ views::Accelerator accel_enable_accessibility_;
// Notifications receiver.
Delegate* delegate_;
@@ -156,6 +176,17 @@ class NewUserView : public views::View,
// If true, this view needs RoundedRect border and background.
bool need_border_;
+ // Whether browse without signin is needed.
+ bool need_browse_without_signin_;
+
+ // Whether create account link is needed. Set to false for now but we may
+ // need it back in near future.
+ bool need_create_account_;
+
+ // Ordinal position of controls inside view layout.
+ int languages_menubutton_order_;
+ int sign_in_button_order_;
+
FRIEND_TEST_ALL_PREFIXES(LoginScreenTest, IncognitoLogin);
friend class LoginScreenTest;
diff --git a/chrome/browser/chromeos/login/owner_key_utils.cc b/chrome/browser/chromeos/login/owner_key_utils.cc
index 916d9c7..3016561 100644
--- a/chrome/browser/chromeos/login/owner_key_utils.cc
+++ b/chrome/browser/chromeos/login/owner_key_utils.cc
@@ -12,58 +12,79 @@
#include <limits>
+#include "base/crypto/rsa_private_key.h"
+#include "base/crypto/signature_creator.h"
+#include "base/crypto/signature_verifier.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
-#include "base/nss_util_internal.h"
#include "base/nss_util.h"
+#include "base/nss_util_internal.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/login_library.h"
+#include "chrome/common/extensions/extension_constants.h"
+
+using base::RSAPrivateKey;
+using extension_misc::kSignatureAlgorithm;
+
+namespace chromeos {
+
+///////////////////////////////////////////////////////////////////////////
+// OwnerKeyUtils
// static
OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;
+OwnerKeyUtils::OwnerKeyUtils() {}
+
+OwnerKeyUtils::~OwnerKeyUtils() {}
+
+///////////////////////////////////////////////////////////////////////////
+// OwnerKeyUtilsImpl
+
class OwnerKeyUtilsImpl : public OwnerKeyUtils {
public:
OwnerKeyUtilsImpl();
- virtual ~OwnerKeyUtilsImpl();
- bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
- SECKEYPublicKey** public_key_out);
+ RSAPrivateKey* GenerateKeyPair();
+
+ bool ExportPublicKeyViaDbus(RSAPrivateKey* pair,
+ LoginLibrary::Delegate* d);
+
+ bool ExportPublicKeyToFile(RSAPrivateKey* pair, const FilePath& key_file);
+
+ bool ImportPublicKey(const FilePath& key_file,
+ std::vector<uint8>* output);
+
+ bool Verify(const std::string& data,
+ const std::vector<uint8> signature,
+ const std::vector<uint8> public_key);
+
+ bool Sign(const std::string& data,
+ std::vector<uint8>* OUT_signature,
+ base::RSAPrivateKey* key);
+
+ RSAPrivateKey* FindPrivateKey(const std::vector<uint8>& key);
- bool ExportPublicKey(SECKEYPublicKey* key, const FilePath& key_file);
+ FilePath GetOwnerKeyFilePath();
- SECKEYPublicKey* ImportPublicKey(const FilePath& key_file);
+ protected:
+ virtual ~OwnerKeyUtilsImpl();
private:
- // Fills in fields of |key_der| with DER encoded data from a file at
- // |key_file|. The caller must pass in a pointer to an actual SECItem
- // struct for |key_der|. |key_der->data| should be initialized to NULL
- // and |key_der->len| should be set to 0.
- //
- // Upon success, data is stored in key_der->data, and the caller takes
- // ownership. Returns false on error.
- //
- // To free the data, call
- // SECITEM_FreeItem(key_der, PR_FALSE);
- static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der);
-
- // The place outside the owner's encrypted home directory where her
+ // The file outside the owner's encrypted home directory where her
// key will live.
static const char kOwnerKeyFile[];
// Key generation parameters.
- static const uint32 kKeyGenMechanism; // used by PK11_GenerateKeyPair()
- static const unsigned long kExponent;
- static const int kKeySizeInBits;
+ static const uint16 kKeySizeInBits;
DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
};
-OwnerKeyUtils::OwnerKeyUtils() {}
-
-OwnerKeyUtils::~OwnerKeyUtils() {}
-
+// Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
OwnerKeyUtils* OwnerKeyUtils::Create() {
if (!factory_)
return new OwnerKeyUtilsImpl();
@@ -76,162 +97,63 @@ const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
// We're generating and using 2048-bit RSA keys.
// static
-const uint32 OwnerKeyUtilsImpl::kKeyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
-// static
-const unsigned long OwnerKeyUtilsImpl::kExponent = 65537UL;
-// static
-const int OwnerKeyUtilsImpl::kKeySizeInBits = 2048;
-
-OwnerKeyUtilsImpl::OwnerKeyUtilsImpl(){}
-
-OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}
-
-bool OwnerKeyUtilsImpl::GenerateKeyPair(SECKEYPrivateKey** private_key_out,
- SECKEYPublicKey** public_key_out) {
- DCHECK(private_key_out);
- DCHECK(public_key_out);
-
- *private_key_out = NULL;
- *public_key_out = NULL;
-
- // Temporary structures used for generating the result
- // in the right format.
- PK11SlotInfo* slot = NULL;
- PK11RSAGenParams rsa_key_gen_params;
- void* key_gen_params;
-
- bool is_success = true; // Set to false as soon as a step fails.
-
- rsa_key_gen_params.keySizeInBits = kKeySizeInBits;
- rsa_key_gen_params.pe = kExponent;
- key_gen_params = &rsa_key_gen_params;
+const uint16 OwnerKeyUtilsImpl::kKeySizeInBits = 2048;
+OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {
// Ensure NSS is initialized.
base::EnsureNSSInit();
+}
- slot = base::GetDefaultNSSKeySlot();
- if (!slot) {
- LOG(ERROR) << "Couldn't get Internal key slot!";
- is_success = false;
- goto failure;
- }
+OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}
- // Need to make sure that the token was initialized.
- // Assume a null password.
- if (SECSuccess != PK11_Authenticate(slot, PR_TRUE, NULL)) {
- LOG(ERROR) << "Couldn't initialze PK11 token!";
- is_success = false;
- goto failure;
- }
+RSAPrivateKey* OwnerKeyUtilsImpl::GenerateKeyPair() {
+ return RSAPrivateKey::CreateSensitive(kKeySizeInBits);
+}
- LOG(INFO) << "Creating key pair...";
- {
- base::AutoNSSWriteLock lock;
- *private_key_out = PK11_GenerateKeyPair(slot,
- kKeyGenMechanism,
- key_gen_params,
- public_key_out,
- PR_TRUE, // isPermanent?
- PR_TRUE, // isSensitive?
- NULL);
- }
- LOG(INFO) << "done.";
+bool OwnerKeyUtilsImpl::ExportPublicKeyViaDbus(RSAPrivateKey* pair,
+ LoginLibrary::Delegate* d) {
+ DCHECK(pair);
+ bool ok = false;
- if (!*private_key_out) {
- LOG(INFO) << "Generation of Keypair failed!";
- is_success = false;
- goto failure;
+ std::vector<uint8> to_export;
+ if (!pair->ExportPublicKey(&to_export)) {
+ LOG(ERROR) << "Formatting key for export via dbus failed!";
+ return false;
}
- failure:
- if (!is_success) {
- LOG(ERROR) << "Owner key generation failed! (NSS error code "
- << PR_GetError() << ")";
- // Do cleanups
- base::AutoNSSWriteLock lock;
- if (*private_key_out) {
- PK11_DestroyTokenObject((*private_key_out)->pkcs11Slot,
- (*private_key_out)->pkcs11ID);
- SECKEY_DestroyPrivateKey(*private_key_out);
- }
- if (*public_key_out) {
- PK11_DestroyTokenObject((*public_key_out)->pkcs11Slot,
- (*public_key_out)->pkcs11ID);
- SECKEY_DestroyPublicKey(*public_key_out);
- }
- } else {
- LOG(INFO) << "Owner key generation succeeded!";
- }
- if (slot != NULL) {
- PK11_FreeSlot(slot);
- }
+ if (CrosLibrary::Get()->EnsureLoaded())
+ ok = CrosLibrary::Get()->GetLoginLibrary()->SetOwnerKeyAsync(to_export, d);
- return is_success;
+ return ok;
}
-bool OwnerKeyUtilsImpl::ExportPublicKey(SECKEYPublicKey* key,
- const FilePath& key_file) {
- DCHECK(key);
- SECItem* der;
+bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(RSAPrivateKey* pair,
+ const FilePath& key_file) {
+ DCHECK(pair);
bool ok = false;
int safe_file_size = 0;
- // Instead of exporting/importing the key directly, I'm actually
- // going to use a SubjectPublicKeyInfo. The reason is because NSS
- // exports functions that encode/decode these kinds of structures, while
- // it does not export the ones that deal directly with public keys.
- der = SECKEY_EncodeDERSubjectPublicKeyInfo(key);
- if (!der) {
- LOG(ERROR) << "Could not encode public key for export!";
+ std::vector<uint8> to_export;
+ if (!pair->ExportPublicKey(&to_export)) {
+ LOG(ERROR) << "Formatting key for export failed!";
return false;
}
- if (der->len > static_cast<uint>(INT_MAX)) {
- LOG(ERROR) << "key is too big! " << der->len;
+ if (to_export.size() > static_cast<uint>(INT_MAX)) {
+ LOG(ERROR) << "key is too big! " << to_export.size();
} else {
- safe_file_size = static_cast<int>(der->len);
+ safe_file_size = static_cast<int>(to_export.size());
ok = (safe_file_size ==
file_util::WriteFile(key_file,
- reinterpret_cast<char*>(der->data),
- der->len));
+ reinterpret_cast<char*>(&to_export.front()),
+ safe_file_size));
}
- SECITEM_FreeItem(der, PR_TRUE);
return ok;
}
-SECKEYPublicKey* OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file) {
- SECItem key_der;
-
- if (!ReadDERFromFile(key_file, &key_der)) {
- PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":";
- return NULL;
- }
-
- // See the comment in ExportPublicKey() for why I wrote a
- // SubjectPublicKeyInfo to disk instead of a key.
- CERTSubjectPublicKeyInfo* spki =
- SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
- if (!spki) {
- LOG(ERROR) << "Could not decode key info: " << PR_GetError();
- SECITEM_FreeItem(&key_der, PR_FALSE);
- return NULL;
- }
-
- SECKEYPublicKey *public_key = SECKEY_ExtractPublicKey(spki);
- SECKEY_DestroySubjectPublicKeyInfo(spki);
- SECITEM_FreeItem(&key_der, PR_FALSE);
- return public_key;
-}
-
-// static
-bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file,
- SECItem* key_der) {
- // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are
- // considered internal to the NSS command line utils.
- // This code is lifted, in spirit, from the implementation of that function.
- DCHECK(key_der) << "Don't pass NULL for |key_der|";
-
+bool OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file,
+ std::vector<uint8>* output) {
// Get the file size (must fit in a 32 bit int for NSS).
int64 file_size;
if (!file_util::GetFileSize(key_file, &file_size)) {
@@ -245,23 +167,48 @@ bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file,
}
int32 safe_file_size = static_cast<int32>(file_size);
- // Allocate space for the DER encoded data.
- key_der->data = NULL;
- if (!SECITEM_AllocItem(NULL, key_der, safe_file_size)) {
- LOG(ERROR) << "Could not create space for DER encoded key";
- return false;
- }
-
+ output->resize(safe_file_size);
// Get the key data off of disk
int data_read = file_util::ReadFile(key_file,
- reinterpret_cast<char*>(key_der->data),
+ reinterpret_cast<char*>(&(output->at(0))),
safe_file_size);
+ return data_read == safe_file_size;
+}
+
+bool OwnerKeyUtilsImpl::Verify(const std::string& data,
+ const std::vector<uint8> signature,
+ const std::vector<uint8> public_key) {
+ base::SignatureVerifier verifier;
+ if (!verifier.VerifyInit(kSignatureAlgorithm, sizeof(kSignatureAlgorithm),
+ &signature[0], signature.size(),
+ &public_key[0], public_key.size())) {
+ return false;
+ }
+
+ verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
+ data.length());
+ return (verifier.VerifyFinal());
+}
- if (data_read != safe_file_size) {
- LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! "
- << data_read;
- SECITEM_FreeItem(key_der, PR_FALSE);
+bool OwnerKeyUtilsImpl::Sign(const std::string& data,
+ std::vector<uint8>* OUT_signature,
+ base::RSAPrivateKey* key) {
+ scoped_ptr<base::SignatureCreator> signer(
+ base::SignatureCreator::Create(key));
+ if (!signer->Update(reinterpret_cast<const uint8*>(data.c_str()),
+ data.length())) {
return false;
}
- return true;
+ return signer->Final(OUT_signature);
+}
+
+RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
+ const std::vector<uint8>& key) {
+ return RSAPrivateKey::FindFromPublicKeyInfo(key);
+}
+
+FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
+ return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/owner_key_utils.h b/chrome/browser/chromeos/login/owner_key_utils.h
index 8900ed4..4921745 100644
--- a/chrome/browser/chromeos/login/owner_key_utils.h
+++ b/chrome/browser/chromeos/login/owner_key_utils.h
@@ -4,21 +4,23 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
+#pragma once
+
+#include <vector>
#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/chromeos/cros/login_library.h"
-// Forward declarations of NSS data structures.
-struct SECKEYPrivateKeyStr;
-struct SECKEYPublicKeyStr;
-struct SECItemStr;
+class FilePath;
-typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-typedef struct SECItemStr SECItem;
+namespace base {
+class RSAPrivateKey;
+}
-class FilePath;
+namespace chromeos {
-class OwnerKeyUtils {
+class OwnerKeyUtils : public base::RefCounted<OwnerKeyUtils> {
public:
class Factory {
public:
@@ -26,7 +28,6 @@ class OwnerKeyUtils {
};
OwnerKeyUtils();
- virtual ~OwnerKeyUtils();
// Sets the factory used by the static method Create to create an
// OwnerKeyUtils. OwnerKeyUtils does not take ownership of
@@ -42,29 +43,59 @@ class OwnerKeyUtils {
// Generate a public/private RSA keypair and store them in the NSS database.
// The keys will be kKeySizeInBits in length (Recommend >= 2048 bits).
+ // The caller takes ownership.
//
- // Returns false on error.
- //
- // The caller takes ownership of both objects, which are allocated by libnss.
- // To free them, call
- // SECKEY_DestroyPrivateKey(*private_key_out);
- // SECKEY_DestroyPublicKey(*public_key_out);
- virtual bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
- SECKEYPublicKey** public_key_out) = 0;
-
- // DER encodes |key| and writes it out to |key_file|.
+ // Returns NULL on error.
+ virtual base::RSAPrivateKey* GenerateKeyPair() = 0;
+
+ // DER encodes public half of |pair| and asynchronously exports it via DBus.
+ // The data sent is a DER-encoded X509 SubjectPublicKeyInfo object.
+ // Returns false on error, true if the attempt is successfully begun.
+ // d->Run() will be called with a boolean indicating success or failure when
+ // the attempt is complete.
+ virtual bool ExportPublicKeyViaDbus(base::RSAPrivateKey* pair,
+ LoginLibrary::Delegate* d) = 0;
+
+ // DER encodes public half of |pair| and writes it out to |key_file|.
// The blob on disk is a DER-encoded X509 SubjectPublicKeyInfo object.
// Returns false on error.
- virtual bool ExportPublicKey(SECKEYPublicKey* key,
- const FilePath& key_file) = 0;
+ virtual bool ExportPublicKeyToFile(base::RSAPrivateKey* pair,
+ const FilePath& key_file) = 0;
// Assumes that the file at |key_file| exists.
- // Caller takes ownership of returned object; returns NULL on error.
- // To free, call SECKEY_DestroyPublicKey.
- virtual SECKEYPublicKey* ImportPublicKey(const FilePath& key_file) = 0;
+ // Upon success, returns true and populates |output|. False on failure.
+ virtual bool ImportPublicKey(const FilePath& key_file,
+ std::vector<uint8>* output) = 0;
+
+ // Verfiy that |signature| is a Sha1-with-RSA signature over |data| with
+ // |public_key|
+ // Returns true if so, false on bad signature or other error.
+ virtual bool Verify(const std::string& data,
+ const std::vector<uint8> signature,
+ const std::vector<uint8> public_key) = 0;
+
+ // Sign |data| with |key| using Sha1 with RSA. If successful, return true
+ // and populate |OUT_signature|.
+ virtual bool Sign(const std::string& data,
+ std::vector<uint8>* OUT_signature,
+ base::RSAPrivateKey* key) = 0;
+
+ // Looks for the private key associated with |key| in the default slot,
+ // and returns it if it can be found. Returns NULL otherwise.
+ // Caller takes ownership.
+ virtual base::RSAPrivateKey* FindPrivateKey(
+ const std::vector<uint8>& key) = 0;
+
+ virtual FilePath GetOwnerKeyFilePath() = 0;
+
+ protected:
+ virtual ~OwnerKeyUtils();
private:
+ friend class base::RefCounted<OwnerKeyUtils>;
static Factory* factory_;
};
+} // namespace chromeos
+
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
diff --git a/chrome/browser/chromeos/login/owner_key_utils_unittest.cc b/chrome/browser/chromeos/login/owner_key_utils_unittest.cc
index 7a7e9e7..3b21466 100644
--- a/chrome/browser/chromeos/login/owner_key_utils_unittest.cc
+++ b/chrome/browser/chromeos/login/owner_key_utils_unittest.cc
@@ -4,112 +4,57 @@
#include "chrome/browser/chromeos/login/owner_key_utils.h"
-#include <cert.h>
-#include <keyhi.h>
-#include <keythi.h> // KeyType enum
-#include <pk11pub.h>
-#include <stdlib.h>
-
#include <string>
+#include <vector>
+#include "base/crypto/rsa_private_key.h"
#include "base/file_path.h"
#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/nss_util_internal.h"
#include "base/nss_util.h"
-#include "base/scoped_ptr.h"
+#include "base/nss_util_internal.h"
+#include "base/ref_counted.h"
#include "base/scoped_temp_dir.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
class OwnerKeyUtilsTest : public ::testing::Test {
public:
- OwnerKeyUtilsTest()
- : private_key_(NULL),
- public_key_(NULL),
- utils_(OwnerKeyUtils::Create()) {
-
- }
+ OwnerKeyUtilsTest() : utils_(OwnerKeyUtils::Create()) {}
virtual ~OwnerKeyUtilsTest() {}
virtual void SetUp() {
base::OpenPersistentNSSDB();
}
- virtual void TearDown() {
- if (private_key_) {
- PK11_DestroyTokenObject(private_key_->pkcs11Slot, private_key_->pkcs11ID);
- SECKEY_DestroyPrivateKey(private_key_);
- }
- if (public_key_) {
- PK11_DestroyTokenObject(public_key_->pkcs11Slot, public_key_->pkcs11ID);
- SECKEY_DestroyPublicKey(public_key_);
- }
- }
-
- SECKEYPrivateKey* private_key_;
- SECKEYPublicKey* public_key_;
- scoped_ptr<OwnerKeyUtils> utils_;
+ scoped_refptr<OwnerKeyUtils> utils_;
};
-TEST_F(OwnerKeyUtilsTest, KeyGenerate) {
- EXPECT_TRUE(utils_->GenerateKeyPair(&private_key_, &public_key_));
- EXPECT_TRUE(private_key_ != NULL);
- ASSERT_TRUE(public_key_ != NULL);
- EXPECT_EQ(public_key_->keyType, rsaKey);
-}
-
TEST_F(OwnerKeyUtilsTest, ExportImportPublicKey) {
- EXPECT_TRUE(utils_->GenerateKeyPair(&private_key_, &public_key_));
+ scoped_ptr<base::RSAPrivateKey> pair(utils_->GenerateKeyPair());
+ ASSERT_NE(pair.get(), reinterpret_cast<base::RSAPrivateKey*>(NULL));
+ // Export public key to file.
ScopedTempDir tmpdir;
FilePath tmpfile;
ASSERT_TRUE(tmpdir.CreateUniqueTempDir());
ASSERT_TRUE(file_util::CreateTemporaryFileInDir(tmpdir.path(), &tmpfile));
-
- EXPECT_TRUE(utils_->ExportPublicKey(public_key_, tmpfile));
-
- // Now, verify that we can look up the private key, given the public key
- // we exported. We'll create
- // an ID from the key, and then use that ID to query the token in the
- // default slot for a matching private key. Then we'll make sure it's
- // the same as |private_key_|
- PK11SlotInfo* slot = NULL;
- SECItem* ck_id = NULL;
- SECKEYPublicKey* from_disk = NULL;
- SECKEYPrivateKey* found = NULL;
-
- slot = base::GetDefaultNSSKeySlot();
- EXPECT_TRUE(slot != NULL);
- if (NULL == slot)
- goto cleanup;
-
- from_disk = utils_->ImportPublicKey(tmpfile);
- ASSERT_TRUE(from_disk != NULL);
-
- ck_id = PK11_MakeIDFromPubKey(&(from_disk->u.rsa.modulus));
- EXPECT_TRUE(ck_id != NULL);
- if (NULL == ck_id)
- goto cleanup;
-
- found = PK11_FindKeyByKeyID(slot, ck_id, NULL);
- EXPECT_TRUE(found != NULL);
- if (NULL == found)
- goto cleanup;
-
- EXPECT_EQ(private_key_->pkcs11ID, found->pkcs11ID);
-
- cleanup:
- if (slot)
- PK11_FreeSlot(slot);
- if (from_disk)
- SECKEY_DestroyPublicKey(from_disk);
- if (found)
- SECKEY_DestroyPrivateKey(found);
- if (ck_id)
- SECITEM_ZfreeItem(ck_id, PR_TRUE);
+ ASSERT_TRUE(utils_->ExportPublicKeyToFile(pair.get(), tmpfile));
+
+ // Export public key, so that we can compare it to the one we get off disk.
+ std::vector<uint8> public_key;
+ ASSERT_TRUE(pair->ExportPublicKey(&public_key));
+ std::vector<uint8> from_disk;
+ ASSERT_TRUE(utils_->ImportPublicKey(tmpfile, &from_disk));
+
+ std::vector<uint8>::iterator pubkey_it;
+ std::vector<uint8>::iterator disk_it;
+ for (pubkey_it = public_key.begin(), disk_it = from_disk.begin();
+ pubkey_it < public_key.end();
+ pubkey_it++, disk_it++) {
+ EXPECT_EQ(*pubkey_it, *disk_it);
+ }
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/password_changed_view.cc b/chrome/browser/chromeos/login/password_changed_view.cc
index ddb36ae..87c89d5 100644
--- a/chrome/browser/chromeos/login/password_changed_view.cc
+++ b/chrome/browser/chromeos/login/password_changed_view.cc
@@ -4,11 +4,12 @@
#include "chrome/browser/chromeos/login/password_changed_view.h"
+#include "app/keyboard_codes.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
-#include "base/keyboard_codes.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "views/controls/button/radio_button.h"
@@ -60,8 +61,10 @@ gfx::Size PasswordChangedView::GetPreferredSize() {
void PasswordChangedView::ViewHierarchyChanged(bool is_add,
views::View* parent,
views::View* child) {
- if (is_add && child == this)
+ if (is_add && child == this) {
Init();
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
+ }
}
void PasswordChangedView::Init() {
@@ -162,7 +165,7 @@ void PasswordChangedView::ButtonPressed(Button* sender,
bool PasswordChangedView::HandleKeystroke(views::Textfield* s,
const views::Textfield::Keystroke& keystroke) {
- if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
+ if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
ExitDialog();
return true;
}
diff --git a/chrome/browser/chromeos/login/password_changed_view.h b/chrome/browser/chromeos/login/password_changed_view.h
index 535a05a..48f6ca3 100644
--- a/chrome/browser/chromeos/login/password_changed_view.h
+++ b/chrome/browser/chromeos/login/password_changed_view.h
@@ -4,10 +4,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_PASSWORD_CHANGED_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_PASSWORD_CHANGED_VIEW_H_
+#pragma once
#include <string>
-#include "app/message_box_flags.h"
#include "views/controls/button/button.h"
#include "views/controls/textfield/textfield.h"
#include "views/view.h"
diff --git a/chrome/browser/chromeos/login/registration_screen.cc b/chrome/browser/chromeos/login/registration_screen.cc
index 40348d7..5c60331 100644
--- a/chrome/browser/chromeos/login/registration_screen.cc
+++ b/chrome/browser/chromeos/login/registration_screen.cc
@@ -17,6 +17,7 @@
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_about_job.h"
#include "net/url_request/url_request_filter.h"
+#include "views/widget/widget_gtk.h"
namespace chromeos {
@@ -86,15 +87,14 @@ void RegistrationScreen::OnPageLoaded() {
if (g_browser_process) {
const std::string locale = g_browser_process->GetApplicationLocale();
input_method::EnableInputMethods(
- locale, input_method::kKeyboardLayoutsOnly, "");
- // TODO(yusukes,suzhe): Change the 2nd argument to kAllInputMethods when
- // crosbug.com/2670 is fixed.
+ locale, input_method::kAllInputMethods, "");
}
view()->ShowPageContent();
}
void RegistrationScreen::OnPageLoadFailed(const std::string& url) {
- CloseScreen(ScreenObserver::CONNECTION_FAILED);
+ LOG(ERROR) << "Error loading registration page: " << url;
+ CloseScreen(ScreenObserver::REGISTRATION_SKIPPED);
}
///////////////////////////////////////////////////////////////////////////////
@@ -106,9 +106,11 @@ void RegistrationScreen::OnPageLoadFailed(const std::string& url) {
PageTransition::Type transition) {
if (url.spec() == kRegistrationSuccessUrl) {
source->Stop();
+ LOG(INFO) << "Registration form completed.";
CloseScreen(ScreenObserver::REGISTRATION_SUCCESS);
} else if (url.spec() == kRegistrationSkippedUrl) {
source->Stop();
+ LOG(INFO) << "Registration form skipped.";
CloseScreen(ScreenObserver::REGISTRATION_SKIPPED);
} else {
source->Stop();
@@ -118,6 +120,13 @@ void RegistrationScreen::OnPageLoadFailed(const std::string& url) {
}
}
+void RegistrationScreen::HandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event) {
+ views::Widget* widget = view()->GetWidget();
+ if (widget && event.os_event && !event.skip_in_browser)
+ static_cast<views::WidgetGtk*>(widget)->HandleKeyboardEvent(event.os_event);
+}
+
///////////////////////////////////////////////////////////////////////////////
// RegistrationScreen, private:
void RegistrationScreen::CloseScreen(ScreenObserver::ExitCodes code) {
diff --git a/chrome/browser/chromeos/login/registration_screen.h b/chrome/browser/chromeos/login/registration_screen.h
index 89d1cdb..6c10f9f 100644
--- a/chrome/browser/chromeos/login/registration_screen.h
+++ b/chrome/browser/chromeos/login/registration_screen.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_REGISTRATION_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_REGISTRATION_SCREEN_H_
+#pragma once
#include <string>
@@ -91,6 +92,7 @@ class RegistrationScreen : public ViewScreen<RegistrationView>,
const GURL& referrer,
WindowOpenDisposition disposition,
PageTransition::Type transition);
+ virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
// WebPageScreen implementation:
virtual void CloseScreen(ScreenObserver::ExitCodes code);
diff --git a/chrome/browser/chromeos/login/rounded_rect_painter.cc b/chrome/browser/chromeos/login/rounded_rect_painter.cc
index 3c2c361..a4878e5 100644
--- a/chrome/browser/chromeos/login/rounded_rect_painter.cc
+++ b/chrome/browser/chromeos/login/rounded_rect_painter.cc
@@ -4,11 +4,11 @@
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
-#include "app/resource_bundle.h"
#include "base/logging.h"
#include "gfx/canvas_skia.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/border.h"
#include "views/painter.h"
@@ -16,7 +16,6 @@ namespace chromeos {
namespace {
-const int kCornerRadius = 5;
const SkColor kScreenTopColor = SkColorSetRGB(250, 251, 251);
const SkColor kScreenBottomColor = SkColorSetRGB(204, 209, 212);
const SkColor kScreenShadowColor = SkColorSetARGB(64, 34, 54, 115);
@@ -183,7 +182,48 @@ void RoundedRectBorder::GetInsets(gfx::Insets* insets) const {
insets->Set(inset - shadow / 3, inset, inset + shadow / 3, inset);
}
-} // namespace
+// Simple solid round background.
+class RoundedBackground : public views::Background {
+ public:
+ explicit RoundedBackground(int corner_radius,
+ int stroke_width,
+ const SkColor& background_color,
+ const SkColor& stroke_color)
+ : corner_radius_(corner_radius),
+ stroke_width_(stroke_width),
+ stroke_color_(stroke_color) {
+ SetNativeControlColor(background_color);
+ }
+
+ virtual void Paint(gfx::Canvas* canvas, views::View* view) const {
+ SkRect rect;
+ rect.iset(0, 0, view->width(), view->height());
+ SkPath path;
+ path.addRoundRect(rect,
+ SkIntToScalar(corner_radius_),
+ SkIntToScalar(corner_radius_));
+ // Draw interior.
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setColor(get_color());
+ canvas->AsCanvasSkia()->drawPath(path, paint);
+ // Redraw boundary region with correspoinding color.
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(stroke_width_));
+ paint.setColor(stroke_color_);
+ canvas->AsCanvasSkia()->drawPath(path, paint);
+ }
+
+ private:
+ int corner_radius_;
+ int stroke_width_;
+ SkColor stroke_color_;
+
+ DISALLOW_COPY_AND_ASSIGN(RoundedBackground);
+};
+
+} // namespace
// static
const BorderDefinition BorderDefinition::kScreenBorder = {
@@ -191,7 +231,17 @@ const BorderDefinition BorderDefinition::kScreenBorder = {
SK_ColorBLACK,
kScreenShadow,
kScreenShadowColor,
- kCornerRadius,
+ login::kScreenCornerRadius,
+ kScreenTopColor,
+ kScreenBottomColor
+};
+
+const BorderDefinition BorderDefinition::kUserBorder = {
+ 0,
+ SK_ColorBLACK,
+ 0,
+ kScreenShadowColor,
+ login::kUserCornerRadius,
kScreenTopColor,
kScreenBottomColor
};
@@ -204,4 +254,12 @@ views::Border* CreateWizardBorder(const BorderDefinition* const border) {
return new RoundedRectBorder(border);
}
+views::Background* CreateRoundedBackground(int corner_radius,
+ int stroke_width,
+ SkColor background_color,
+ SkColor stroke_color) {
+ return new RoundedBackground(
+ corner_radius, stroke_width, background_color, stroke_color);
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/rounded_rect_painter.h b/chrome/browser/chromeos/login/rounded_rect_painter.h
index 3788c1b..4bd36ec 100644
--- a/chrome/browser/chromeos/login/rounded_rect_painter.h
+++ b/chrome/browser/chromeos/login/rounded_rect_painter.h
@@ -4,10 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ROUNDED_RECT_PAINTER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_ROUNDED_RECT_PAINTER_H_
+#pragma once
#include "third_party/skia/include/core/SkColor.h"
namespace views {
+class Background;
class Border;
class Painter;
} // namespace views
@@ -24,6 +26,7 @@ struct BorderDefinition {
SkColor bottom_color;
static const BorderDefinition kScreenBorder;
+ static const BorderDefinition kUserBorder;
};
// Creates painter to paint view background with parameters specified.
@@ -32,6 +35,11 @@ views::Painter* CreateWizardPainter(const BorderDefinition* const border);
// that actually draws both border and background.
views::Border* CreateWizardBorder(const BorderDefinition* const border);
+// Creates simple round background.
+views::Background* CreateRoundedBackground(int corner_radius,
+ int stroke_width,
+ SkColor background_color,
+ SkColor stroke_color);
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_ROUNDED_RECT_PAINTER_H_
diff --git a/chrome/browser/chromeos/login/screen_lock_view.cc b/chrome/browser/chromeos/login/screen_lock_view.cc
index f387d48..f7d3330 100644
--- a/chrome/browser/chromeos/login/screen_lock_view.cc
+++ b/chrome/browser/chromeos/login/screen_lock_view.cc
@@ -8,9 +8,12 @@
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/user_view.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
+#include "chrome/browser/profile_manager.h"
#include "chrome/common/notification_service.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -25,6 +28,8 @@ namespace chromeos {
namespace {
+const int kCornerRadius = 5;
+
// A Textfield for password, which also sets focus to itself
// when a mouse is clicked on it. This is necessary in screen locker
// as mouse events are grabbed in the screen locker.
@@ -64,10 +69,17 @@ void ScreenLockView::Init() {
NotificationType::LOGIN_USER_IMAGE_CHANGED,
NotificationService::AllSources());
- user_view_ = new UserView(this, false);
+ user_view_ = new UserView(this,
+ false, // is_login
+ true); // need_background
views::View* main = new views::View();
+ // Use rounded rect background.
+ views::Painter* painter =
+ CreateWizardPainter(&BorderDefinition::kUserBorder);
+
main->set_background(
- views::Background::CreateSolidBackground(login::kBackgroundColor));
+ views::Background::CreateBackgroundPainter(true, painter));
+ main->set_border(CreateWizardBorder(&BorderDefinition::kUserBorder));
// Password field.
password_field_ = new PasswordField();
@@ -184,7 +196,7 @@ bool ScreenLockView::HandleKeystroke(
views::Textfield* sender,
const views::Textfield::Keystroke& keystroke) {
screen_locker_->ClearErrors();
- if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
+ if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
screen_locker_->Authenticate(password_field_->text());
return true;
}
@@ -205,4 +217,10 @@ void ScreenLockView::Observe(
user_view_->SetImage(user->image());
}
+void ScreenLockView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && this == child)
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
+}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screen_lock_view.h b/chrome/browser/chromeos/login/screen_lock_view.h
index eb75d78..e826271 100644
--- a/chrome/browser/chromeos/login/screen_lock_view.h
+++ b/chrome/browser/chromeos/login/screen_lock_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCK_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCK_VIEW_H_
+#pragma once
#include "chrome/browser/chromeos/login/user_view.h"
#include "chrome/common/notification_observer.h"
@@ -67,6 +68,12 @@ class ScreenLockView : public views::View,
// UserView::Delegate implementation:
virtual void OnSignout();
+ protected:
+ // views::View implementation:
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
private:
friend class test::ScreenLockerTester;
diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc
index ebd120d..382f854 100644
--- a/chrome/browser/chromeos/login/screen_locker.cc
+++ b/chrome/browser/chromeos/login/screen_locker.cc
@@ -9,14 +9,19 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/singleton.h"
#include "base/string_util.h"
+#include "base/timer.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
+#include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/authenticator.h"
@@ -26,10 +31,12 @@
#include "chrome/browser/chromeos/login/screen_lock_view.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
+#include "cros/chromeos_wm_ipc_enums.h"
+#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "cros/chromeos_wm_ipc_enums.h"
#include "views/screen.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"
@@ -43,6 +50,9 @@ const int kGrabFailureLimit = 60;
// Each keyboard layout has a dummy input method ID which starts with "xkb:".
const char kValidInputMethodPrefix[] = "xkb:";
+// A idle time to show the screen saver in seconds.
+const int kScreenSaverIdleTimeout = 15;
+
// Observer to start ScreenLocker when the screen lock
class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer,
public NotificationObserver {
@@ -65,6 +75,7 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer,
}
virtual void LockScreen(chromeos::ScreenLockLibrary* obj) {
+ LOG(INFO) << "In: ScreenLockObserver::LockScreen";
SetupInputMethodsForScreenLocker();
chromeos::ScreenLocker::Show();
}
@@ -90,11 +101,21 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer,
saved_active_input_method_list_.empty()) {
chromeos::InputMethodLibrary* language =
chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
+ chromeos::KeyboardLibrary* keyboard =
+ chromeos::CrosLibrary::Get()->GetKeyboardLibrary();
+
saved_previous_input_method_id_ = language->previous_input_method().id;
saved_current_input_method_id_ = language->current_input_method().id;
scoped_ptr<chromeos::InputMethodDescriptors> active_input_method_list(
language->GetActiveInputMethods());
+ const std::string hardware_keyboard =
+ keyboard->GetHardwareKeyboardLayoutName(); // e.g. "xkb:us::eng"
+ // We'll add the hardware keyboard if it's not included in
+ // |active_input_method_list| so that the user can always use the hardware
+ // keyboard on the screen locker.
+ bool should_add_hardware_keyboard = true;
+
chromeos::ImeConfigValue value;
value.type = chromeos::ImeConfigValue::kValueTypeStringList;
for (size_t i = 0; i < active_input_method_list->size(); ++i) {
@@ -105,13 +126,17 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer,
if (!StartsWithASCII(input_method_id, kValidInputMethodPrefix, true))
continue;
value.string_list_value.push_back(input_method_id);
+ if (input_method_id == hardware_keyboard) {
+ should_add_hardware_keyboard = false;
+ }
}
- if (value.string_list_value.empty()) {
- value.string_list_value.push_back(kFallbackInputMethodId); // US qwerty
+ if (should_add_hardware_keyboard) {
+ value.string_list_value.push_back(hardware_keyboard);
}
- language->SetImeConfig(chromeos::kGeneralSectionName,
- chromeos::kPreloadEnginesConfigName,
- value);
+ language->SetImeConfig(
+ chromeos::language_prefs::kGeneralSectionName,
+ chromeos::language_prefs::kPreloadEnginesConfigName,
+ value);
}
}
@@ -124,9 +149,10 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer,
chromeos::ImeConfigValue value;
value.type = chromeos::ImeConfigValue::kValueTypeStringList;
value.string_list_value = saved_active_input_method_list_;
- language->SetImeConfig(chromeos::kGeneralSectionName,
- chromeos::kPreloadEnginesConfigName,
- value);
+ language->SetImeConfig(
+ chromeos::language_prefs::kGeneralSectionName,
+ chromeos::language_prefs::kPreloadEnginesConfigName,
+ value);
// Send previous input method id first so Ctrl+space would work fine.
if (!saved_previous_input_method_id_.empty())
language->ChangeInputMethod(saved_previous_input_method_id_);
@@ -169,6 +195,11 @@ class LockWindow : public views::WidgetGtk {
return false;
}
+ virtual void OnDestroy(GtkWidget* object) {
+ LOG(INFO) << "OnDestroy: LockWindow destroyed";
+ views::WidgetGtk::OnDestroy(object);
+ }
+
virtual void ClearNativeFocus() {
DCHECK(toplevel_focus_widget_);
gtk_widget_grab_focus(toplevel_focus_widget_);
@@ -206,6 +237,11 @@ class GrabWidget : public views::WidgetGtk {
virtual void Show() {
views::WidgetGtk::Show();
+ // Now steal all inputs.
+ TryGrabAllInputs();
+ }
+
+ void ClearGrab() {
GtkWidget* current_grab_window;
// Grab gtk input first so that the menu holding grab will close itself.
gtk_grab_add(window_contents());
@@ -217,9 +253,6 @@ class GrabWidget : public views::WidgetGtk {
// until it's empty.
while ((current_grab_window = gtk_grab_get_current()) != NULL)
gtk_grab_remove(current_grab_window);
-
- // Now steal all inputs.
- TryGrabAllInputs();
}
virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) {
@@ -256,9 +289,12 @@ class GrabWidget : public views::WidgetGtk {
};
void GrabWidget::TryGrabAllInputs() {
- if (kbd_grab_status_ != GDK_GRAB_SUCCESS)
+ ClearGrab();
+
+ if (kbd_grab_status_ != GDK_GRAB_SUCCESS) {
kbd_grab_status_ = gdk_keyboard_grab(window_contents()->window, FALSE,
GDK_CURRENT_TIME);
+ }
if (mouse_grab_status_ != GDK_GRAB_SUCCESS) {
mouse_grab_status_ =
gdk_pointer_grab(window_contents()->window,
@@ -273,8 +309,8 @@ void GrabWidget::TryGrabAllInputs() {
if ((kbd_grab_status_ != GDK_GRAB_SUCCESS ||
mouse_grab_status_ != GDK_GRAB_SUCCESS) &&
grab_failure_count_++ < kGrabFailureLimit) {
- DLOG(WARNING) << "Failed to grab inputs. Trying again in 1 second: kbd="
- << kbd_grab_status_ << ", mouse=" << mouse_grab_status_;
+ LOG(WARNING) << "Failed to grab inputs. Trying again in 1 second: kbd="
+ << kbd_grab_status_ << ", mouse=" << mouse_grab_status_;
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
task_factory_.NewRunnableMethod(&GrabWidget::TryGrabAllInputs),
@@ -293,7 +329,7 @@ void GrabWidget::TryGrabAllInputs() {
// addition to other background components.
class ScreenLockerBackgroundView : public chromeos::BackgroundView {
public:
- ScreenLockerBackgroundView(views::WidgetGtk* lock_widget)
+ explicit ScreenLockerBackgroundView(views::WidgetGtk* lock_widget)
: lock_widget_(lock_widget) {
}
@@ -330,23 +366,30 @@ ScreenLocker* ScreenLocker::screen_locker_ = NULL;
// See screen_locker.h for more details.
class MouseEventRelay : public MessageLoopForUI::Observer {
public:
- MouseEventRelay(GdkWindow* src, GdkWindow* dest) : src_(src), dest_(dest) {
+ MouseEventRelay(GdkWindow* src, GdkWindow* dest)
+ : src_(src),
+ dest_(dest),
+ initialized_(false) {
DCHECK(src_);
DCHECK(dest_);
- gint src_x, src_y, dest_x, dest_y, width, height, depth;
- gdk_window_get_geometry(src_, &src_x, &src_y, &width, &height, &depth);
- gdk_window_get_geometry(dest_, &dest_x, &dest_y, &width, &height, &depth);
-
- offset_.SetPoint(dest_x - src_x, dest_y - src_y);
}
virtual void WillProcessEvent(GdkEvent* event) {}
virtual void DidProcessEvent(GdkEvent* event) {
- if (event->any.window != src_) {
+ if (event->any.window != src_)
return;
+ if (!initialized_) {
+ gint src_x, src_y, dest_x, dest_y, width, height, depth;
+ gdk_window_get_geometry(dest_, &dest_x, &dest_y, &width, &height, &depth);
+ // wait to compute offset until the info bubble widget's location
+ // is available.
+ if (dest_x < 0 || dest_y < 0)
+ return;
+ gdk_window_get_geometry(src_, &src_x, &src_y, &width, &height, &depth);
+ offset_.SetPoint(dest_x - src_x, dest_y - src_y);
+ initialized_ = true;
}
-
if (event->type == GDK_BUTTON_PRESS ||
event->type == GDK_BUTTON_RELEASE) {
GdkEvent* copy = gdk_event_copy(event);
@@ -359,8 +402,8 @@ class MouseEventRelay : public MessageLoopForUI::Observer {
gdk_event_free(copy);
} else if (event->type == GDK_MOTION_NOTIFY) {
GdkEvent* copy = gdk_event_copy(event);
- copy->button.window = dest_;
- g_object_ref(copy->button.window);
+ copy->motion.window = dest_;
+ g_object_ref(copy->motion.window);
copy->motion.x -= offset_.x();
copy->motion.y -= offset_.y();
@@ -372,6 +415,7 @@ class MouseEventRelay : public MessageLoopForUI::Observer {
private:
GdkWindow* src_;
GdkWindow* dest_;
+ bool initialized_;
// Offset from src_'s origin to dest_'s origin.
gfx::Point offset_;
@@ -381,6 +425,7 @@ class MouseEventRelay : public MessageLoopForUI::Observer {
// A event observer used to unlock the screen upon user's action
// without asking password. Used in BWSI and auto login mode.
+// TODO(oshima): consolidate InputEventObserver and LockerInputEventObserver.
class InputEventObserver : public MessageLoopForUI::Observer {
public:
explicit InputEventObserver(ScreenLocker* screen_locker)
@@ -411,7 +456,42 @@ class InputEventObserver : public MessageLoopForUI::Observer {
DISALLOW_COPY_AND_ASSIGN(InputEventObserver);
};
-////////////////////////////////////////////////////////////////////////////////
+// A event observer used to show the screen locker upon
+// user action: mouse or keyboard interactions.
+// TODO(oshima): this has to be disabled while authenticating.
+class LockerInputEventObserver : public MessageLoopForUI::Observer {
+ public:
+ explicit LockerInputEventObserver(ScreenLocker* screen_locker)
+ : screen_locker_(screen_locker),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ timer_(base::TimeDelta::FromSeconds(kScreenSaverIdleTimeout), this,
+ &LockerInputEventObserver::StartScreenSaver)) {
+ }
+
+ virtual void WillProcessEvent(GdkEvent* event) {
+ if ((event->type == GDK_KEY_PRESS ||
+ event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_MOTION_NOTIFY)) {
+ timer_.Reset();
+ screen_locker_->StopScreenSaver();
+ }
+ }
+
+ virtual void DidProcessEvent(GdkEvent* event) {
+ }
+
+ private:
+ void StartScreenSaver() {
+ screen_locker_->StartScreenSaver();
+ }
+
+ chromeos::ScreenLocker* screen_locker_;
+ base::DelayTimer<LockerInputEventObserver> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(LockerInputEventObserver);
+};
+
+//////////////////////////////////////////////////////////////////////////////
// ScreenLocker, public:
ScreenLocker::ScreenLocker(const UserManager::User& user)
@@ -461,14 +541,20 @@ void ScreenLocker::Init() {
lock_widget_->GetRootView()->SetVisible(false);
lock_widget_->Show();
- views::View* screen = new ScreenLockerBackgroundView(lock_widget_);
+ // Configuring the background url.
+ std::string url_string =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kScreenSaverUrl);
+ background_view_ = new ScreenLockerBackgroundView(lock_widget_);
+ background_view_->Init(GURL(url_string));
DCHECK(GTK_WIDGET_REALIZED(lock_window_->GetNativeView()));
WmIpc::instance()->SetWindowType(
lock_window_->GetNativeView(),
WM_IPC_WINDOW_CHROME_SCREEN_LOCKER,
NULL);
- lock_window_->SetContentsView(screen);
+
+ lock_window_->SetContentsView(background_view_);
lock_window_->Show();
// Don't let X draw default background, which was causing flash on
@@ -480,7 +566,7 @@ void ScreenLocker::Init() {
lock_window->set_toplevel_focus_widget(lock_widget_->window_contents());
}
-void ScreenLocker::OnLoginFailure(const std::string& error) {
+void ScreenLocker::OnLoginFailure(const LoginFailure& error) {
DLOG(INFO) << "OnLoginFailure";
EnableInput();
// Don't enable signout button here as we're showing
@@ -494,8 +580,9 @@ void ScreenLocker::OnLoginFailure(const std::string& error) {
if (error_info_)
error_info_->Close();
std::wstring msg = l10n_util::GetString(IDS_LOGIN_ERROR_AUTHENTICATING);
- if (!error.empty())
- msg += L"\n" + ASCIIToWide(error);
+ const std::string error_text = error.GetErrorString();
+ if (!error_text.empty())
+ msg += L"\n" + ASCIIToWide(error_text);
InputMethodLibrary* input_method_library =
CrosLibrary::Get()->GetInputMethodLibrary();
@@ -508,6 +595,7 @@ void ScreenLocker::OnLoginFailure(const std::string& error) {
BubbleBorder::BOTTOM_LEFT,
ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
msg,
+ std::wstring(), // TODO: add help link
this);
if (mouse_event_relay_.get()) {
MessageLoopForUI::current()->RemoveObserver(mouse_event_relay_.get());
@@ -520,9 +608,7 @@ void ScreenLocker::OnLoginFailure(const std::string& error) {
void ScreenLocker::OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& unused) {
-
- DLOG(INFO) << "OnLoginSuccess";
-
+ LOG(INFO) << "OnLoginSuccess: Sending Unlock request.";
if (CrosLibrary::Get()->EnsureLoaded())
CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenUnlockRequested();
}
@@ -565,7 +651,9 @@ void ScreenLocker::EnableInput() {
void ScreenLocker::Signout() {
if (!error_info_) {
// TODO(oshima): record this action in user metrics.
- BrowserList::CloseAllBrowsersAndExit();
+ if (CrosLibrary::Get()->EnsureLoaded()) {
+ CrosLibrary::Get()->GetLoginLibrary()->StopSession("");
+ }
// Don't hide yet the locker because the chrome screen may become visible
// briefly.
@@ -581,25 +669,27 @@ void ScreenLocker::OnGrabInputs() {
// static
void ScreenLocker::Show() {
+ LOG(INFO) << "In ScreenLocker::Show";
DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
// Exit fullscreen.
Browser* browser = BrowserList::GetLastActive();
- DCHECK(browser);
- if (browser->window()->IsFullscreen()) {
+ // browser can be NULL if we receive a lock request before the first browser
+ // window is shown.
+ if (browser && browser->window()->IsFullscreen()) {
browser->ToggleFullscreenMode();
}
- // TODO(oshima): Currently, PowerManager may send a lock screen event
- // even if a screen is locked. Investigate & solve the issue and
- // enable this again if it's possible.
- // DCHECK(!screen_locker_);
if (!screen_locker_) {
+ LOG(INFO) << "Show: Locking screen";
ScreenLocker* locker =
new ScreenLocker(UserManager::Get()->logged_in_user());
locker->Init();
} else {
- LOG(INFO) << "Show(): screen locker already exists. "
+ // PowerManager re-sends lock screen signal if it doesn't
+ // receive the response within timeout. Just send complete
+ // signal.
+ LOG(INFO) << "Show: locker already exists. "
<< "just sending completion event";
if (CrosLibrary::Get()->EnsureLoaded())
CrosLibrary::Get()->GetScreenLockLibrary()->NotifyScreenLockCompleted();
@@ -610,7 +700,7 @@ void ScreenLocker::Show() {
void ScreenLocker::Hide() {
DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
DCHECK(screen_locker_);
- LOG(INFO) << "Hide Screen Locker:" << screen_locker_;
+ LOG(INFO) << "Hide: Deleting ScreenLocker:" << screen_locker_;
MessageLoopForUI::current()->DeleteSoon(FROM_HERE, screen_locker_);
}
@@ -618,13 +708,17 @@ void ScreenLocker::Hide() {
void ScreenLocker::UnlockScreenFailed() {
DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
if (screen_locker_) {
+ // Power manager decided no to unlock the screen even if a user
+ // typed in password, for example, when a user closed the lid
+ // immediately after typing in the password.
+ LOG(INFO) << "UnlockScreenFailed: re-enabling screen locker";
screen_locker_->EnableInput();
} else {
// This can happen when a user requested unlock, but PowerManager
// rejected because the computer is closed, then PowerManager unlocked
// because it's open again and the above failure message arrives.
// This'd be extremely rare, but may still happen.
- LOG(INFO) << "Screen is unlocked";
+ LOG(INFO) << "UnlockScreenFailed: screen is already unlocked.";
}
}
@@ -641,12 +735,18 @@ ScreenLocker::~ScreenLocker() {
ClearErrors();
if (input_event_observer_.get())
MessageLoopForUI::current()->RemoveObserver(input_event_observer_.get());
+ if (locker_input_event_observer_.get()) {
+ lock_widget_->GetFocusManager()->UnregisterAccelerator(
+ views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+ MessageLoopForUI::current()->RemoveObserver(
+ locker_input_event_observer_.get());
+ }
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
gdk_pointer_ungrab(GDK_CURRENT_TIME);
DCHECK(lock_window_);
- LOG(INFO) << "Closing ScreenLocker window";
+ LOG(INFO) << "~ScreenLocker(): Closing ScreenLocker window";
lock_window_->Close();
// lock_widget_ will be deleted by gtk's destroy signal.
screen_locker_ = NULL;
@@ -664,10 +764,20 @@ void ScreenLocker::SetAuthenticator(Authenticator* authenticator) {
}
void ScreenLocker::ScreenLockReady() {
- DLOG(INFO) << "ScreenLockReady";
+ LOG(INFO) << "ScreenLockReady: sending completed signal to power manager.";
// Don't show the password field until we grab all inputs.
lock_widget_->GetRootView()->SetVisible(true);
- EnableInput();
+ if (background_view_->ScreenSaverEnabled()) {
+ lock_widget_->GetFocusManager()->RegisterAccelerator(
+ views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
+ locker_input_event_observer_.reset(new LockerInputEventObserver(this));
+ MessageLoopForUI::current()->AddObserver(
+ locker_input_event_observer_.get());
+ StartScreenSaver();
+ } else {
+ EnableInput();
+ }
+
bool state = true;
NotificationService::current()->Notify(
NotificationType::SCREEN_LOCK_STATE_CHANGED,
@@ -692,4 +802,36 @@ void ScreenLocker::OnWindowManagerReady() {
ScreenLockReady();
}
+void ScreenLocker::StopScreenSaver() {
+ if (background_view_->IsScreenSaverVisible()) {
+ LOG(INFO) << "StopScreenSaver";
+ background_view_->HideScreenSaver();
+ if (screen_lock_view_) {
+ screen_lock_view_->SetVisible(true);
+ screen_lock_view_->RequestFocus();
+ }
+ EnableInput();
+ }
+}
+
+void ScreenLocker::StartScreenSaver() {
+ if (!background_view_->IsScreenSaverVisible()) {
+ LOG(INFO) << "StartScreenSaver";
+ background_view_->ShowScreenSaver();
+ if (screen_lock_view_) {
+ screen_lock_view_->SetEnabled(false);
+ screen_lock_view_->SetVisible(false);
+ }
+ ClearErrors();
+ }
+}
+
+bool ScreenLocker::AcceleratorPressed(const views::Accelerator& accelerator) {
+ if (!background_view_->IsScreenSaverVisible()) {
+ StartScreenSaver();
+ return true;
+ }
+ return false;
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h
index f2681b7..5162263 100644
--- a/chrome/browser/chromeos/login/screen_locker.h
+++ b/chrome/browser/chromeos/login/screen_locker.h
@@ -4,13 +4,15 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_H_
+#pragma once
#include <string>
#include "base/task.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
+#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "views/accelerator.h"
namespace gfx {
class Rect;
@@ -23,10 +25,13 @@ class WidgetGtk;
namespace chromeos {
class Authenticator;
+class BackgroundView;
class InputEventObserver;
+class LockerInputEventObserver;
class MessageBubble;
class MouseEventRelay;
class ScreenLockView;
+class LoginFailure;
namespace test {
class ScreenLockerTester;
@@ -36,7 +41,8 @@ class ScreenLockerTester;
// authenticate the user. ScreenLocker manages its life cycle and will
// delete itself when it's unlocked.
class ScreenLocker : public LoginStatusConsumer,
- public InfoBubbleDelegate {
+ public MessageBubbleDelegate,
+ public views::AcceleratorTarget {
public:
explicit ScreenLocker(const UserManager::User& user);
@@ -44,7 +50,7 @@ class ScreenLocker : public LoginStatusConsumer,
void Init();
// LoginStatusConsumer implements:
- virtual void OnLoginFailure(const std::string& error);
+ virtual void OnLoginFailure(const chromeos::LoginFailure& error);
virtual void OnLoginSuccess(const std::string& username,
const GaiaAuthConsumer::ClientLoginResult& result);
@@ -53,6 +59,7 @@ class ScreenLocker : public LoginStatusConsumer,
bool closed_by_escape);
virtual bool CloseOnEscape() { return true; }
virtual bool FadeInOnShow() { return false; }
+ virtual void OnHelpLinkActivated() {}
// Authenticates the user with given |password| and authenticator.
void Authenticate(const string16& password);
@@ -94,6 +101,7 @@ class ScreenLocker : public LoginStatusConsumer,
private:
friend class DeleteTask<ScreenLocker>;
friend class test::ScreenLockerTester;
+ friend class LockerInputEventObserver;
virtual ~ScreenLocker();
@@ -106,6 +114,15 @@ class ScreenLocker : public LoginStatusConsumer,
// Called when the window manager is ready to handle locked state.
void OnWindowManagerReady();
+ // Stops screen saver.
+ void StopScreenSaver();
+
+ // Starts screen saver.
+ void StartScreenSaver();
+
+ // Overridden from AcceleratorTarget:
+ virtual bool AcceleratorPressed(const views::Accelerator& accelerator);
+
// Event handler for client-event.
CHROMEGTK_CALLBACK_1(ScreenLocker, void, OnClientEvent, GdkEventClient*);
@@ -118,6 +135,9 @@ class ScreenLocker : public LoginStatusConsumer,
// A view that accepts password.
ScreenLockView* screen_lock_view_;
+ // A view that can display html page as background.
+ BackgroundView* background_view_;
+
// Logged in user.
UserManager::User user_;
@@ -134,6 +154,10 @@ class ScreenLocker : public LoginStatusConsumer,
// Used when |unlock_on_input_| is true.
scoped_ptr<InputEventObserver> input_event_observer_;
+ // A message loop observer to detect user's keyboard/mouse event.
+ // Used when to show the screen locker upon such an event.
+ scoped_ptr<LockerInputEventObserver> locker_input_event_observer_;
+
// An info bubble to display login failure message.
MessageBubble* error_info_;
diff --git a/chrome/browser/chromeos/login/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
index 01b615c..2b0258b 100644
--- a/chrome/browser/chromeos/login/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/automation/ui_controls.h"
@@ -9,11 +10,11 @@
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
-#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
#include "chrome/browser/chromeos/cros/mock_input_method_library.h"
+#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
+#include "chrome/browser/chromeos/login/mock_authenticator.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/screen_locker_tester.h"
-#include "chrome/browser/chromeos/login/mock_authenticator.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/views/browser_dialogs.h"
#include "chrome/common/chrome_switches.h"
@@ -30,7 +31,7 @@ namespace {
// An object that wait for lock state and fullscreen state.
class Waiter : public NotificationObserver {
public:
- Waiter(Browser* browser)
+ explicit Waiter(Browser* browser)
: browser_(browser) {
registrar_.Add(this,
NotificationType::SCREEN_LOCK_STATE_CHANGED,
@@ -90,9 +91,13 @@ namespace chromeos {
class ScreenLockerTest : public CrosInProcessBrowserTest {
public:
- ScreenLockerTest() {}
+ ScreenLockerTest() : mock_screen_lock_library_(NULL),
+ mock_input_method_library_(NULL) {
+ }
protected:
+ MockScreenLockLibrary *mock_screen_lock_library_;
+ MockInputMethodLibrary *mock_input_method_library_;
// Test the no password mode with different unlock scheme given by
// |unlock| function.
@@ -125,8 +130,10 @@ class ScreenLockerTest : public CrosInProcessBrowserTest {
private:
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
- InitMockScreenLockLibrary();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->InitMockScreenLockLibrary();
+ mock_screen_lock_library_ = cros_mock_->mock_screen_lock_library();
+ mock_input_method_library_ = cros_mock_->mock_input_method_library();
EXPECT_CALL(*mock_screen_lock_library_, AddObserver(testing::_))
.Times(1)
.RetiresOnSaturation();
@@ -134,13 +141,13 @@ class ScreenLockerTest : public CrosInProcessBrowserTest {
.Times(1)
.RetiresOnSaturation();
// Expectations for the status are on the screen lock window.
- SetStatusAreaMocksExpectations();
+ cros_mock_->SetStatusAreaMocksExpectations();
// Expectations for the status area on the browser window.
- SetStatusAreaMocksExpectations();
+ cros_mock_->SetStatusAreaMocksExpectations();
}
virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitchWithValue(switches::kLoginProfile, "user");
+ command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
command_line->AppendSwitch(switches::kNoFirstRun);
}
@@ -165,6 +172,14 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) {
ui_test_utils::WaitForNotification(
NotificationType::SCREEN_LOCK_STATE_CHANGED);
+ // Test to make sure that the widget is actually appearing and is of
+ // reasonable size, preventing a regression of
+ // http://code.google.com/p/chromium-os/issues/detail?id=5987
+ gfx::Rect lock_bounds;
+ tester->GetChildWidget()->GetBounds(&lock_bounds, true);
+ EXPECT_GT(lock_bounds.width(), 10);
+ EXPECT_GT(lock_bounds.height(), 10);
+
tester->InjectMockAuthenticator("user", "pass");
EXPECT_TRUE(tester->IsLocked());
tester->EnterPassword("fail");
@@ -208,6 +223,7 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) {
}
tester->InjectMockAuthenticator("user", "pass");
tester->EnterPassword("pass");
+ ui_test_utils::RunAllPendingInMessageLoop();
ScreenLocker::Hide();
ui_test_utils::RunAllPendingInMessageLoop();
EXPECT_FALSE(tester->IsLocked());
@@ -231,7 +247,7 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseClick) {
void KeyPress(views::Widget* widget) {
ui_controls::SendKeyPress(GTK_WINDOW(widget->GetNativeView()),
- base::VKEY_SPACE, false, false, false, false);
+ app::VKEY_SPACE, false, false, false, false);
}
IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithKeyPress) {
diff --git a/chrome/browser/chromeos/login/screen_locker_tester.cc b/chrome/browser/chromeos/login/screen_locker_tester.cc
index 8172fb9..aeec099 100644
--- a/chrome/browser/chromeos/login/screen_locker_tester.cc
+++ b/chrome/browser/chromeos/login/screen_locker_tester.cc
@@ -6,16 +6,16 @@
#include <gdk/gdkkeysyms.h>
-#include "app/l10n_util.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/mock_authenticator.h"
-#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/screen_lock_view.h"
+#include "chrome/browser/chromeos/login/screen_locker.h"
#include "views/controls/button/button.h"
#include "views/controls/label.h"
#include "views/controls/textfield/textfield.h"
-#include "views/widget/widget_gtk.h"
#include "views/widget/root_view.h"
+#include "views/widget/widget_gtk.h"
namespace chromeos {
@@ -65,6 +65,11 @@ views::Widget* ScreenLockerTester::GetWidget() {
return ScreenLocker::screen_locker_->lock_window_;
}
+views::Widget* ScreenLockerTester::GetChildWidget() {
+ DCHECK(ScreenLocker::screen_locker_);
+ return ScreenLocker::screen_locker_->lock_widget_;
+}
+
} // namespace test
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screen_locker_tester.h b/chrome/browser/chromeos/login/screen_locker_tester.h
index 33dc41e..bc8800e 100644
--- a/chrome/browser/chromeos/login/screen_locker_tester.h
+++ b/chrome/browser/chromeos/login/screen_locker_tester.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_TESTER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_LOCKER_TESTER_H_
+#pragma once
#include "base/basictypes.h"
@@ -38,6 +39,8 @@ class ScreenLockerTester {
// Returns the widget for screen locker window.
views::Widget* GetWidget();
+ views::Widget* GetChildWidget();
+
private:
friend class chromeos::ScreenLocker;
diff --git a/chrome/browser/chromeos/login/screen_observer.h b/chrome/browser/chromeos/login/screen_observer.h
index 85875f1..4cba1bb 100644
--- a/chrome/browser/chromeos/login/screen_observer.h
+++ b/chrome/browser/chromeos/login/screen_observer.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREEN_OBSERVER_H_
+#pragma once
#include <string>
@@ -34,6 +35,7 @@ class ScreenObserver {
USER_IMAGE_SELECTED,
USER_IMAGE_SKIPPED,
EULA_ACCEPTED,
+ EULA_BACK,
REGISTRATION_SUCCESS,
REGISTRATION_SKIPPED,
EXIT_CODES_COUNT // not a real code, must be the last
diff --git a/chrome/browser/chromeos/login/update_screen.cc b/chrome/browser/chromeos/login/update_screen.cc
index 8e9a05a..20b04b0 100644
--- a/chrome/browser/chromeos/login/update_screen.cc
+++ b/chrome/browser/chromeos/login/update_screen.cc
@@ -5,18 +5,24 @@
#include "chrome/browser/chromeos/login/update_screen.h"
#include "base/logging.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/chromeos/login/update_view.h"
namespace {
-// Update window should appear for at least kMinimalUpdateTime seconds.
-const int kMinimalUpdateTime = 3;
+// Progress bar stages. Each represents progress bar value
+// at the beginning of each stage.
+// TODO(nkostylev): Base stage progress values on approximate time.
+// TODO(nkostylev): Animate progress during each state.
+const int kBeforeUpdateCheckProgress = 7;
+const int kBeforeDownloadProgress = 14;
+const int kBeforeVerifyingProgress = 74;
+const int kBeforeFinalizingProgress = 81;
+const int kProgressComplete = 100;
-// Progress bar increment step.
-const int kBeforeUpdateCheckProgressIncrement = 10;
-const int kAfterUpdateCheckProgressIncrement = 10;
-const int kUpdateCompleteProgressIncrement = 75;
+// Defines what part of update progress does download part takes.
+const int kDownloadProgressIncrement = 60;
} // anonymous namespace
@@ -24,64 +30,64 @@ namespace chromeos {
UpdateScreen::UpdateScreen(WizardScreenDelegate* delegate)
: DefaultViewScreen<chromeos::UpdateView>(delegate),
- update_result_(UPGRADE_STARTED),
- update_error_(GOOGLE_UPDATE_NO_ERROR),
- checking_for_update_(true) {
+ checking_for_update_(true),
+ maximal_curtain_time_(0),
+ reboot_check_delay_(0) {
}
UpdateScreen::~UpdateScreen() {
// Remove pointer to this object from view.
if (view())
view()->set_controller(NULL);
- // Google Updater is holding a pointer to us until it reports status,
- // so we need to remove it in case we were still listening.
- if (google_updater_.get())
- google_updater_->set_status_listener(NULL);
+ CrosLibrary::Get()->GetUpdateLibrary()->RemoveObserver(this);
}
-void UpdateScreen::OnReportResults(GoogleUpdateUpgradeResult result,
- GoogleUpdateErrorCode error_code,
- const std::wstring& version) {
- // Drop the last reference to the object so that it gets cleaned up here.
- if (google_updater_.get()) {
- google_updater_->set_status_listener(NULL);
- google_updater_ = NULL;
+void UpdateScreen::UpdateStatusChanged(UpdateLibrary* library) {
+ UpdateStatusOperation status = library->status().status;
+ if (checking_for_update_ && status > UPDATE_STATUS_CHECKING_FOR_UPDATE) {
+ checking_for_update_ = false;
}
- // Depending on the result decide what to do next.
- update_result_ = result;
- update_error_ = error_code;
- LOG(INFO) << "Update result: " << result;
- if (error_code != GOOGLE_UPDATE_NO_ERROR)
- LOG(INFO) << "Update error code: " << error_code;
- LOG(INFO) << "Update version: " << version;
- switch (update_result_) {
- case UPGRADE_IS_AVAILABLE:
- checking_for_update_ = false;
- // Advance view progress bar.
- view()->AddProgress(kAfterUpdateCheckProgressIncrement);
- // Create new Google Updater instance and install the update.
- google_updater_ = CreateGoogleUpdate();
- google_updater_->CheckForUpdate(true, NULL);
- LOG(INFO) << "Installing an update";
+
+ switch (status) {
+ case UPDATE_STATUS_CHECKING_FOR_UPDATE:
+ // Do nothing in these cases, we don't want to notify the user of the
+ // check unless there is an update.
break;
- case UPGRADE_SUCCESSFUL:
- view()->AddProgress(kUpdateCompleteProgressIncrement);
- minimal_update_time_timer_.Stop();
- checking_for_update_ = false;
- // TODO(nkostylev): Call reboot API. http://crosbug.com/4002
- ExitUpdate();
+ case UPDATE_STATUS_UPDATE_AVAILABLE:
+ view()->SetProgress(kBeforeDownloadProgress);
+ LOG(INFO) << "Update available: " << library->status().new_version;
break;
- case UPGRADE_ALREADY_UP_TO_DATE:
- checking_for_update_ = false;
- view()->AddProgress(kAfterUpdateCheckProgressIncrement);
- // Fall through.
- case UPGRADE_ERROR:
- if (MinimalUpdateTimeElapsed()) {
- ExitUpdate();
+ case UPDATE_STATUS_DOWNLOADING:
+ {
+ view()->ShowCurtain(false);
+ int download_progress = static_cast<int>(
+ library->status().download_progress * kDownloadProgressIncrement);
+ view()->SetProgress(kBeforeDownloadProgress + download_progress);
}
break;
+ case UPDATE_STATUS_VERIFYING:
+ view()->SetProgress(kBeforeVerifyingProgress);
+ break;
+ case UPDATE_STATUS_FINALIZING:
+ view()->SetProgress(kBeforeFinalizingProgress);
+ break;
+ case UPDATE_STATUS_UPDATED_NEED_REBOOT:
+ view()->SetProgress(kProgressComplete);
+ view()->ShowCurtain(false);
+ CrosLibrary::Get()->GetUpdateLibrary()->RebootAfterUpdate();
+ LOG(INFO) << "Reboot API was called. Waiting for reboot.";
+ reboot_timer_.Start(base::TimeDelta::FromSeconds(reboot_check_delay_),
+ this,
+ &UpdateScreen::OnWaitForRebootTimeElapsed);
+ break;
+ case UPDATE_STATUS_IDLE:
+ case UPDATE_STATUS_ERROR:
+ case UPDATE_STATUS_REPORTING_ERROR_EVENT:
+ ExitUpdate();
+ break;
default:
NOTREACHED();
+ break;
}
}
@@ -90,72 +96,81 @@ void UpdateScreen::StartUpdate() {
view()->Reset();
view()->set_controller(this);
- // Start the minimal update time timer.
- minimal_update_time_timer_.Start(
- base::TimeDelta::FromSeconds(kMinimalUpdateTime),
- this,
- &UpdateScreen::OnMinimalUpdateTimeElapsed);
-
- // Create Google Updater object and check if there is an update available.
- checking_for_update_ = true;
- google_updater_ = CreateGoogleUpdate();
- google_updater_->CheckForUpdate(false, NULL);
- view()->AddProgress(kBeforeUpdateCheckProgressIncrement);
- LOG(INFO) << "Checking for update";
+ // Start the maximal curtain time timer.
+ if (maximal_curtain_time_ > 0) {
+ maximal_curtain_time_timer_.Start(
+ base::TimeDelta::FromSeconds(maximal_curtain_time_),
+ this,
+ &UpdateScreen::OnMaximalCurtainTimeElapsed);
+ } else {
+ view()->ShowCurtain(false);
+ }
+
+ view()->SetProgress(kBeforeUpdateCheckProgress);
+
+ if (!CrosLibrary::Get()->EnsureLoaded()) {
+ LOG(ERROR) << "Error loading CrosLibrary";
+ } else {
+ CrosLibrary::Get()->GetUpdateLibrary()->AddObserver(this);
+ LOG(INFO) << "Checking for update";
+ if (!CrosLibrary::Get()->GetUpdateLibrary()->CheckForUpdate()) {
+ ExitUpdate();
+ }
+ }
}
void UpdateScreen::CancelUpdate() {
#if !defined(OFFICIAL_BUILD)
- update_result_ = UPGRADE_ALREADY_UP_TO_DATE;
- update_error_ = GOOGLE_UPDATE_NO_ERROR;
ExitUpdate();
#endif
}
void UpdateScreen::ExitUpdate() {
- if (google_updater_.get()) {
- google_updater_->set_status_listener(NULL);
- google_updater_ = NULL;
- }
- minimal_update_time_timer_.Stop();
+ maximal_curtain_time_timer_.Stop();
ScreenObserver* observer = delegate()->GetObserver(this);
- if (observer) {
- switch (update_result_) {
- case UPGRADE_ALREADY_UP_TO_DATE:
- observer->OnExit(ScreenObserver::UPDATE_NOUPDATE);
- break;
- case UPGRADE_SUCCESSFUL:
- observer->OnExit(ScreenObserver::UPDATE_INSTALLED);
- break;
- case UPGRADE_ERROR:
- if (checking_for_update_) {
- observer->OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE);
- } else {
- observer->OnExit(ScreenObserver::UPDATE_ERROR_UPDATING);
- }
- break;
- default:
- NOTREACHED();
- }
+
+ if (!CrosLibrary::Get()->EnsureLoaded()) {
+ observer->OnExit(ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE);
+ }
+
+ UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary();
+ update_library->RemoveObserver(this);
+ switch (update_library->status().status) {
+ case UPDATE_STATUS_IDLE:
+ observer->OnExit(ScreenObserver::UPDATE_NOUPDATE);
+ break;
+ case UPDATE_STATUS_ERROR:
+ case UPDATE_STATUS_REPORTING_ERROR_EVENT:
+ observer->OnExit(checking_for_update_ ?
+ ScreenObserver::UPDATE_ERROR_CHECKING_FOR_UPDATE :
+ ScreenObserver::UPDATE_ERROR_UPDATING);
+ break;
+ default:
+ NOTREACHED();
}
}
-bool UpdateScreen::MinimalUpdateTimeElapsed() {
- return !minimal_update_time_timer_.IsRunning();
+void UpdateScreen::OnMaximalCurtainTimeElapsed() {
+ view()->ShowCurtain(false);
}
-GoogleUpdate* UpdateScreen::CreateGoogleUpdate() {
- GoogleUpdate* updater = new GoogleUpdate();
- updater->set_status_listener(this);
- return updater;
+void UpdateScreen::OnWaitForRebootTimeElapsed() {
+ LOG(ERROR) << "Unable to reboot - asking user for a manual reboot.";
+ view()->ShowManualRebootInfo();
}
-void UpdateScreen::OnMinimalUpdateTimeElapsed() {
- if (update_result_ == UPGRADE_SUCCESSFUL ||
- update_result_ == UPGRADE_ALREADY_UP_TO_DATE ||
- update_result_ == UPGRADE_ERROR) {
- ExitUpdate();
- }
+void UpdateScreen::SetMaximalCurtainTime(int seconds) {
+ if (seconds <= 0)
+ maximal_curtain_time_timer_.Stop();
+ DCHECK(!maximal_curtain_time_timer_.IsRunning());
+ maximal_curtain_time_ = seconds;
+}
+
+void UpdateScreen::SetRebootCheckDelay(int seconds) {
+ if (seconds <= 0)
+ reboot_timer_.Stop();
+ DCHECK(!reboot_timer_.IsRunning());
+ reboot_check_delay_ = seconds;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/update_screen.h b/chrome/browser/chromeos/login/update_screen.h
index 825a2b5..2253c2e 100644
--- a/chrome/browser/chromeos/login/update_screen.h
+++ b/chrome/browser/chromeos/login/update_screen.h
@@ -4,12 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UPDATE_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_UPDATE_SCREEN_H_
+#pragma once
-#include "base/ref_counted.h"
#include "base/timer.h"
+#include "chrome/browser/chromeos/cros/update_library.h"
#include "chrome/browser/chromeos/login/update_view.h"
#include "chrome/browser/chromeos/login/view_screen.h"
-#include "chrome/browser/google_update.h"
namespace chromeos {
@@ -22,16 +22,14 @@ class UpdateController {
};
class UpdateScreen: public DefaultViewScreen<chromeos::UpdateView>,
- public GoogleUpdateStatusListener,
+ public UpdateLibrary::Observer,
public UpdateController {
public:
explicit UpdateScreen(WizardScreenDelegate* delegate);
virtual ~UpdateScreen();
- // Overridden from GoogleUpdateStatusListener:
- virtual void OnReportResults(GoogleUpdateUpgradeResult result,
- GoogleUpdateErrorCode error_code,
- const std::wstring& version);
+ // UpdateLibrary::Observer implementation:
+ virtual void UpdateStatusChanged(UpdateLibrary* library);
// Overridden from UpdateController:
virtual void StartUpdate();
@@ -39,25 +37,38 @@ class UpdateScreen: public DefaultViewScreen<chromeos::UpdateView>,
// Reports update results to the ScreenObserver.
virtual void ExitUpdate();
- // Returns true if minimal update time has elapsed.
- virtual bool MinimalUpdateTimeElapsed();
- // Creates GoogleUpdate object.
- virtual GoogleUpdate* CreateGoogleUpdate();
+
+ // Maximal curtain time get/set, in seconds.
+ int maximal_curtain_time() const { return maximal_curtain_time_; }
+ void SetMaximalCurtainTime(int seconds);
+
+ // Reboot check delay get/set, in seconds.
+ int reboot_check_delay() const { return reboot_check_delay_; }
+ void SetRebootCheckDelay(int seconds);
private:
- // Timer notification handler.
- void OnMinimalUpdateTimeElapsed();
+ // Timer notification handlers.
+ void OnMaximalCurtainTimeElapsed();
+ void OnWaitForRebootTimeElapsed();
- // Timer.
- base::OneShotTimer<UpdateScreen> minimal_update_time_timer_;
+ // Timer for the interval while curtain view is shown.
+ base::OneShotTimer<UpdateScreen> maximal_curtain_time_timer_;
- // Update status.
- GoogleUpdateUpgradeResult update_result_;
- GoogleUpdateErrorCode update_error_;
+ // Timer for the interval to wait for the reboot.
+ // If reboot didn't happen - ask user to reboot manually.
+ base::OneShotTimer<UpdateScreen> reboot_timer_;
+
+ // True if in the process of checking for update.
bool checking_for_update_;
- // Google Updater.
- scoped_refptr<GoogleUpdate> google_updater_;
+ // Maximal time (secs) the curtain view is shown. Updating progress is shown
+ // to the user when this time elapsed.
+ int maximal_curtain_time_;
+
+ // Time in seconds after which we decide that the device has not rebooted
+ // automatically. If reboot didn't happen during this interval, ask user to
+ // reboot device manually.
+ int reboot_check_delay_;
DISALLOW_COPY_AND_ASSIGN(UpdateScreen);
};
diff --git a/chrome/browser/chromeos/login/update_view.cc b/chrome/browser/chromeos/login/update_view.cc
index 9facdbe..59e20dd 100644
--- a/chrome/browser/chromeos/login/update_view.cc
+++ b/chrome/browser/chromeos/login/update_view.cc
@@ -8,13 +8,16 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/update_screen.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "views/border.h"
#include "views/controls/label.h"
#include "views/controls/progress_bar.h"
+#include "views/controls/throbber.h"
#include "views/focus/focus_manager.h"
#include "views/widget/widget.h"
@@ -25,29 +28,42 @@ using views::Widget;
namespace {
+// TODO(nkostylev): Switch to GridLayout.
+
// Y offset for the 'installing updates' label.
-const int kInstallingUpdatesLabelY = 200;
+const int kInstallingUpdatesLabelYBottomFromProgressBar = 18;
// Y offset for the progress bar.
-const int kProgressBarY = 250;
+const int kProgressBarY = 199;
+// Y offset for the 'computer will restart' label.
+const int kRebootLabelYFromProgressBar = 77;
// Y offset for the 'ESCAPE to skip' label.
-const int kEscapeToSkipLabelY = 290;
+const int kEscapeToSkipLabelY = 48;
// Progress bar width.
-const int kProgressBarWidth = 450;
+const int kProgressBarWidth = 550;
+// Progress bar height.
+const int kProgressBarHeight = 18;
// Horizontal spacing (ex. min left and right margins for label on the screen).
-const int kHorizontalSpacing = 25;
+const int kHorizontalSpacing = 75;
+// Horizontal spacing between spinner and label on the curtain screen.
+const int kBetweenSpacing = 25;
// Label color.
const SkColor kLabelColor = 0xFF000000;
const SkColor kSkipLabelColor = 0xFFAA0000;
+const SkColor kManualRebootLabelColor = 0xFFAA0000;
} // namespace
namespace chromeos {
UpdateView::UpdateView(chromeos::ScreenObserver* observer)
- : escape_accelerator_(base::VKEY_ESCAPE, false, false, false),
+ : escape_accelerator_(app::VKEY_ESCAPE, false, false, false),
installing_updates_label_(NULL),
+ reboot_label_(NULL),
+ manual_reboot_label_(NULL),
progress_bar_(NULL),
+ show_curtain_(true),
+ show_manual_reboot_label_(false),
observer_(observer) {
}
@@ -60,30 +76,35 @@ void UpdateView::Init() {
&chromeos::BorderDefinition::kScreenBorder);
set_background(views::Background::CreateBackgroundPainter(true, painter));
- ResourceBundle& res_bundle = ResourceBundle::GetSharedInstance();
- gfx::Font base_font = res_bundle.GetFont(ResourceBundle::BaseFont);
-
InitLabel(&installing_updates_label_);
- installing_updates_label_->SetFont(base_font);
+ InitLabel(&reboot_label_);
+ InitLabel(&manual_reboot_label_);
+ manual_reboot_label_->SetVisible(false);
+ manual_reboot_label_->SetColor(kManualRebootLabelColor);
progress_bar_ = new views::ProgressBar();
AddChildView(progress_bar_);
- UpdateLocalizedStrings();
+ // Curtain view.
+ InitLabel(&checking_label_);
+ throbber_ = CreateDefaultThrobber();
+ AddChildView(throbber_);
#if !defined(OFFICIAL_BUILD)
- escape_to_skip_label_ = new views::Label();
+ InitLabel(&escape_to_skip_label_);
escape_to_skip_label_->SetColor(kSkipLabelColor);
- escape_to_skip_label_->SetFont(base_font);
escape_to_skip_label_->SetText(
L"Press ESCAPE to skip (Non-official builds only)");
- AddChildView(escape_to_skip_label_);
#endif
+
+ UpdateLocalizedStrings();
+ UpdateVisibility();
}
void UpdateView::Reset() {
progress_bar_->SetProgress(0);
#if !defined(OFFICIAL_BUILD)
+ ResetAccelerators();
AddAccelerator(escape_accelerator_);
#endif
}
@@ -92,35 +113,86 @@ void UpdateView::UpdateLocalizedStrings() {
installing_updates_label_->SetText(
l10n_util::GetStringF(IDS_INSTALLING_UPDATE,
l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
+ reboot_label_->SetText(l10n_util::GetString(IDS_INSTALLING_UPDATE_DESC));
+ manual_reboot_label_->SetText(l10n_util::GetString(IDS_UPDATE_COMPLETED));
+ checking_label_->SetText(l10n_util::GetString(IDS_CHECKING_FOR_UPDATES));
}
void UpdateView::AddProgress(int ticks) {
progress_bar_->AddProgress(ticks);
}
-// Sets the bounds of the view, placing it at the center of the screen
-// with the |y| coordinate provided. |width| could specify desired view width
-// otherwise preferred width/height are used.
-// |x_center| specifies screen center.
-static void setViewBounds(
- views::View* view, int x_center, int y, int width = -1) {
- int preferred_width = (width >= 0) ? width : view->GetPreferredSize().width();
+void UpdateView::SetProgress(int progress) {
+ progress_bar_->SetProgress(progress);
+}
+
+void UpdateView::ShowManualRebootInfo() {
+ show_manual_reboot_label_ = true;
+ UpdateVisibility();
+}
+
+void UpdateView::ShowCurtain(bool show_curtain) {
+ if (show_curtain_ != show_curtain) {
+ show_curtain_ = show_curtain;
+ UpdateVisibility();
+ }
+}
+
+// Sets the bounds of the view, placing center of the view at the given
+// coordinates (|x| and |y|).
+static void setViewBounds(views::View* view, int x, int y) {
+ int preferred_width = view->GetPreferredSize().width();
int preferred_height = view->GetPreferredSize().height();
view->SetBounds(
- x_center - preferred_width / 2,
- y,
+ x - preferred_width / 2,
+ y - preferred_height / 2,
preferred_width,
preferred_height);
}
void UpdateView::Layout() {
- int x_center = width() / 2;
int max_width = width() - GetInsets().width() - 2 * kHorizontalSpacing;
+ int right_margin = GetInsets().right() + kHorizontalSpacing;
+ int max_height = height() - GetInsets().height();
+ int vertical_center = GetInsets().top() + max_height / 2;
+
installing_updates_label_->SizeToFit(max_width);
- setViewBounds(installing_updates_label_, x_center, kInstallingUpdatesLabelY);
- setViewBounds(progress_bar_, x_center, kProgressBarY, kProgressBarWidth);
+ reboot_label_->SizeToFit(max_width);
+ manual_reboot_label_->SizeToFit(max_width);
+
+ progress_bar_->SetBounds(right_margin,
+ vertical_center - kProgressBarHeight / 2,
+ max_width,
+ kProgressBarHeight);
+
+ installing_updates_label_->SetX(right_margin);
+ installing_updates_label_->SetY(
+ progress_bar_->y() -
+ kInstallingUpdatesLabelYBottomFromProgressBar -
+ installing_updates_label_->height());
+ reboot_label_->SetX(right_margin);
+ reboot_label_->SetY(
+ progress_bar_->y() +
+ progress_bar_->height() +
+ kRebootLabelYFromProgressBar);
+ manual_reboot_label_->SetX(reboot_label_->x());
+ manual_reboot_label_->SetY(reboot_label_->y());
+ // Curtain layout is independed.
+ int x_center = width() / 2;
+ int throbber_width = throbber_->GetPreferredSize().width();
+ checking_label_->SizeToFit(max_width - throbber_width - kBetweenSpacing);
+ int checking_label_width = checking_label_->GetPreferredSize().width();
+ int space_half = (kBetweenSpacing + 1) / 2;
+ setViewBounds(
+ throbber_, x_center - checking_label_width / 2 - space_half,
+ vertical_center);
+ setViewBounds(
+ checking_label_, x_center + (throbber_width + 1) / 2 + space_half,
+ vertical_center);
#if !defined(OFFICIAL_BUILD)
- setViewBounds(escape_to_skip_label_, x_center, kEscapeToSkipLabelY);
+ escape_to_skip_label_->SizeToFit(max_width);
+ escape_to_skip_label_->SetX(right_margin);
+ escape_to_skip_label_->SetY(kEscapeToSkipLabelY);
#endif
SchedulePaint();
}
@@ -128,7 +200,7 @@ void UpdateView::Layout() {
bool UpdateView::AcceleratorPressed(const views::Accelerator& a) {
#if !defined(OFFICIAL_BUILD)
RemoveAccelerator(escape_accelerator_);
- if (a.GetKeyCode() == base::VKEY_ESCAPE) {
+ if (a.GetKeyCode() == app::VKEY_ESCAPE) {
if (controller_ != NULL) {
controller_->CancelUpdate();
}
@@ -138,12 +210,38 @@ bool UpdateView::AcceleratorPressed(const views::Accelerator& a) {
return false;
}
+void UpdateView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
+ if (is_add && this == child)
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
+}
+
void UpdateView::InitLabel(views::Label** label) {
*label = new views::Label();
(*label)->SetColor(kLabelColor);
- (*label)->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
+ (*label)->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
(*label)->SetMultiLine(true);
+
+ ResourceBundle& res_bundle = ResourceBundle::GetSharedInstance();
+ gfx::Font label_font = res_bundle.GetFont(ResourceBundle::MediumBoldFont);
+ (*label)->SetFont(label_font);
+
AddChildView(*label);
}
+void UpdateView::UpdateVisibility() {
+ installing_updates_label_->SetVisible(
+ !show_curtain_&& !show_manual_reboot_label_);
+ reboot_label_->SetVisible(!show_curtain_&& !show_manual_reboot_label_);
+ manual_reboot_label_->SetVisible(!show_curtain_ && show_manual_reboot_label_);
+ progress_bar_->SetVisible(!show_curtain_);
+
+ checking_label_->SetVisible(show_curtain_);
+ throbber_->SetVisible(show_curtain_);
+ if (show_curtain_) {
+ throbber_->Start();
+ } else {
+ throbber_->Stop();
+ }
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/update_view.h b/chrome/browser/chromeos/login/update_view.h
index b5b09fb..0549edf 100644
--- a/chrome/browser/chromeos/login/update_view.h
+++ b/chrome/browser/chromeos/login/update_view.h
@@ -4,12 +4,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UPDATE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_UPDATE_VIEW_H_
+#pragma once
#include "views/view.h"
namespace views {
class Label;
class ProgressBar;
+class Throbber;
} // namespace views
namespace chromeos {
@@ -23,34 +25,66 @@ class UpdateView : public views::View {
explicit UpdateView(ScreenObserver* observer);
virtual ~UpdateView();
- virtual void Init();
- virtual void Reset();
- virtual void UpdateLocalizedStrings();
+ void Init();
+ void Reset();
+ void UpdateLocalizedStrings();
// Sets update controller.
- virtual void set_controller(UpdateController* controller) {
+ void set_controller(UpdateController* controller) {
controller_ = controller;
}
// Advances view's progress bar. Maximum progress is 100.
- virtual void AddProgress(int progress);
+ void AddProgress(int progress);
+
+ // Sets the current value for the progress bar. Maximum progress is 100.
+ void SetProgress(int progress);
+
+ // Shows label with instructions for user to do a manual reboot.
+ // Usually is not called since we rely on API that will reboot after update.
+ void ShowManualRebootInfo();
+
+ // Whether curtain window with throbber and label in the center should
+ // be shown.
+ void ShowCurtain(bool show_curtain);
// views::View implementation:
virtual void Layout();
virtual bool AcceleratorPressed(const views::Accelerator& a);
+ protected:
+ // views::View implementation:
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
private:
// Creates Label control and adds it as a child.
void InitLabel(views::Label** label);
+ // Updates visibility of the elements.
+ void UpdateVisibility();
+
// Keyboard accelerator to allow cancelling update by hitting escape.
views::Accelerator escape_accelerator_;
// Dialog controls.
views::Label* installing_updates_label_;
+ views::Label* reboot_label_;
+ views::Label* manual_reboot_label_;
views::Label* escape_to_skip_label_;
views::ProgressBar* progress_bar_;
+ // Curtain views.
+ views::Label* checking_label_;
+ views::Throbber* throbber_;
+
+ // Show curtain view?
+ bool show_curtain_;
+
+ // Show manual reboot label?
+ bool show_manual_reboot_label_;
+
// Notifications receiver.
chromeos::ScreenObserver* observer_;
// Update controller.
diff --git a/chrome/browser/chromeos/login/user_controller.cc b/chrome/browser/chromeos/login/user_controller.cc
index e7de077..c005270 100644
--- a/chrome/browser/chromeos/login/user_controller.cc
+++ b/chrome/browser/chromeos/login/user_controller.cc
@@ -9,20 +9,24 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/login/existing_user_view.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/user_view.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
+#include "cros/chromeos_wm_ipc_enums.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "cros/chromeos_wm_ipc_enums.h"
#include "views/background.h"
-#include "views/controls/label.h"
#include "views/controls/button/native_button.h"
+#include "views/controls/label.h"
#include "views/grid_layout.h"
+#include "views/screen.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"
@@ -38,7 +42,7 @@ namespace {
const int kUserNameGap = 4;
// Approximate height of controls window, this constant is used in new user
-// case to make border window size close to exsisting users.
+// case to make border window size close to existing users.
const int kControlsHeight = 26;
// Widget that notifies window manager about clicking on itself.
@@ -54,7 +58,7 @@ class ClickNotifyingWidget : public views::WidgetGtk {
private:
gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) {
if (!controller_->is_user_selected())
- controller_->SelectUser(controller_->user_index());
+ controller_->SelectUser(controller_->user_index(), true);
return views::WidgetGtk::OnButtonPress(widget, event);
}
@@ -64,81 +68,6 @@ class ClickNotifyingWidget : public views::WidgetGtk {
DISALLOW_COPY_AND_ASSIGN(ClickNotifyingWidget);
};
-// Returns tooltip text for user name. Tooltip contains user's display name
-// and his email domain to distinguish this user from the other one with the
-// same display name.
-std::string GetNameTooltip(const UserManager::User& user) {
- const std::string& email = user.email();
- size_t at_pos = email.rfind('@');
- if (at_pos == std::string::npos) {
- NOTREACHED();
- return std::string();
- }
- size_t domain_start = at_pos + 1;
- std::string domain = email.substr(domain_start,
- email.length() - domain_start);
- return StringPrintf("%s (%s)",
- user.GetDisplayName().c_str(),
- domain.c_str());
-}
-
-// NativeButton that will always return focus to password field.
-class UserEntryNativeButton : public views::NativeButton {
- public:
- UserEntryNativeButton(UserController* controller,
- views::ButtonListener* listener,
- const std::wstring& label)
- : NativeButton(listener, label),
- controller_(controller) {}
-
- // Overridden from View:
- virtual void DidGainFocus() {
- controller_->FocusPasswordField();
- }
-
- private:
- UserController* controller_;
-
- DISALLOW_COPY_AND_ASSIGN(UserEntryNativeButton);
-};
-
-// Textfield with custom processing for Tab/Shift+Tab to select entries.
-class UserEntryTextfield : public views::Textfield {
- public:
- explicit UserEntryTextfield(UserController* controller)
- : Textfield(),
- controller_(controller) {}
-
- UserEntryTextfield(UserController* controller,
- views::Textfield::StyleFlags style)
- : Textfield(style),
- controller_(controller) {}
-
- // Overridden from View:
- virtual bool OnKeyPressed(const views::KeyEvent& e) {
- if (e.GetKeyCode() == base::VKEY_TAB) {
- int index = controller_->user_index() + (e.IsShiftDown() ? -1 : 1);
- controller_->SelectUser(index);
- return true;
- } else {
- return false;
- }
- }
-
- // Overridden from views::Textfield:
- virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
- if (e.GetKeyCode() == base::VKEY_TAB)
- return true;
- else
- return views::Textfield::SkipDefaultKeyEventProcessing(e);
- }
-
- private:
- UserController* controller_;
-
- DISALLOW_COPY_AND_ASSIGN(UserEntryTextfield);
-};
-
} // namespace
using login::kBackgroundColor;
@@ -152,14 +81,13 @@ const int UserController::kPadding = 20;
// Max size needed when an entry is not selected.
const int UserController::kUnselectedSize = 100;
-UserController::UserController(Delegate* delegate)
+UserController::UserController(Delegate* delegate, bool is_bwsi)
: user_index_(-1),
is_user_selected_(false),
- is_guest_(true),
+ is_new_user_(!is_bwsi),
+ is_bwsi_(is_bwsi),
show_name_tooltip_(false),
delegate_(delegate),
- password_field_(NULL),
- submit_button_(NULL),
controls_window_(NULL),
image_window_(NULL),
border_window_(NULL),
@@ -167,6 +95,7 @@ UserController::UserController(Delegate* delegate)
unselected_label_window_(NULL),
user_view_(NULL),
new_user_view_(NULL),
+ existing_user_view_(NULL),
label_view_(NULL),
unselected_label_view_(NULL) {
registrar_.Add(
@@ -179,12 +108,11 @@ UserController::UserController(Delegate* delegate,
const UserManager::User& user)
: user_index_(-1),
is_user_selected_(false),
- is_guest_(false),
+ is_new_user_(false),
+ is_bwsi_(false),
show_name_tooltip_(false),
user_(user),
delegate_(delegate),
- password_field_(NULL),
- submit_button_(NULL),
controls_window_(NULL),
image_window_(NULL),
border_window_(NULL),
@@ -192,6 +120,7 @@ UserController::UserController(Delegate* delegate,
unselected_label_window_(NULL),
user_view_(NULL),
new_user_view_(NULL),
+ existing_user_view_(NULL),
label_view_(NULL),
unselected_label_view_(NULL) {
registrar_.Add(
@@ -208,9 +137,12 @@ UserController::~UserController() {
unselected_label_window_->Close();
}
-void UserController::Init(int index, int total_user_count) {
+void UserController::Init(int index,
+ int total_user_count,
+ bool need_browse_without_signin) {
int controls_height = 0;
- controls_window_ = CreateControlsWindow(index, &controls_height);
+ controls_window_ =
+ CreateControlsWindow(index, &controls_height, need_browse_without_signin);
image_window_ = CreateImageWindow(index);
CreateBorderWindow(index, total_user_count, controls_height);
label_window_ = CreateLabelWindow(index, WM_IPC_WINDOW_LOGIN_LABEL);
@@ -219,29 +151,63 @@ void UserController::Init(int index, int total_user_count) {
}
void UserController::SetPasswordEnabled(bool enable) {
- DCHECK(!is_guest_);
- password_field_->SetEnabled(enable);
- submit_button_->SetEnabled(enable);
+ DCHECK(!is_new_user_);
+ existing_user_view_->password_field()->SetEnabled(enable);
+ existing_user_view_->submit_button()->SetEnabled(enable);
enable ? user_view_->StopThrobber() : user_view_->StartThrobber();
}
+std::wstring UserController::GetNameTooltip() const {
+ if (is_new_user_)
+ return l10n_util::GetString(IDS_ADD_USER);
+ if (is_bwsi_)
+ return l10n_util::GetString(IDS_GO_INCOGNITO_BUTTON);
+
+ // Tooltip contains user's display name and his email domain to distinguish
+ // this user from the other one with the same display name.
+ const std::wstring& email = UTF8ToWide(user_.email());
+ size_t at_pos = email.rfind('@');
+ if (at_pos == std::wstring::npos) {
+ NOTREACHED();
+ return std::wstring();
+ }
+ size_t domain_start = at_pos + 1;
+ std::wstring domain = email.substr(domain_start,
+ email.length() - domain_start);
+ return base::StringPrintf(L"%s (%s)",
+ user_.GetDisplayName().c_str(),
+ domain.c_str());
+}
+
+void UserController::UpdateSubmitButtonState() {
+ if (!is_new_user_) {
+ existing_user_view_->submit_button()->SetEnabled(
+ !existing_user_view_->password_field()->text().empty());
+ }
+}
+
void UserController::ClearAndEnablePassword() {
- if (is_guest_) {
+ if (is_new_user_) {
new_user_view_->ClearAndEnablePassword();
} else {
- password_field_->SetText(string16());
+ existing_user_view_->password_field()->SetText(string16());
SetPasswordEnabled(true);
FocusPasswordField();
}
}
-void UserController::EnableNameTooltip(bool enable) {
- if (is_guest_)
- return;
+void UserController::ClearAndEnableFields() {
+ if (is_new_user_) {
+ new_user_view_->ClearAndEnableFields();
+ } else {
+ ClearAndEnablePassword();
+ }
+}
+void UserController::EnableNameTooltip(bool enable) {
std::wstring tooltip_text;
if (enable)
- tooltip_text = UTF8ToWide(GetNameTooltip(user_));
+ tooltip_text = GetNameTooltip();
if (user_view_)
user_view_->SetTooltipText(tooltip_text);
@@ -259,20 +225,25 @@ void UserController::ButtonPressed(views::Button* sender,
bool UserController::HandleKeystroke(
views::Textfield* sender,
const views::Textfield::Keystroke& keystroke) {
- if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
+ if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
Login();
return true;
- } else if (keystroke.GetKeyboardCode() == base::VKEY_LEFT) {
- SelectUser(user_index() - 1);
+ } else if (keystroke.GetKeyboardCode() == app::VKEY_LEFT) {
+ SelectUser(user_index() - 1, false);
return true;
- } else if (keystroke.GetKeyboardCode() == base::VKEY_RIGHT) {
- SelectUser(user_index() + 1);
+ } else if (keystroke.GetKeyboardCode() == app::VKEY_RIGHT) {
+ SelectUser(user_index() + 1, false);
return true;
}
delegate_->ClearErrors();
return false;
}
+void UserController::ContentsChanged(views::Textfield* sender,
+ const string16& new_contents) {
+ UpdateSubmitButtonState();
+}
+
void UserController::Observe(
NotificationType type,
const NotificationSource& source,
@@ -290,20 +261,44 @@ void UserController::Observe(
}
void UserController::Login() {
- // Delegate will reenable as necessary.
- SetPasswordEnabled(false);
+ if (is_bwsi_) {
+ delegate_->LoginOffTheRecord();
+ } else {
+ // Delegate will reenable as necessary.
+ SetPasswordEnabled(false);
- delegate_->Login(this, password_field_->text());
+ delegate_->Login(this, existing_user_view_->password_field()->text());
+ }
}
void UserController::IsActiveChanged(bool active) {
is_user_selected_ = active;
if (active) {
delegate_->OnUserSelected(this);
- user_view_->SetMenuVisible(!is_guest_);
+ user_view_->SetRemoveButtonVisible(!is_new_user_ && !is_bwsi_);
+ // Background is NULL for inactive new user pod to make it transparent.
+ if (is_new_user_ && !border_window_->GetRootView()->background()) {
+ views::Painter* painter = CreateWizardPainter(
+ &BorderDefinition::kUserBorder);
+ border_window_->GetRootView()->set_background(
+ views::Background::CreateBackgroundPainter(true, painter));
+ border_window_->GetRootView()->SchedulePaint();
+ }
} else {
- user_view_->SetMenuVisible(false);
+ user_view_->SetRemoveButtonVisible(false);
delegate_->ClearErrors();
+ if (is_new_user_) {
+ gfx::Rect controls_bounds;
+ controls_window_->GetBounds(&controls_bounds, true);
+ gfx::Rect screen_bounds =
+ views::Screen::GetMonitorWorkAreaNearestWindow(NULL);
+ // The windows was moved out of screen so the pod was really deactivated,
+ // otherwise it just some dialog was shown and took focus.
+ if (!screen_bounds.Intersects(controls_bounds)) {
+ border_window_->GetRootView()->set_background(NULL);
+ border_window_->GetRootView()->SchedulePaint();
+ }
+ }
}
}
@@ -330,39 +325,27 @@ void UserController::ConfigureLoginWindow(WidgetGtk* window,
window->Show();
}
-WidgetGtk* UserController::CreateControlsWindow(int index, int* height) {
+WidgetGtk* UserController::CreateControlsWindow(
+ int index,
+ int* height,
+ bool need_browse_without_signin) {
views::View* control_view;
- if (is_guest_) {
- new_user_view_ = new NewUserView(this, false);
+ if (is_new_user_) {
+ new_user_view_ =
+ new NewUserView(this, false, need_browse_without_signin);
new_user_view_->Init();
control_view = new_user_view_;
} else {
- password_field_ = new UserEntryTextfield(this,
- views::Textfield::STYLE_PASSWORD);
- password_field_->set_text_to_display_when_empty(
- l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT));
- password_field_->SetController(this);
- submit_button_ = new UserEntryNativeButton(
- this, this, l10n_util::GetString(IDS_LOGIN_BUTTON));
- submit_button_->SetFocusable(false);
- control_view = new views::View();
- GridLayout* layout = new GridLayout(control_view);
- control_view->SetLayoutManager(layout);
- views::ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
- GridLayout::USE_PREF, 0, 0);
- column_set->AddPaddingColumn(0, kBorderSize);
- column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
- GridLayout::USE_PREF, 0, 0);
-
- layout->StartRow(0, 0);
- layout->AddView(password_field_);
- layout->AddView(submit_button_);
+ existing_user_view_ = new ExistingUserView(this);
+ existing_user_view_->RecreateFields();
+ control_view = existing_user_view_;
}
*height = kControlsHeight;
- if (is_guest_)
+ if (is_new_user_)
*height += kUserImageSize + kUserNameGap;
+ if (is_bwsi_)
+ *height = 1;
WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
ConfigureLoginWindow(window,
@@ -374,13 +357,16 @@ WidgetGtk* UserController::CreateControlsWindow(int index, int* height) {
}
WidgetGtk* UserController::CreateImageWindow(int index) {
- user_view_ = new UserView(this, true);
+ user_view_ = new UserView(this, true, !is_new_user_);
- if (!is_guest_) {
- user_view_->SetImage(user_.image());
- } else {
+ if (is_bwsi_) {
+ user_view_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_LOGIN_GUEST));
+ } else if (is_new_user_) {
user_view_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
- IDR_LOGIN_OTHER_USER));
+ IDR_LOGIN_ADD_USER));
+ } else {
+ user_view_->SetImage(user_.image());
}
WidgetGtk* window = new ClickNotifyingWidget(WidgetGtk::TYPE_WINDOW, this);
@@ -389,22 +375,30 @@ WidgetGtk* UserController::CreateImageWindow(int index) {
gfx::Rect(user_view_->GetPreferredSize()),
WM_IPC_WINDOW_LOGIN_IMAGE,
user_view_);
+
return window;
}
void UserController::CreateBorderWindow(int index,
int total_user_count,
int controls_height) {
- // Guest login controls window is much higher than exsisting user's controls
+ // New user login controls window is much higher than existing user's controls
// window so window manager will place the control instead of image window.
- int width = kUserImageSize + kBorderSize * 2;
+ int width = kBorderSize * 2 + kUserImageSize;
int height = kBorderSize * 2 + controls_height;
- if (!is_guest_)
+ if (!is_new_user_)
height += kBorderSize + kUserImageSize;
+ if (is_bwsi_)
+ height = kBorderSize * 2 + kUserImageSize + 1;
border_window_ = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
+ border_window_->MakeTransparent();
border_window_->Init(NULL, gfx::Rect(0, 0, width, height));
- border_window_->GetRootView()->set_background(
- views::Background::CreateSolidBackground(kBackgroundColor));
+ if (!is_new_user_) {
+ views::Painter* painter = CreateWizardPainter(
+ &BorderDefinition::kUserBorder);
+ border_window_->GetRootView()->set_background(
+ views::Background::CreateBackgroundPainter(true, painter));
+ }
UpdateUserCount(index, total_user_count);
GdkWindow* gdk_window = border_window_->GetNativeView()->window;
@@ -432,8 +426,18 @@ WidgetGtk* UserController::CreateLabelWindow(int index,
const gfx::Font& font = (type == WM_IPC_WINDOW_LOGIN_LABEL) ?
rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD) :
rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD);
- std::wstring text = is_guest_ ? l10n_util::GetString(IDS_GUEST) :
- UTF8ToWide(user_.GetDisplayName());
+ std::wstring text;
+ if (is_bwsi_) {
+ text = l10n_util::GetString(IDS_GUEST);
+ } else if (is_new_user_) {
+ // Add user should have label only in activated state.
+ // When new user is the only, label is not needed.
+ if (type == WM_IPC_WINDOW_LOGIN_LABEL && index != 0)
+ text = l10n_util::GetString(IDS_ADD_USER);
+ } else {
+ text = UTF8ToWide(user_.GetDisplayName());
+ }
+
views::Label* label = new views::Label(text);
label->SetColor(kTextColor);
label->SetFont(font);
@@ -455,15 +459,10 @@ WidgetGtk* UserController::CreateLabelWindow(int index,
}
gfx::Rect UserController::GetScreenBounds() const {
- if (is_guest_) {
- return new_user_view_->GetPasswordBounds();
- } else {
- gfx::Rect screen_bounds(password_field_->bounds());
- gfx::Point origin(screen_bounds.origin());
- views::View::ConvertPointToScreen(password_field_->GetParent(), &origin);
- screen_bounds.set_origin(origin);
- return screen_bounds;
- }
+ if (is_new_user_)
+ return new_user_view_->GetUsernameBounds();
+ else
+ return existing_user_view_->password_field()->GetScreenBounds();
}
void UserController::OnLogin(const std::string& username,
@@ -484,20 +483,23 @@ void UserController::ClearErrors() {
delegate_->ClearErrors();
}
-void UserController::OnRemoveUser() {
- delegate_->RemoveUser(this);
+void UserController::NavigateAway() {
+ SelectUser(user_index() - 1, false);
}
-void UserController::OnChangePhoto() {
- // TODO(dpolukhin): implement change user photo, see http://crosbug.com/2348
+void UserController::OnRemoveUser() {
+ delegate_->RemoveUser(this);
}
-void UserController::SelectUser(int index) {
- delegate_->SelectUser(index);
+void UserController::SelectUser(int index, bool is_click) {
+ if (is_click && is_bwsi_)
+ delegate_->LoginOffTheRecord();
+ else
+ delegate_->SelectUser(index);
}
void UserController::FocusPasswordField() {
- password_field_->RequestFocus();
+ existing_user_view_->FocusPasswordField();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_controller.h b/chrome/browser/chromeos/login/user_controller.h
index d702fcd..c62e94c 100644
--- a/chrome/browser/chromeos/login/user_controller.h
+++ b/chrome/browser/chromeos/login/user_controller.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_CONTROLLER_H_
+#pragma once
#include <string>
@@ -26,6 +27,7 @@ class WidgetGtk;
namespace chromeos {
class UserView;
+class ExistingUserView;
// UserController manages the set of windows needed to login a single existing
// user or first time login for a new user. ExistingUserController creates
@@ -55,8 +57,8 @@ class UserController : public views::ButtonListener,
virtual ~Delegate() {}
};
- // Creates a UserController representing the guest (other user) login.
- explicit UserController(Delegate* delegate);
+ // Creates a UserController representing new user or bwsi login.
+ UserController(Delegate* delegate, bool is_bwsi);
// Creates a UserController for the specified user.
UserController(Delegate* delegate, const UserManager::User& user);
@@ -66,7 +68,7 @@ class UserController : public views::ButtonListener,
// Initializes the UserController, creating the set of windows/controls.
// |index| is the index of this user, and |total_user_count| the total
// number of users.
- void Init(int index, int total_user_count);
+ void Init(int index, int total_user_count, bool need_browse_without_signin);
// Update border window parameters to notify window manager about new numbers.
// |index| of this user and |total_user_count| of users.
@@ -74,7 +76,9 @@ class UserController : public views::ButtonListener,
int user_index() const { return user_index_; }
bool is_user_selected() const { return is_user_selected_; }
- bool is_guest() const { return is_guest_; }
+ bool is_new_user() const { return is_new_user_; }
+ bool is_bwsi() const { return is_bwsi_; }
+ NewUserView* new_user_view() const { return new_user_view_; }
const UserManager::User& user() const { return user_; }
@@ -84,7 +88,11 @@ class UserController : public views::ButtonListener,
// Resets password text and sets the enabled state of the password.
void ClearAndEnablePassword();
+ // Called when user view is activated (OnUserSelected).
+ void ClearAndEnableFields();
+
// Returns bounds of password field in screen coordinates.
+ // For new user it returns username coordinates.
gfx::Rect GetScreenBounds() const;
// Get widget that contains all controls.
@@ -97,7 +105,7 @@ class UserController : public views::ButtonListener,
// Textfield::Controller:
virtual void ContentsChanged(views::Textfield* sender,
- const string16& new_contents) {}
+ const string16& new_contents);
virtual bool HandleKeystroke(views::Textfield* sender,
const views::Textfield::Keystroke& keystroke);
@@ -118,13 +126,14 @@ class UserController : public views::ButtonListener,
delegate_->AddStartUrl(start_url);
}
virtual void ClearErrors();
+ virtual void NavigateAway();
// UserView::Delegate implementation:
virtual void OnRemoveUser();
- virtual void OnChangePhoto();
- // Selects user entry with specified |index|.
- void SelectUser(int index);
+ // Selects user entry with specified |index|, |is_click| is true if the entry
+ // was selected by mouse click.
+ void SelectUser(int index, bool is_click);
// Sets focus on password field.
void FocusPasswordField();
@@ -145,7 +154,9 @@ class UserController : public views::ButtonListener,
const gfx::Rect& bounds,
chromeos::WmIpcWindowType type,
views::View* contents_view);
- views::WidgetGtk* CreateControlsWindow(int index, int* height);
+ views::WidgetGtk* CreateControlsWindow(int index,
+ int* height,
+ bool need_browse_without_signin);
views::WidgetGtk* CreateImageWindow(int index);
views::WidgetGtk* CreateLabelWindow(int index, WmIpcWindowType type);
void CreateBorderWindow(int index, int total_user_count, int controls_height);
@@ -159,30 +170,34 @@ class UserController : public views::ButtonListener,
// Sets the enabled state of the password field to |enable|.
void SetPasswordEnabled(bool enable);
+ // Returns tooltip text for user name.
+ std::wstring GetNameTooltip() const;
+
+ // Enable or disable the 'Submit' button based on the contents of
+ // |password_field_|. Enabled if there is text, otherwise disabled.
+ void UpdateSubmitButtonState();
+
// User index within all the users.
int user_index_;
// Is this user selected now?
bool is_user_selected_;
- // Is this the guest user?
- const bool is_guest_;
+ // Is this the new user pod?
+ const bool is_new_user_;
+
+ // Is this the bwsi pod?
+ const bool is_bwsi_;
// Should we show tooltips above user image and label to help distinguish
// users with the same display name.
bool show_name_tooltip_;
- // If is_guest_ is false, this is the user being shown.
+ // If is_new_user_ and is_bwsi_ are false, this is the user being shown.
UserManager::User user_;
Delegate* delegate_;
- // For editing the password.
- views::Textfield* password_field_;
-
- // Button to start login.
- views::NativeButton* submit_button_;
-
// A window is used to represent the individual chunks.
views::WidgetGtk* controls_window_;
views::WidgetGtk* image_window_;
@@ -196,6 +211,9 @@ class UserController : public views::ButtonListener,
// View that is used for new user login.
NewUserView* new_user_view_;
+ // View that is used for existing user login.
+ ExistingUserView* existing_user_view_;
+
// Views that show display name of the user.
views::Label* label_view_;
views::Label* unselected_label_view_;
diff --git a/chrome/browser/chromeos/login/user_image_downloader.cc b/chrome/browser/chromeos/login/user_image_downloader.cc
index 83f5d45..3deea71 100644
--- a/chrome/browser/chromeos/login/user_image_downloader.cc
+++ b/chrome/browser/chromeos/login/user_image_downloader.cc
@@ -8,10 +8,11 @@
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/chromeos/login/google_authenticator.h"
+#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/profile_manager.h"
@@ -50,7 +51,7 @@ UserImageDownloader::UserImageDownloader(const std::string& username,
profile_fetcher_->set_request_context(
ProfileManager::GetDefaultProfile()->GetRequestContext());
profile_fetcher_->set_extra_request_headers(
- StringPrintf(kAuthorizationHeader, auth_token_.c_str()));
+ base::StringPrintf(kAuthorizationHeader, auth_token_.c_str()));
profile_fetcher_->Start();
}
@@ -85,8 +86,12 @@ void UserImageDownloader::OnURLFetchComplete(const URLFetcher* source,
void UserImageDownloader::OnImageDecoded(const SkBitmap& decoded_image) {
// Save the image to file and its path to preferences.
chromeos::UserManager* user_manager = chromeos::UserManager::Get();
- if (user_manager)
+ if (user_manager) {
+ if (user_manager->logged_in_user().email() == username_) {
+ user_manager->SetLoggedInUserImage(decoded_image);
+ }
user_manager->SaveUserImage(username_, decoded_image);
+ }
}
bool UserImageDownloader::GetImageURL(const std::string& json_data,
@@ -105,11 +110,11 @@ bool UserImageDownloader::GetImageURL(const std::string& json_data,
DictionaryValue* root_dictionary =
static_cast<DictionaryValue*>(root.get());
DictionaryValue* feed_dictionary = NULL;
- if (!root_dictionary->GetDictionary(L"feed", &feed_dictionary))
+ if (!root_dictionary->GetDictionary("feed", &feed_dictionary))
return false;
ListValue* entry_list = NULL;
- if (!feed_dictionary->GetList(L"entry", &entry_list))
+ if (!feed_dictionary->GetList("entry", &entry_list))
return false;
return GetImageURLFromEntries(entry_list, image_url);
@@ -125,7 +130,7 @@ bool UserImageDownloader::GetImageURLFromEntries(ListValue* entry_list,
continue;
ListValue* email_list = NULL;
- if (!entry_dictionary->GetList(L"gd$email", &email_list))
+ if (!entry_dictionary->GetList("gd$email", &email_list))
continue;
// Match entry email address to understand that this is user's entry.
@@ -133,7 +138,7 @@ bool UserImageDownloader::GetImageURLFromEntries(ListValue* entry_list,
continue;
ListValue* link_list = NULL;
- if (!entry_dictionary->GetList(L"link", &link_list))
+ if (!entry_dictionary->GetList("link", &link_list))
continue;
if (GetImageURLFromLinks(link_list, image_url))
@@ -153,7 +158,7 @@ bool UserImageDownloader::IsUserEntry(ListValue* email_list) const {
if (!email_dictionary->GetStringASCII("address", &email))
continue;
- if (GoogleAuthenticator::Canonicalize(email) == username_)
+ if (Authenticator::Canonicalize(email) == username_)
return true;
}
return false;
diff --git a/chrome/browser/chromeos/login/user_image_downloader.h b/chrome/browser/chromeos/login/user_image_downloader.h
index f4de665..5eba206 100644
--- a/chrome/browser/chromeos/login/user_image_downloader.h
+++ b/chrome/browser/chromeos/login/user_image_downloader.h
@@ -4,12 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_DOWNLOADER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_DOWNLOADER_H_
+#pragma once
#include <string>
-#include <vector>
#include "base/basictypes.h"
-#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/login/image_decoder.h"
#include "chrome/common/net/url_fetcher.h"
diff --git a/chrome/browser/chromeos/login/user_image_loader.h b/chrome/browser/chromeos/login/user_image_loader.h
index 454900b..4c7e0ad 100644
--- a/chrome/browser/chromeos/login/user_image_loader.h
+++ b/chrome/browser/chromeos/login/user_image_loader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_LOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/user_image_screen.cc b/chrome/browser/chromeos/login/user_image_screen.cc
index 9b617cc..a990f31 100644
--- a/chrome/browser/chromeos/login/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/user_image_screen.cc
@@ -71,6 +71,7 @@ void UserImageScreen::OnOK(const SkBitmap& image) {
UserManager* user_manager = UserManager::Get();
if (user_manager) {
// TODO(avayvod): Check that there's logged in user actually.
+ user_manager->SetLoggedInUserImage(image);
const UserManager::User& user = user_manager->logged_in_user();
user_manager->SaveUserImage(user.email(), image);
}
@@ -78,15 +79,8 @@ void UserImageScreen::OnOK(const SkBitmap& image) {
delegate()->GetObserver(this)->OnExit(ScreenObserver::USER_IMAGE_SELECTED);
}
-void UserImageScreen::OnCancel() {
- // Download user image from his Google account.
- UserManager* user_manager = UserManager::Get();
- if (user_manager) {
- // TODO(avayvod): Check that there's logged in user actually.
- const UserManager::User& user = user_manager->logged_in_user();
- new UserImageDownloader(user.email(),
- LoginUtils::Get()->GetAuthToken());
- }
+void UserImageScreen::OnSkip() {
+ // TODO(avayvod): Use one of the default images. See http://crosbug.com/5780.
if (delegate())
delegate()->GetObserver(this)->OnExit(ScreenObserver::USER_IMAGE_SKIPPED);
}
diff --git a/chrome/browser/chromeos/login/user_image_screen.h b/chrome/browser/chromeos/login/user_image_screen.h
index 609e5f6..5dd0142 100644
--- a/chrome/browser/chromeos/login/user_image_screen.h
+++ b/chrome/browser/chromeos/login/user_image_screen.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_SCREEN_H_
+#pragma once
#include "chrome/browser/chromeos/login/camera.h"
#include "chrome/browser/chromeos/login/user_image_view.h"
@@ -32,7 +33,7 @@ class UserImageScreen: public ViewScreen<UserImageView>,
// UserImageView::Delegate implementation:
virtual void OnOK(const SkBitmap& image);
- virtual void OnCancel();
+ virtual void OnSkip();
// NotificationObserver implementation:
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/chromeos/login/user_image_view.cc b/chrome/browser/chromeos/login/user_image_view.cc
index eb93af3..dfd89ea 100644
--- a/chrome/browser/chromeos/login/user_image_view.cc
+++ b/chrome/browser/chromeos/login/user_image_view.cc
@@ -9,8 +9,10 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/callback.h"
-#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
+#include "chrome/browser/profile_manager.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -19,6 +21,7 @@
#include "views/controls/button/native_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
+#include "views/grid_layout.h"
namespace {
@@ -30,8 +33,15 @@ const int kVerticalMargin = 10;
const int kHorizontalPadding = 10;
// Padding between vertically neighboring elements.
const int kVerticalPadding = 10;
-// Size for button with video image.
-const int kVideoImageSize = 256;
+// Size for user image shown on the screen.
+const int kUserImageSize = 256;
+
+// IDs of column sets for grid layout manager.
+enum ColumnSets {
+ kTitleRow, // Column set for screen title.
+ kImageRow, // Column set for image from camera and snapshot button.
+ kButtonsRow, // Column set for Skip and OK buttons.
+};
} // namespace
@@ -42,11 +52,11 @@ using login::kUserImageSize;
UserImageView::UserImageView(Delegate* delegate)
: title_label_(NULL),
ok_button_(NULL),
- cancel_button_(NULL),
- video_button_(NULL),
- selected_image_(NULL),
+ skip_button_(NULL),
+ snapshot_button_(NULL),
+ user_image_(NULL),
delegate_(delegate),
- image_selected_(false) {
+ is_capturing_(true) {
}
UserImageView::~UserImageView() {
@@ -59,158 +69,107 @@ void UserImageView::Init() {
&BorderDefinition::kScreenBorder);
set_background(views::Background::CreateBackgroundPainter(true, painter));
- // Set up fonts.
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gfx::Font title_font = rb.GetFont(ResourceBundle::MediumBoldFont);
-
- title_label_ = new views::Label();
+ title_label_ =
+ new views::Label(l10n_util::GetString(IDS_USER_IMAGE_SCREEN_TITLE));
title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- title_label_->SetFont(title_font);
title_label_->SetMultiLine(true);
- AddChildView(title_label_);
-
- SkBitmap video_button_image =
- skia::ImageOperations::Resize(
- *ResourceBundle::GetSharedInstance().GetBitmapNamed(
- IDR_USER_IMAGE_NO_VIDEO),
- skia::ImageOperations::RESIZE_BOX,
- kVideoImageSize,
- kVideoImageSize);
-
- video_button_ = new views::ImageButton(this);
- video_button_->SetImage(views::CustomButton::BS_NORMAL, &video_button_image);
- AddChildView(video_button_);
- selected_image_ = new views::ImageView();
- selected_image_->SetImageSize(
+ user_image_ = new views::ImageView();
+ user_image_->SetImageSize(
gfx::Size(kUserImageSize, kUserImageSize));
- selected_image_->SetImage(
- *ResourceBundle::GetSharedInstance().GetBitmapNamed(
- IDR_LOGIN_OTHER_USER));
- AddChildView(selected_image_);
+ user_image_->SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_USER_IMAGE_NO_VIDEO));
- UpdateLocalizedStrings();
-}
+ snapshot_button_ = new views::ImageButton(this);
+ snapshot_button_->SetFocusable(true);
+ snapshot_button_->SetImage(views::CustomButton::BS_NORMAL,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_USER_IMAGE_CAPTURE));
-void UserImageView::RecreateNativeControls() {
- // There is no way to get native button preferred size after the button was
- // sized so delete and recreate the button on text update.
- delete ok_button_;
- ok_button_ = new views::NativeButton(this, std::wstring());
- AddChildView(ok_button_);
- ok_button_->SetEnabled(image_selected_);
- if (image_selected_)
- ok_button_->RequestFocus();
-
- delete cancel_button_;
- cancel_button_ = new views::NativeButton(this, std::wstring());
- AddChildView(cancel_button_);
- cancel_button_->SetEnabled(true);
-}
+ ok_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_OK));
+ ok_button_->SetEnabled(!is_capturing_);
-void UserImageView::UpdateLocalizedStrings() {
- RecreateNativeControls();
+ skip_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_SKIP));
+ skip_button_->SetEnabled(true);
- title_label_->SetText(l10n_util::GetString(IDS_USER_IMAGE_SCREEN_TITLE));
- ok_button_->SetLabel(l10n_util::GetString(IDS_OK));
- cancel_button_->SetLabel(l10n_util::GetString(IDS_CANCEL));
- selected_image_->SetTooltipText(
- l10n_util::GetString(IDS_USER_IMAGE_SELECTED_TOOLTIP));
+ InitLayout();
+ // Request focus only after the button is added to views hierarchy.
+ snapshot_button_->RequestFocus();
}
-void UserImageView::UpdateVideoFrame(const SkBitmap& frame) {
- last_frame_.reset(new SkBitmap(frame));
- SkBitmap video_button_image =
- skia::ImageOperations::Resize(
- *last_frame_,
- skia::ImageOperations::RESIZE_BOX,
- kVideoImageSize,
- kVideoImageSize);
-
- video_button_->SetImage(views::CustomButton::BS_NORMAL, &video_button_image);
- video_button_->SchedulePaint();
+void UserImageView::InitLayout() {
+ views::GridLayout* layout = new views::GridLayout(this);
+ layout->SetInsets(GetInsets());
+ SetLayoutManager(layout);
+
+ // The title is left-top aligned.
+ views::ColumnSet* column_set = layout->AddColumnSet(kTitleRow);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+ column_set->AddColumn(views::GridLayout::LEADING,
+ views::GridLayout::LEADING,
+ 1,
+ views::GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+
+ // User image and snapshot button are centered horizontally.
+ column_set = layout->AddColumnSet(kImageRow);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+ column_set->AddColumn(views::GridLayout::CENTER,
+ views::GridLayout::LEADING,
+ 1,
+ views::GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+
+ // OK and Skip buttons are in the right bottom corner of the view.
+ column_set = layout->AddColumnSet(kButtonsRow);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+ // This column takes the empty space to the left of the buttons.
+ column_set->AddPaddingColumn(1, 1);
+ column_set->AddColumn(views::GridLayout::TRAILING,
+ views::GridLayout::TRAILING,
+ 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kHorizontalPadding);
+ column_set->AddColumn(views::GridLayout::TRAILING,
+ views::GridLayout::TRAILING,
+ 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kHorizontalMargin);
+
+ // Fill the layout with rows and views now.
+ layout->StartRowWithPadding(0, kTitleRow, 0, kVerticalMargin);
+ layout->AddView(title_label_);
+ layout->StartRowWithPadding(0, kImageRow, 0, kVerticalPadding);
+ layout->AddView(user_image_);
+ layout->StartRowWithPadding(1, kImageRow, 0, kVerticalPadding);
+ layout->AddView(snapshot_button_);
+ layout->StartRowWithPadding(0, kButtonsRow, 0, kVerticalPadding);
+ layout->AddView(skip_button_);
+ layout->AddView(ok_button_);
+ layout->AddPaddingRow(0, kVerticalMargin);
}
-void UserImageView::OnVideoImageClicked() {
- // TODO(avayvod): Snapshot sound.
- if (!last_frame_.get())
+void UserImageView::UpdateVideoFrame(const SkBitmap& frame) {
+ if (!is_capturing_)
return;
- selected_image_->SetImage(
+ last_frame_.reset(new SkBitmap(frame));
+ SkBitmap user_image =
skia::ImageOperations::Resize(
*last_frame_,
- skia::ImageOperations::RESIZE_LANCZOS3,
+ skia::ImageOperations::RESIZE_BOX,
kUserImageSize,
- kUserImageSize));
- image_selected_ = true;
- ok_button_->SetEnabled(true);
- ok_button_->RequestFocus();
-}
+ kUserImageSize);
-void UserImageView::LocaleChanged() {
- UpdateLocalizedStrings();
- Layout();
+ user_image_->SetImage(&user_image);
}
-void UserImageView::Layout() {
- gfx::Insets insets = GetInsets();
-
- // Place title at the top.
- int title_x = insets.left() + kHorizontalMargin;
- int title_y = insets.top() + kVerticalMargin;
- int max_width = width() - insets.width() - kHorizontalMargin * 2;
- title_label_->SizeToFit(max_width);
-
- gfx::Size title_size = title_label_->GetPreferredSize();
- title_label_->SetBounds(title_x,
- title_y,
- std::min(max_width, title_size.width()),
- title_size.height());
-
- // Put OK button at the right bottom corner.
- gfx::Size ok_size = ok_button_->GetPreferredSize();
- int ok_x = width() - insets.right() - kHorizontalMargin - ok_size.width();
- int ok_y = height() - insets.bottom() - kVerticalMargin - ok_size.height();
- ok_button_->SetBounds(ok_x, ok_y, ok_size.width(), ok_size.height());
-
- // Put Cancel button to the left from OK.
- gfx::Size cancel_size = cancel_button_->GetPreferredSize();
- int cancel_x = ok_x - kHorizontalPadding - cancel_size.width();
- int cancel_y = ok_y; // Height should be the same for both buttons.
- cancel_button_->SetBounds(cancel_x,
- cancel_y,
- cancel_size.width(),
- cancel_size.height());
-
- // The area between buttons and title is for images.
- int title_bottom = title_label_->y() + title_label_->height();
- gfx::Rect images_area(insets.left() + kHorizontalMargin,
- title_bottom + kVerticalPadding,
- max_width,
- ok_button_->y() - title_bottom -
- 2 * kVerticalPadding);
-
- // Selected image is floating in the middle between top and height, near
- // the right border.
- gfx::Size selected_image_size = selected_image_->GetPreferredSize();
- int selected_image_x = images_area.right() - selected_image_size.width();
- int selected_image_y = images_area.y() +
- (images_area.height() - selected_image_size.height()) / 2;
- selected_image_->SetBounds(selected_image_x,
- selected_image_y,
- selected_image_size.width(),
- selected_image_size.height());
-
- // Video capture image is on the left side of the area, top aligned with
- // selected image.
- int video_button_x = images_area.x();
- int video_button_y = selected_image_y;
- video_button_->SetBounds(video_button_x,
- video_button_y,
- kVideoImageSize,
- kVideoImageSize);
-
- SchedulePaint();
+void UserImageView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && this == child)
+ WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
}
gfx::Size UserImageView::GetPreferredSize() {
@@ -220,16 +179,30 @@ gfx::Size UserImageView::GetPreferredSize() {
void UserImageView::ButtonPressed(
views::Button* sender, const views::Event& event) {
DCHECK(delegate_);
- if (sender == video_button_) {
- OnVideoImageClicked();
- return;
- }
- if (sender == ok_button_)
- delegate_->OnOK(selected_image_->GetImage());
- else if (sender == cancel_button_)
- delegate_->OnCancel();
- else
+ if (sender == snapshot_button_) {
+ if (is_capturing_) {
+ ok_button_->SetEnabled(true);
+ ok_button_->RequestFocus();
+ snapshot_button_->SetImage(
+ views::CustomButton::BS_NORMAL,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_USER_IMAGE_RECYCLE));
+ } else {
+ ok_button_->SetEnabled(false);
+ snapshot_button_->SetImage(
+ views::CustomButton::BS_NORMAL,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_USER_IMAGE_CAPTURE));
+ }
+ snapshot_button_->SchedulePaint();
+ is_capturing_ = !is_capturing_;
+ } else if (sender == ok_button_) {
+ delegate_->OnOK(user_image_->GetImage());
+ } else if (sender == skip_button_) {
+ delegate_->OnSkip();
+ } else {
NOTREACHED();
+ }
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_image_view.h b/chrome/browser/chromeos/login/user_image_view.h
index 028499d..7f59381 100644
--- a/chrome/browser/chromeos/login/user_image_view.h
+++ b/chrome/browser/chromeos/login/user_image_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_IMAGE_VIEW_H_
+#pragma once
#include "views/controls/button/button.h"
#include "views/view.h"
@@ -11,10 +12,10 @@
class SkBitmap;
namespace views {
+class ImageButton;
class ImageView;
class Label;
class NativeButton;
-class ImageButton;
} // namespace views
namespace chromeos {
@@ -33,51 +34,46 @@ class UserImageView : public views::View,
virtual void OnOK(const SkBitmap& image) = 0;
// Called if user decides to skip image selection screen.
- virtual void OnCancel() = 0;
+ virtual void OnSkip() = 0;
};
explicit UserImageView(Delegate* delegate);
virtual ~UserImageView();
- // Initialize view layout.
+ // Initializes this view, its children and layout.
void Init();
- // Update strings from the resources. Executed on language change.
- void UpdateLocalizedStrings();
-
- // Updates snapshot from camera on camera image view.
+ // Updates image from camera.
void UpdateVideoFrame(const SkBitmap& frame);
- // Called when user left-clicks video image control.
- void OnVideoImageClicked();
-
// Overridden from views::View:
virtual gfx::Size GetPreferredSize();
- virtual void Layout();
// Overridden from views::ButtonListener.
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
protected:
// views::View overrides:
- virtual void LocaleChanged();
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
private:
- // Delete and recreate native controls that fail to update preferred size
- // after string update.
- void RecreateNativeControls();
+ // Initializes layout manager for this view.
+ void InitLayout();
views::Label* title_label_;
views::NativeButton* ok_button_;
- views::NativeButton* cancel_button_;
- views::ImageButton* video_button_;
- views::ImageView* selected_image_;
+ views::NativeButton* skip_button_;
+ views::ImageButton* snapshot_button_;
+ views::ImageView* user_image_;
// Notifications receiver.
Delegate* delegate_;
- // Indicates that some image was selected and OK can be pressed.
- bool image_selected_;
+ // Indicates that we're in capturing mode. When |false|, new video frames
+ // are not shown to user if received.
+ bool is_capturing_;
// Last frame that was received from the camera in its original resolution.
scoped_ptr<SkBitmap> last_frame_;
diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc
index f0c18a8..f6edcbe 100644
--- a/chrome/browser/chromeos/login/user_manager.cc
+++ b/chrome/browser/chromeos/login/user_manager.cc
@@ -9,6 +9,7 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/time.h"
@@ -16,10 +17,14 @@
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/input_method_library.h"
+#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
#include "gfx/codec/png_codec.h"
#include "grit/theme_resources.h"
@@ -28,9 +33,13 @@ namespace chromeos {
namespace {
// A vector pref of the users who have logged into the device.
-const wchar_t kLoggedInUsers[] = L"LoggedInUsers";
+const char kLoggedInUsers[] = "LoggedInUsers";
// A dictionary that maps usernames to file paths to their images.
-const wchar_t kUserImages[] = L"UserImages";
+const char kUserImages[] = "UserImages";
+
+// Incognito user is represented by an empty string (since some code already
+// depends on that and it's hard to figure out what).
+const char kIncognitoUser[] = "";
// The one true UserManager.
static UserManager* user_manager_ = NULL;
@@ -42,8 +51,7 @@ void save_path_to_local_state(const std::string& username,
PrefService* local_state = g_browser_process->local_state();
DictionaryValue* images =
local_state->GetMutableDictionary(kUserImages);
- images->SetWithoutPathExpansion(UTF8ToWide(username),
- new StringValue(image_path));
+ images->SetWithoutPathExpansion(username, new StringValue(image_path));
LOG(INFO) << "Saving path to user image in Local State.";
local_state->SavePersistentPrefs();
}
@@ -74,6 +82,14 @@ void save_image_to_file(const SkBitmap& image,
username, image_path.value()));
}
+// Checks current user's ownership on file thread.
+void CheckOwnership() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
+ UserManager::Get()->set_current_user_is_owner(
+ OwnershipService::GetSharedInstance()->CurrentUserIsOwner());
+}
+
} // namespace
UserManager::User::User() {
@@ -124,8 +140,7 @@ std::vector<UserManager::User> UserManager::GetUsers() const {
std::string image_path;
if (image_it == user_images_.end()) {
if (prefs_images &&
- prefs_images->GetStringWithoutPathExpansion(
- ASCIIToWide(email), &image_path)) {
+ prefs_images->GetStringWithoutPathExpansion(email, &image_path)) {
// Insert the default image so we don't send another request if
// GetUsers is called twice.
user_images_[email] = user.image();
@@ -142,10 +157,17 @@ std::vector<UserManager::User> UserManager::GetUsers() const {
}
void UserManager::OffTheRecordUserLoggedIn() {
+ logged_in_user_ = User();
+ logged_in_user_.set_email(kIncognitoUser);
NotifyOnLogin();
}
void UserManager::UserLoggedIn(const std::string& email) {
+ if (email == kIncognitoUser) {
+ OffTheRecordUserLoggedIn();
+ return;
+ }
+
// Get a copy of the current users.
std::vector<User> users = GetUsers();
@@ -193,6 +215,25 @@ void UserManager::RemoveUser(const std::string& email) {
prefs->SavePersistentPrefs();
}
+bool UserManager::IsKnownUser(const std::string& email) {
+ std::vector<User> users = GetUsers();
+ for (std::vector<User>::iterator it = users.begin();
+ it < users.end();
+ ++it) {
+ if (it->email() == email)
+ return true;
+ }
+
+ return false;
+}
+
+void UserManager::SetLoggedInUserImage(const SkBitmap& image) {
+ if (logged_in_user_.email().empty())
+ return;
+ logged_in_user_.set_image(image);
+ OnImageLoaded(logged_in_user_.email(), image);
+}
+
void UserManager::SaveUserImage(const std::string& username,
const SkBitmap& image) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
@@ -224,7 +265,10 @@ void UserManager::OnImageLoaded(const std::string& username,
// Private constructor and destructor. Do nothing.
UserManager::UserManager()
- : ALLOW_THIS_IN_INITIALIZER_LIST(image_loader_(new UserImageLoader(this))) {
+ : ALLOW_THIS_IN_INITIALIZER_LIST(image_loader_(new UserImageLoader(this))),
+ current_user_is_owner_(false) {
+ registrar_.Add(this, NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
+ NotificationService::AllSources());
}
UserManager::~UserManager() {
@@ -237,8 +281,28 @@ void UserManager::NotifyOnLogin() {
Source<UserManager>(this),
Details<const User>(&logged_in_user_));
+ chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
+ SetDeferImeStartup(false);
+ // Shut down the IME so that it will reload the user's settings.
+ chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
+ StopInputMethodProcesses();
// Let the window manager know that we're logged in now.
WmIpc::instance()->SetLoggedInProperty(true);
+ // Ensure we've opened the real user's key/certificate database.
+ base::OpenPersistentNSSDB();
+
+ // Schedules current user ownership check on file thread.
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
+ NewRunnableFunction(&CheckOwnership));
+}
+
+void UserManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
+ NewRunnableFunction(&CheckOwnership));
+ }
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index 0e4ce31..d3e40be 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_MANAGER_H_
+#pragma once
#include <string>
#include <vector>
@@ -12,6 +13,8 @@
#include "base/hash_tables.h"
#include "base/ref_counted.h"
#include "chrome/browser/chromeos/login/user_image_loader.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
#include "third_party/skia/include/core/SkBitmap.h"
class PrefService;
@@ -20,7 +23,8 @@ namespace chromeos {
// This class provides a mechanism for discovering users who have logged
// into this chromium os device before and updating that list.
-class UserManager : public UserImageLoader::Delegate {
+class UserManager : public UserImageLoader::Delegate,
+ public NotificationObserver {
public:
// A class representing information about a previously logged in user.
class User {
@@ -65,11 +69,18 @@ class UserManager : public UserImageLoader::Delegate {
// Remove user from persistent list. NOTE: user's data won't be removed.
void RemoveUser(const std::string& email);
+ // Returns true if given user has logged into the device before.
+ bool IsKnownUser(const std::string& email);
+
// Returns the logged-in user.
const User& logged_in_user() {
return logged_in_user_;
}
+ // Sets image for logged-in user and sends LOGIN_USER_IMAGE_CHANGED
+ // notification about the image changed via NotificationService.
+ void SetLoggedInUserImage(const SkBitmap& image);
+
// Saves image to file and saves image path in local state preferences.
void SaveUserImage(const std::string& username,
const SkBitmap& image);
@@ -78,6 +89,19 @@ class UserManager : public UserImageLoader::Delegate {
virtual void OnImageLoaded(const std::string& username,
const SkBitmap& image);
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Accessor for current_user_is_owner_
+ bool current_user_is_owner() const {
+ return current_user_is_owner_;
+ }
+ void set_current_user_is_owner(bool current_user_is_owner) {
+ current_user_is_owner_ = current_user_is_owner;
+ }
+
private:
UserManager();
~UserManager();
@@ -95,6 +119,11 @@ class UserManager : public UserImageLoader::Delegate {
// The logged-in user.
User logged_in_user_;
+ // Cached flag of whether currently logged-in user is owner or not.
+ bool current_user_is_owner_;
+
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(UserManager);
};
diff --git a/chrome/browser/chromeos/login/user_view.cc b/chrome/browser/chromeos/login/user_view.cc
index 10db8b0..77afcb9 100644
--- a/chrome/browser/chromeos/login/user_view.cc
+++ b/chrome/browser/chromeos/login/user_view.cc
@@ -7,12 +7,14 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/button/text_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
-#include "views/controls/menu/menu_2.h"
+#include "views/controls/link.h"
#include "views/controls/throbber.h"
namespace {
@@ -20,28 +22,25 @@ namespace {
// Background color of the login status label and signout button.
const SkColor kSignoutBackgroundColor = 0xFF007700;
-// Left margin to the "Active User" text.
-const int kSignoutLeftOffset = 10;
+// Horiz/Vert insets for Signout view.
+const int kSignoutViewHorizontalInsets = 10;
+const int kSignoutViewVerticalInsets = 5;
-// Padding between menu button and left right image corner.
-const int kMenuButtonPadding = 4;
-
-const int kIdRemove = 1;
-const int kIdChangePhoto = 2;
+// Padding between remove button and top right image corner.
+const int kRemoveButtonPadding = 3;
} // namespace
namespace chromeos {
using login::kBackgroundColor;
-using login::kBorderSize;
using login::kTextColor;
using login::kUserImageSize;
// The view that shows the Sign out button below the user's image.
class SignoutView : public views::View {
public:
- explicit SignoutView(views::ButtonListener* listener) {
+ explicit SignoutView(views::LinkController* link_controller) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
const gfx::Font& font = rb.GetFont(ResourceBundle::SmallFont);
@@ -50,16 +49,15 @@ class SignoutView : public views::View {
active_user_label_->SetFont(font);
active_user_label_->SetColor(kTextColor);
- signout_button_ = new views::TextButton(
- listener, l10n_util::GetString(IDS_SCREEN_LOCK_SIGN_OUT));
- signout_button_->SetFont(font);
- signout_button_->SetEnabledColor(kTextColor);
- signout_button_->SetNormalHasBorder(false);
- signout_button_->set_tag(login::SIGN_OUT);
- signout_button_->SetFocusable(true);
+ signout_link_ = new views::Link(
+ l10n_util::GetString(IDS_SCREEN_LOCK_SIGN_OUT));
+ signout_link_->SetController(link_controller);
+ signout_link_->SetFont(font);
+ signout_link_->SetColor(kTextColor);
+ signout_link_->SetFocusable(true);
AddChildView(active_user_label_);
- AddChildView(signout_button_);
+ AddChildView(signout_link_);
set_background(views::Background::CreateSolidBackground(
kSignoutBackgroundColor));
@@ -68,51 +66,133 @@ class SignoutView : public views::View {
// views::View overrides.
virtual void Layout() {
gfx::Size label = active_user_label_->GetPreferredSize();
- gfx::Size button = signout_button_->GetPreferredSize();
- active_user_label_->SetBounds(kSignoutLeftOffset,
- (height() - label.height()) / 2,
- label.width(), label.height());
- signout_button_->SetBounds(
- width() - button.width(), (height() - button.height()) / 2,
+ gfx::Size button = signout_link_->GetPreferredSize();
+ active_user_label_->SetBounds(
+ kSignoutViewHorizontalInsets, (height() - label.height()) / 2,
+ label.width(), label.height());
+ signout_link_->SetBounds(
+ width() - button.width() - kSignoutViewHorizontalInsets,
+ (height() - button.height()) / 2,
button.width(), button.height());
}
virtual gfx::Size GetPreferredSize() {
gfx::Size label = active_user_label_->GetPreferredSize();
- gfx::Size button = signout_button_->GetPreferredSize();
+ gfx::Size button = signout_link_->GetPreferredSize();
return gfx::Size(label.width() + button.width(),
- std::max(label.height(), button.height()));
+ std::max(label.height(), button.height()) +
+ kSignoutViewVerticalInsets * 2);
}
- views::Button* signout_button() { return signout_button_; }
+ views::Link* signout_link() { return signout_link_; }
private:
friend class UserView;
views::Label* active_user_label_;
- views::TextButton* signout_button_;
+ views::Link* signout_link_;
DISALLOW_COPY_AND_ASSIGN(SignoutView);
};
-UserView::UserView(Delegate* delegate, bool is_login)
+class RemoveButton : public views::TextButton {
+ public:
+ RemoveButton(views::ButtonListener* listener,
+ const SkBitmap& icon,
+ const std::wstring& text,
+ const gfx::Point& top_right)
+ : views::TextButton(listener, std::wstring()),
+ icon_(icon),
+ text_(text),
+ top_right_(top_right) {
+ SetEnabledColor(SK_ColorWHITE);
+ SetDisabledColor(SK_ColorWHITE);
+ SetHighlightColor(SK_ColorWHITE);
+ SetHoverColor(SK_ColorWHITE);
+ SetIcon(icon_);
+ set_border(NULL);
+ UpdatePosition();
+ }
+
+ protected:
+ // Overridden from View:
+ virtual void OnMouseEntered(const views::MouseEvent& e) {
+ SetIcon(SkBitmap());
+ views::TextButton::SetText(text_);
+
+ const SkColor kStrokeColor = SK_ColorWHITE;
+ const SkColor kButtonColor = 0xFFE94949;
+ const int kStrokeWidth = 1;
+ const int kVerticalPadding = 4;
+ const int kHorizontalPadding = 8;
+ const int kCornerRadius = 4;
+
+ set_background(
+ CreateRoundedBackground(
+ kCornerRadius, kStrokeWidth, kButtonColor, kStrokeColor));
+
+ set_border(
+ views::Border::CreateEmptyBorder(kVerticalPadding,
+ kHorizontalPadding,
+ kVerticalPadding,
+ kHorizontalPadding));
+
+ UpdatePosition();
+ }
+
+ void OnMouseMoved(const views::MouseEvent& e) {
+ }
+
+ virtual void OnMouseExited(const views::MouseEvent& e) {
+ SetIcon(icon_);
+ views::TextButton::SetText(std::wstring());
+ ClearMaxTextSize();
+ set_background(NULL);
+ set_border(NULL);
+ UpdatePosition();
+ }
+
+ void SetText(const std::wstring& text) {
+ text_ = text;
+ }
+
+ private:
+ // Update button position and schedule paint event for the view and parent.
+ void UpdatePosition() {
+ gfx::Size size = GetPreferredSize();
+ gfx::Point origin = top_right_;
+ origin.Offset(-size.width(), 0);
+ SetBounds(gfx::Rect(origin, size));
+
+ if (GetParent())
+ GetParent()->SchedulePaint();
+ }
+
+ SkBitmap icon_;
+ std::wstring text_;
+ gfx::Point top_right_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoveButton);
+};
+
+UserView::UserView(Delegate* delegate, bool is_login, bool need_background)
: delegate_(delegate),
signout_view_(NULL),
image_view_(new views::ImageView()),
throbber_(CreateDefaultSmoothedThrobber()),
- menu_button_(NULL) {
+ remove_button_(NULL) {
DCHECK(delegate);
if (!is_login)
signout_view_ = new SignoutView(this);
- if (is_login)
- menu_button_ = new views::MenuButton(NULL, std::wstring(), this, true);
- Init();
+ Init(need_background);
}
-void UserView::Init() {
- image_view_->set_background(
- views::Background::CreateSolidBackground(kBackgroundColor));
+void UserView::Init(bool need_background) {
+ if (need_background) {
+ image_view_->set_background(
+ views::Background::CreateSolidBackground(kBackgroundColor));
+ }
if (throbber_) {
int w = throbber_->GetPreferredSize().width();
int h = throbber_->GetPreferredSize().height();
@@ -132,14 +212,15 @@ void UserView::Init() {
signout_view_->GetPreferredSize().height());
AddChildView(signout_view_);
}
- if (menu_button_) {
- int w = menu_button_->GetPreferredSize().width();
- int h = menu_button_->GetPreferredSize().height();
- menu_button_->SetBounds(kUserImageSize - w - kMenuButtonPadding,
- kMenuButtonPadding, w, h);
- menu_button_->SetVisible(false);
- AddChildView(menu_button_);
- }
+
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ remove_button_ = new RemoveButton(
+ this,
+ *rb.GetBitmapNamed(IDR_CLOSE_BAR_H),
+ l10n_util::GetString(IDS_LOGIN_REMOVE),
+ gfx::Point(kUserImageSize - kRemoveButtonPadding, kRemoveButtonPadding));
+ remove_button_->SetVisible(false);
+ AddChildView(remove_button_);
}
void UserView::SetImage(const SkBitmap& image) {
@@ -175,58 +256,28 @@ gfx::Size UserView::GetPreferredSize() {
void UserView::SetSignoutEnabled(bool enabled) {
DCHECK(signout_view_);
- signout_view_->signout_button_->SetEnabled(enabled);
+ signout_view_->signout_link_->SetEnabled(enabled);
}
-void UserView::ButtonPressed(views::Button* sender, const views::Event& event) {
+void UserView::LinkActivated(views::Link* source, int event_flags) {
DCHECK(delegate_);
- if (sender->tag() == login::SIGN_OUT)
+ DCHECK(signout_view_);
+ if (signout_view_->signout_link_ == source)
delegate_->OnSignout();
}
-void UserView::SetMenuVisible(bool flag) {
- DCHECK(menu_button_);
- menu_button_->SetVisible(flag);
-}
-
-void UserView::BuildMenu() {
- menu_model_.reset(new menus::SimpleMenuModel(this));
- menu_model_->AddItemWithStringId(kIdRemove, IDS_LOGIN_REMOVE);
- menu_model_->AddItemWithStringId(kIdChangePhoto, IDS_LOGIN_CHANGE_PHOTO);
- menu_.reset(new views::Menu2(menu_model_.get()));
-}
-
-void UserView::RunMenu(View* source, const gfx::Point& pt) {
- if (!menu_.get())
- BuildMenu();
-
- menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
-}
-
-bool UserView::IsCommandIdChecked(int command_id) const {
- return false;
-}
-
-bool UserView::IsCommandIdEnabled(int command_id) const {
- // TODO(dpolukhin): implement and enable change photo.
- return command_id != kIdChangePhoto;
+void UserView::SetRemoveButtonVisible(bool flag) {
+ remove_button_->SetVisible(flag);
}
-bool UserView::GetAcceleratorForCommandId(int command_id,
- menus::Accelerator* accelerator) {
- return false;
+void UserView::ButtonPressed(views::Button* sender, const views::Event& event) {
+ DCHECK(delegate_);
+ if (remove_button_ == sender)
+ delegate_->OnRemoveUser();
}
-void UserView::ExecuteCommand(int command_id) {
- switch (command_id) {
- case kIdRemove:
- delegate_->OnRemoveUser();
- break;
-
- case kIdChangePhoto:
- delegate_->OnChangePhoto();
- break;
- }
+void UserView::OnLocaleChanged() {
+ remove_button_->SetText(l10n_util::GetString(IDS_LOGIN_REMOVE));
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_view.h b/chrome/browser/chromeos/login/user_view.h
index 25eb9d9..772910c 100644
--- a/chrome/browser/chromeos/login/user_view.h
+++ b/chrome/browser/chromeos/login/user_view.h
@@ -4,20 +4,19 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USER_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_USER_VIEW_H_
+#pragma once
#include <string>
-#include "app/menus/simple_menu_model.h"
#include "views/controls/button/button.h"
-#include "views/controls/menu/view_menu_delegate.h"
+#include "views/controls/link.h"
#include "views/view.h"
class SkBitmap;
namespace views {
class ImageView;
-class Menu2;
-class MenuButton;
+class TextButton;
class Throbber;
} // namespace views
@@ -26,9 +25,8 @@ namespace chromeos {
class SignoutView;
class UserView : public views::View,
- public views::ButtonListener,
- public views::ViewMenuDelegate,
- public menus::SimpleMenuModel::Delegate {
+ public views::LinkController,
+ public views::ButtonListener {
public:
class Delegate {
public:
@@ -39,19 +37,17 @@ class UserView : public views::View,
// Notifies that user would like to remove this user from login screen.
virtual void OnRemoveUser() {}
-
- // Notifies that user would like to take new picture for this user on
- // login screen.
- virtual void OnChangePhoto() {}
};
// Creates UserView for login screen (|is_login| == true) or screen locker.
// On login screen this will have addition menu with user specific actions.
- // On screen locker it will have sign out button.
- UserView(Delegate* delegate, bool is_login);
+ // On screen locker it will have sign out button. |need_background| is needed
+ // to show image with transparent areas.
+ UserView(Delegate* delegate, bool is_login, bool need_background);
// view::View overrides.
virtual gfx::Size GetPreferredSize();
+ virtual void OnLocaleChanged();
// Sets the user's image.
void SetImage(const SkBitmap& image);
@@ -63,27 +59,21 @@ class UserView : public views::View,
void StartThrobber();
void StopThrobber();
- // Show/Hide menu for user specific actions.
- void SetMenuVisible(bool flag);
+ // Show/Hide remove button.
+ void SetRemoveButtonVisible(bool flag);
// Enable/Disable sign-out button.
void SetSignoutEnabled(bool enabled);
- // ButtonListener:
- virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
- // ViewMenuDelegate:
- virtual void RunMenu(View* source, const gfx::Point& pt);
+ // Implements LinkController.
+ // Called when a signout link is clicked.
+ virtual void LinkActivated(views::Link* source, int event_flags);
- // menus::SimpleMenuModel::Delegate:
- virtual bool IsCommandIdChecked(int command_id) const;
- virtual bool IsCommandIdEnabled(int command_id) const;
- virtual bool GetAcceleratorForCommandId(int command_id,
- menus::Accelerator* accelerator);
- virtual void ExecuteCommand(int command_id);
+ // Overridden from views::ButtonListener.
+ virtual void ButtonPressed(views::Button* sender, const views::Event& event);
private:
- void Init();
+ void Init(bool need_background);
void BuildMenu();
Delegate* delegate_;
@@ -95,10 +85,7 @@ class UserView : public views::View,
views::Throbber* throbber_;
- // Menu for user specific actions.
- scoped_ptr<menus::SimpleMenuModel> menu_model_;
- scoped_ptr<views::Menu2> menu_;
- views::MenuButton* menu_button_;
+ views::TextButton* remove_button_;
DISALLOW_COPY_AND_ASSIGN(UserView);
};
@@ -106,4 +93,3 @@ class UserView : public views::View,
} // chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_USER_VIEW_H_
-
diff --git a/chrome/browser/chromeos/login/view_screen.h b/chrome/browser/chromeos/login/view_screen.h
index ea9d437..81586e4 100644
--- a/chrome/browser/chromeos/login/view_screen.h
+++ b/chrome/browser/chromeos/login/view_screen.h
@@ -4,19 +4,27 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_VIEW_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_VIEW_SCREEN_H_
+#pragma once
#include "base/message_loop.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/wizard_screen.h"
+#include "gfx/size.h"
template <class V>
class ViewScreen : public WizardScreen {
public:
+ // Create screen with default size.
explicit ViewScreen(WizardScreenDelegate* delegate);
+
+ // Create screen with the specified size.
+ ViewScreen(WizardScreenDelegate* delegate, int width, int height);
virtual ~ViewScreen();
// Overridden from WizardScreen:
virtual void Show();
virtual void Hide();
+ virtual gfx::Size GetScreenSize() const { return size_; }
V* view() { return view_; }
@@ -35,6 +43,9 @@ class ViewScreen : public WizardScreen {
V* view_;
+ // Size of the screen.
+ gfx::Size size_;
+
DISALLOW_COPY_AND_ASSIGN(ViewScreen);
};
@@ -53,7 +64,16 @@ class DefaultViewScreen : public ViewScreen<V> {
template <class V>
ViewScreen<V>::ViewScreen(WizardScreenDelegate* delegate)
: WizardScreen(delegate),
- view_(NULL) {
+ view_(NULL),
+ size_(chromeos::login::kWizardScreenWidth,
+ chromeos::login::kWizardScreenHeight) {
+}
+
+template <class V>
+ViewScreen<V>::ViewScreen(WizardScreenDelegate* delegate, int width, int height)
+ : WizardScreen(delegate),
+ view_(NULL),
+ size_(width, height) {
}
template <class V>
diff --git a/chrome/browser/chromeos/login/web_page_screen.h b/chrome/browser/chromeos/login/web_page_screen.h
index 5c9bc17..c9746bf 100644
--- a/chrome/browser/chromeos/login/web_page_screen.h
+++ b/chrome/browser/chromeos/login/web_page_screen.h
@@ -4,8 +4,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_WEB_PAGE_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_WEB_PAGE_SCREEN_H_
+#pragma once
-#include "base/scoped_ptr.h"
#include "base/timer.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
@@ -37,18 +37,23 @@ class WebPageScreen : public TabContentsDelegate {
const gfx::Rect& initial_pos,
bool user_gesture) {}
virtual void ActivateContents(TabContents* contents) {}
+ virtual void DeactivateContents(TabContents* contents) {}
virtual void LoadingStateChanged(TabContents* source) = 0;
virtual void CloseContents(TabContents* source) {}
virtual bool IsPopup(TabContents* source) { return false; }
virtual void URLStarredChanged(TabContents* source, bool starred) {}
virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
- virtual bool ShouldAddNavigationToHistory() const { return false; }
+ virtual bool ShouldAddNavigationToHistory(
+ const history::HistoryAddPageArgs& add_page_args,
+ NavigationType::Type navigation_type) {
+ return false;
+ }
virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
virtual bool HandleContextMenu(const ContextMenuParams& params);
// Called by |timeout_timer_|. Stops page fetching and closes screen.
- void OnNetworkTimeout();
+ virtual void OnNetworkTimeout();
// Start/stop timeout timer.
void StartTimeoutTimer();
diff --git a/chrome/browser/chromeos/login/web_page_view.cc b/chrome/browser/chromeos/login/web_page_view.cc
index daac923..5205fa1 100644
--- a/chrome/browser/chromeos/login/web_page_view.cc
+++ b/chrome/browser/chromeos/login/web_page_view.cc
@@ -7,9 +7,9 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/callback.h"
+#include "base/logging.h"
#include "base/string_util.h"
#include "base/time.h"
-#include "base/values.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
@@ -53,7 +53,7 @@ WizardWebPageViewTabContents::WizardWebPageViewTabContents(
Profile* profile,
SiteInstance* site_instance,
WebPageDelegate* page_delegate)
- : TabContents(profile, site_instance, MSG_ROUTING_NONE, NULL),
+ : TabContents(profile, site_instance, MSG_ROUTING_NONE, NULL, NULL),
page_delegate_(page_delegate) {
}
@@ -63,15 +63,18 @@ void WizardWebPageViewTabContents::DidFailProvisionalLoadWithError(
int error_code,
const GURL& url,
bool showing_repost_interstitial) {
+ LOG(ERROR) << "Page load failed. URL = " << url << ", error: " << error_code;
page_delegate_->OnPageLoadFailed(url.spec());
}
void WizardWebPageViewTabContents::DidDisplayInsecureContent() {
- page_delegate_->OnPageLoadFailed("");
+ LOG(ERROR) << "Page load failed: did display insecure content";
+ page_delegate_->OnPageLoadFailed("Displayed insecure content");
}
void WizardWebPageViewTabContents::DidRunInsecureContent(
const std::string& security_origin) {
+ LOG(ERROR) << "Page load failed: did run insecure content";
page_delegate_->OnPageLoadFailed(security_origin);
}
@@ -80,6 +83,7 @@ void WizardWebPageViewTabContents::DocumentLoadedInFrame() {
}
void WizardWebPageViewTabContents::OnContentBlocked(ContentSettingsType type) {
+ LOG(ERROR) << "Page load failed: content blocked. Type: " << type;
page_delegate_->OnPageLoadFailed("");
}
diff --git a/chrome/browser/chromeos/login/web_page_view.h b/chrome/browser/chromeos/login/web_page_view.h
index 8197743..b497715 100644
--- a/chrome/browser/chromeos/login/web_page_view.h
+++ b/chrome/browser/chromeos/login/web_page_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_WEB_PAGE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_WEB_PAGE_VIEW_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 8506921..fa0f938 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -11,20 +11,25 @@
#include <string>
#include <vector>
-#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/system_library.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/account_screen.h"
+#include "chrome/browser/chromeos/login/apply_services_customization.h"
#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/eula_view.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/html_page_screen.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_screen.h"
#include "chrome/browser/chromeos/login/login_utils.h"
@@ -34,11 +39,13 @@
#include "chrome/browser/chromeos/login/update_screen.h"
#include "chrome/browser/chromeos/login/user_image_screen.h"
#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
#include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "unicode/timezone.h"
#include "views/accelerator.h"
@@ -49,39 +56,54 @@
namespace {
// A boolean pref of the OOBE complete flag.
-const wchar_t kOobeComplete[] = L"OobeComplete";
+const char kOobeComplete[] = "OobeComplete";
-// Default size of the OOBE screen.
-const int kWizardScreenWidth = 700;
-const int kWizardScreenHeight = 416;
+// Path to OEM partner startup customization manifest.
+const char kStartupCustomizationManifestPath[] =
+ "/mnt/partner_partition/etc/chromeos/startup_manifest.json";
+
+// Path to flag file indicating that OOBE was completed successfully.
+const char kOobeCompleteFlagFilePath[] =
+ "/home/chronos/.oobe_completed";
+
+// Upadate window will be behind the curtain at most |kMaximalCurtainTimeSec|.
+const int kMaximalCurtainTimeSec = 15;
+
+// Time in seconds that we wait for the device to reboot.
+// If reboot didn't happen, ask user to reboot device manually.
+const int kWaitForRebootTimeSec = 3;
// RootView of the Widget WizardController creates. Contains the contents of the
// WizardController.
class ContentView : public views::View {
public:
- ContentView(int window_x, int window_y, int screen_w, int screen_h)
- : window_x_(window_x),
- window_y_(window_y),
- screen_w_(screen_w),
- screen_h_(screen_h),
- accel_account_screen_(views::Accelerator(base::VKEY_A,
- false, true, true)),
- accel_login_screen_(views::Accelerator(base::VKEY_L,
- false, true, true)),
- accel_network_screen_(views::Accelerator(base::VKEY_N,
- false, true, true)),
- accel_update_screen_(views::Accelerator(base::VKEY_U,
- false, true, true)),
- accel_image_screen_(views::Accelerator(base::VKEY_I,
- false, true, true)),
- accel_eula_screen_(views::Accelerator(base::VKEY_E,
- false, true, true)) {
+ ContentView()
+ : accel_enable_accessibility_(
+ WizardAccessibilityHelper::GetAccelerator()) {
+ AddAccelerator(accel_enable_accessibility_);
+#if !defined(OFFICIAL_BUILD)
+ accel_account_screen_ = views::Accelerator(app::VKEY_A,
+ false, true, true);
+ accel_login_screen_ = views::Accelerator(app::VKEY_L,
+ false, true, true);
+ accel_network_screen_ = views::Accelerator(app::VKEY_N,
+ false, true, true);
+ accel_update_screen_ = views::Accelerator(app::VKEY_U,
+ false, true, true);
+ accel_image_screen_ = views::Accelerator(app::VKEY_I,
+ false, true, true);
+ accel_eula_screen_ = views::Accelerator(app::VKEY_E,
+ false, true, true);
+ accel_register_screen_ = views::Accelerator(app::VKEY_R,
+ false, true, true);
AddAccelerator(accel_account_screen_);
AddAccelerator(accel_login_screen_);
AddAccelerator(accel_network_screen_);
AddAccelerator(accel_update_screen_);
AddAccelerator(accel_image_screen_);
AddAccelerator(accel_eula_screen_);
+ AddAccelerator(accel_register_screen_);
+#endif
}
~ContentView() {
@@ -96,7 +118,11 @@ class ContentView : public views::View {
if (!controller)
return false;
- if (accel == accel_account_screen_) {
+ if (accel == accel_enable_accessibility_) {
+ WizardAccessibilityHelper::GetInstance()->EnableAccessibility(
+ controller->contents());
+#if !defined(OFFICIAL_BUILD)
+ } else if (accel == accel_account_screen_) {
controller->ShowAccountScreen();
} else if (accel == accel_login_screen_) {
controller->ShowLoginScreen();
@@ -108,6 +134,9 @@ class ContentView : public views::View {
controller->ShowUserImageScreen();
} else if (accel == accel_eula_screen_) {
controller->ShowEulaScreen();
+ } else if (accel == accel_register_screen_) {
+ controller->ShowRegistrationScreen();
+#endif
} else {
return false;
}
@@ -115,16 +144,6 @@ class ContentView : public views::View {
return true;
}
- void PaintBackground(gfx::Canvas* canvas) {
- if (painter_.get()) {
- // TODO(sky): nuke this once new login manager is in place. This needs to
- // exist because with no window manager transparency isn't really
- // supported.
- canvas->TranslateInt(-window_x_, -window_y_);
- painter_->Paint(screen_w_, screen_h_, canvas);
- }
- }
-
virtual void Layout() {
for (int i = 0; i < GetChildViewCount(); ++i) {
views::View* cur = GetChildViewAt(i);
@@ -136,17 +155,16 @@ class ContentView : public views::View {
private:
scoped_ptr<views::Painter> painter_;
- const int window_x_;
- const int window_y_;
- const int screen_w_;
- const int screen_h_;
-
+#if !defined(OFFICIAL_BUILD)
views::Accelerator accel_account_screen_;
views::Accelerator accel_login_screen_;
views::Accelerator accel_network_screen_;
views::Accelerator accel_update_screen_;
views::Accelerator accel_image_screen_;
views::Accelerator accel_eula_screen_;
+ views::Accelerator accel_register_screen_;
+#endif
+ views::Accelerator accel_enable_accessibility_;
DISALLOW_COPY_AND_ASSIGN(ContentView);
};
@@ -162,6 +180,26 @@ void DeleteWizardControllerAndLaunchBrowser(WizardController* controller) {
ProfileManager::GetDefaultProfile()));
}
+const chromeos::StartupCustomizationDocument* LoadStartupManifest() {
+ // Load partner customization startup manifest if it is available.
+ FilePath startup_manifest_path(kStartupCustomizationManifestPath);
+ if (file_util::PathExists(startup_manifest_path)) {
+ scoped_ptr<chromeos::StartupCustomizationDocument> customization(
+ new chromeos::StartupCustomizationDocument());
+ bool manifest_loaded = customization->LoadManifestFromFile(
+ startup_manifest_path);
+ if (manifest_loaded) {
+ LOG(INFO) << "Startup manifest loaded successfully";
+ return customization.release();
+ } else {
+ LOG(ERROR) << "Error loading startup manifest. " <<
+ kStartupCustomizationManifestPath;
+ }
+ }
+
+ return NULL;
+}
+
} // namespace
const char WizardController::kNetworkScreenName[] = "network";
@@ -171,6 +209,7 @@ const char WizardController::kUpdateScreenName[] = "update";
const char WizardController::kUserImageScreenName[] = "image";
const char WizardController::kEulaScreenName[] = "eula";
const char WizardController::kRegistrationScreenName[] = "register";
+const char WizardController::kHTMLPageScreenName[] = "html";
// Passing this parameter as a "first screen" initiates full OOBE flow.
const char WizardController::kOutOfBoxScreenName[] = "oobe";
@@ -191,6 +230,11 @@ WizardController::WizardController()
background_view_(NULL),
contents_(NULL),
current_screen_(NULL),
+#if defined(OFFICIAL_BUILD)
+ is_official_build_(true),
+#else
+ is_official_build_(false),
+#endif
is_out_of_box_(false),
is_test_mode_(false),
observer_(NULL) {
@@ -211,56 +255,43 @@ WizardController::~WizardController() {
void WizardController::Init(const std::string& first_screen_name,
const gfx::Rect& screen_bounds) {
+ LOG(INFO) << "Starting OOBE wizard with screen: " << first_screen_name;
DCHECK(!contents_);
+ first_screen_name_ = first_screen_name;
- int offset_x = (screen_bounds.width() - kWizardScreenWidth) / 2;
- int offset_y = (screen_bounds.height() - kWizardScreenHeight) / 2;
- int window_x = screen_bounds.x() + offset_x;
- int window_y = screen_bounds.y() + offset_y;
+ // When device is not registered yet we need to load startup manifest as well.
+ // In case of OOBE (network-EULA-update) manifest has been loaded in
+ // ShowLoginWizard().
+ if (IsOobeCompleted() && !IsDeviceRegistered())
+ SetCustomization(LoadStartupManifest());
- contents_ = new ContentView(offset_x, offset_y,
- screen_bounds.width(), screen_bounds.height());
-
- views::WidgetGtk* window =
- new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
- widget_ = window;
- window->MakeTransparent();
- // Window transparency makes background flicker through controls that
- // are constantly updating its contents (like image view with video
- // stream). Hence enabling double buffer.
- window->EnableDoubleBuffer(true);
- window->Init(NULL, gfx::Rect(window_x, window_y, kWizardScreenWidth,
- kWizardScreenHeight));
- chromeos::WmIpc::instance()->SetWindowType(
- window->GetNativeView(),
- chromeos::WM_IPC_WINDOW_LOGIN_GUEST,
- NULL);
- window->SetContentsView(contents_);
-
- PrefService* prefs = g_browser_process->local_state();
- bool oobe_complete = prefs->GetBoolean(kOobeComplete);
+ screen_bounds_ = screen_bounds;
+ contents_ = new ContentView();
+ bool oobe_complete = IsOobeCompleted();
if (!oobe_complete || first_screen_name == kOutOfBoxScreenName) {
is_out_of_box_ = true;
}
ShowFirstScreen(first_screen_name);
-
- // This keeps the window from flashing at startup.
- GdkWindow* gdk_window = window->GetNativeView()->window;
- gdk_window_set_back_pixmap(gdk_window, NULL, false);
}
void WizardController::Show() {
- DCHECK(widget_);
- widget_->Show();
+ // In tests we might startup without initial screen
+ // so widget_ hasn't been created yet.
+ if (first_screen_name_ != kTestNoScreenName)
+ DCHECK(widget_);
+ if (widget_)
+ widget_->Show();
}
void WizardController::ShowBackground(const gfx::Rect& bounds) {
DCHECK(!background_widget_);
background_widget_ =
chromeos::BackgroundView::CreateWindowContainingView(bounds,
+ GURL(),
&background_view_);
+ background_view_->SetOobeProgressBarVisible(true);
background_widget_->Show();
}
@@ -270,11 +301,12 @@ void WizardController::OwnBackground(
DCHECK(!background_widget_);
background_widget_ = background_widget;
background_view_ = background_view;
+ background_view_->OnOwnerChanged();
}
chromeos::NetworkScreen* WizardController::GetNetworkScreen() {
if (!network_screen_.get())
- network_screen_.reset(new chromeos::NetworkScreen(this, is_out_of_box_));
+ network_screen_.reset(new chromeos::NetworkScreen(this));
return network_screen_.get();
}
@@ -291,8 +323,11 @@ chromeos::AccountScreen* WizardController::GetAccountScreen() {
}
chromeos::UpdateScreen* WizardController::GetUpdateScreen() {
- if (!update_screen_.get())
+ if (!update_screen_.get()) {
update_screen_.reset(new chromeos::UpdateScreen(this));
+ update_screen_->SetMaximalCurtainTime(kMaximalCurtainTimeSec);
+ update_screen_->SetRebootCheckDelay(kWaitForRebootTimeSec);
+ }
return update_screen_.get();
}
@@ -314,13 +349,35 @@ chromeos::RegistrationScreen* WizardController::GetRegistrationScreen() {
return registration_screen_.get();
}
+chromeos::HTMLPageScreen* WizardController::GetHTMLPageScreen() {
+ if (!html_page_screen_.get()) {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ std::string url;
+ // It's strange but args may contains empty strings.
+ for (size_t i = 0; i < command_line->args().size(); i++) {
+ if (!command_line->args()[i].empty()) {
+ DCHECK(url.empty()) << "More than one URL in command line";
+ url = command_line->args()[i];
+ }
+ }
+ DCHECK(!url.empty()) << "No URL in commane line";
+ html_page_screen_.reset(new chromeos::HTMLPageScreen(this, url));
+ }
+ return html_page_screen_.get();
+}
+
void WizardController::ShowNetworkScreen() {
SetStatusAreaVisible(false);
SetCurrentScreen(GetNetworkScreen());
+ background_view_->SetOobeProgress(chromeos::BackgroundView::SELECT_NETWORK);
}
-void WizardController::ShowLoginScreen() {
+chromeos::ExistingUserController* WizardController::ShowLoginScreen() {
SetStatusAreaVisible(true);
+ background_view_->SetOobeProgress(chromeos::BackgroundView::SIGNIN);
+
+ // Initiate services customization.
+ chromeos::ApplyServicesCustomization::StartIfNeeded();
// When run under automation test show plain login screen.
if (!is_test_mode_ &&
@@ -338,44 +395,71 @@ void WizardController::ShowLoginScreen() {
controller->Init();
background_widget_ = NULL;
background_view_ = NULL;
+
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
- return;
+
+ return controller;
}
SetCurrentScreen(GetLoginScreen());
+ return NULL;
}
void WizardController::ShowAccountScreen() {
+ LOG(INFO) << "Showing create account screen.";
SetStatusAreaVisible(true);
SetCurrentScreen(GetAccountScreen());
}
void WizardController::ShowUpdateScreen() {
+ LOG(INFO) << "Showing update screen.";
SetStatusAreaVisible(true);
SetCurrentScreen(GetUpdateScreen());
+ // There is no special step for update.
+#if defined(OFFICIAL_BUILD)
+ background_view_->SetOobeProgress(chromeos::BackgroundView::EULA);
+#else
+ background_view_->SetOobeProgress(chromeos::BackgroundView::SELECT_NETWORK);
+#endif
}
void WizardController::ShowUserImageScreen() {
- SetStatusAreaVisible(true);
+ LOG(INFO) << "Showing user image screen.";
+ SetStatusAreaVisible(false);
SetCurrentScreen(GetUserImageScreen());
+ background_view_->SetOobeProgress(chromeos::BackgroundView::PICTURE);
}
void WizardController::ShowEulaScreen() {
+ LOG(INFO) << "Showing EULA screen.";
SetStatusAreaVisible(false);
SetCurrentScreen(GetEulaScreen());
+#if defined(OFFICIAL_BUILD)
+ background_view_->SetOobeProgress(chromeos::BackgroundView::EULA);
+#endif
}
void WizardController::ShowRegistrationScreen() {
+ if (!GetCustomization() ||
+ !GURL(GetCustomization()->registration_url()).is_valid()) {
+ LOG(INFO) <<
+ "Skipping registration screen: manifest not defined or invalid URL.";
+ OnRegistrationSkipped();
+ return;
+ }
+ LOG(INFO) << "Showing registration screen.";
SetStatusAreaVisible(true);
SetCurrentScreen(GetRegistrationScreen());
+#if defined(OFFICIAL_BUILD)
+ background_view_->SetOobeProgress(chromeos::BackgroundView::REGISTRATION);
+#endif
}
-void WizardController::SetStatusAreaVisible(bool visible) {
- // When ExistingUserController passes background ownership
- // to WizardController it happens after screen is shown.
- if (background_view_) {
- background_view_->SetStatusAreaVisible(visible);
- }
+void WizardController::ShowHTMLPageScreen() {
+ LOG(INFO) << "Showing HTML page screen.";
+ SetStatusAreaVisible(true);
+ background_view_->SetOobeProgressBarVisible(false);
+ SetCurrentScreen(GetHTMLPageScreen());
}
void WizardController::SetCustomization(
@@ -384,13 +468,25 @@ void WizardController::SetCustomization(
}
const chromeos::StartupCustomizationDocument*
- WizardController::GetCustomization() {
+ WizardController::GetCustomization() const {
return customization_.get();
}
+void WizardController::SkipRegistration() {
+ if (current_screen_ == GetRegistrationScreen())
+ OnRegistrationSkipped();
+ else
+ LOG(ERROR) << "Registration screen is not active.";
+}
+
// static
void WizardController::RegisterPrefs(PrefService* local_state) {
local_state->RegisterBooleanPref(kOobeComplete, false);
+ // Check if the pref is already registered in case
+ // Preferences::RegisterUserPrefs runs before this code in the future.
+ if (local_state->FindPreference(prefs::kAccessibilityEnabled) == NULL) {
+ local_state->RegisterBooleanPref(prefs::kAccessibilityEnabled, false);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -416,12 +512,11 @@ void WizardController::OnLoginCreateAccount() {
}
void WizardController::OnNetworkConnected() {
- if (is_out_of_box_) {
+ if (is_official_build_) {
+ ShowEulaScreen();
+ } else {
ShowUpdateScreen();
GetUpdateScreen()->StartUpdate();
- } else {
- // TODO(nkostylev): Remove this path after accelerator is removed.
- ShowLoginScreen();
}
}
@@ -432,22 +527,20 @@ void WizardController::OnNetworkOffline() {
}
void WizardController::OnAccountCreateBack() {
- ShowLoginScreen();
+ chromeos::ExistingUserController* controller = ShowLoginScreen();
+ if (controller)
+ controller->SelectNewUser();
}
void WizardController::OnAccountCreated() {
- ShowLoginScreen();
- chromeos::LoginScreen* login = GetLoginScreen();
- if (!username_.empty()) {
- login->view()->SetUsername(username_);
- if (!password_.empty()) {
- login->view()->SetPassword(password_);
- // TODO(dpolukhin): clear password memory for real. Now it is not
- // a problem becuase we can't extract password from the form.
- password_.clear();
- login->view()->Login();
- }
- }
+ chromeos::ExistingUserController* controller = ShowLoginScreen();
+ if (controller)
+ controller->LoginNewUser(username_, password_);
+ else
+ Login(username_, password_);
+ // TODO(dpolukhin): clear password memory for real. Now it is not
+ // a problem because we can't extract password from the form.
+ password_.clear();
}
void WizardController::OnConnectionFailed() {
@@ -456,12 +549,12 @@ void WizardController::OnConnectionFailed() {
}
void WizardController::OnUpdateCompleted() {
- ShowEulaScreen();
+ OnOOBECompleted();
}
void WizardController::OnEulaAccepted() {
- MarkOobeCompleted();
- ShowLoginScreen();
+ ShowUpdateScreen();
+ GetUpdateScreen()->StartUpdate();
}
void WizardController::OnUpdateErrorCheckingForUpdate() {
@@ -470,7 +563,7 @@ void WizardController::OnUpdateErrorCheckingForUpdate() {
// screen if there is any error checking for an update.
// They could use "browse without sign-in" feature to set up the network to be
// able to perform the update later.
- ShowEulaScreen();
+ OnOOBECompleted();
}
void WizardController::OnUpdateErrorUpdating() {
@@ -479,7 +572,7 @@ void WizardController::OnUpdateErrorUpdating() {
// TODO(nkostylev): Show message to the user explaining update error.
// TODO(nkostylev): Update should be required during OOBE.
// Temporary fix, need to migrate to new API. http://crosbug.com/4321
- ShowEulaScreen();
+ OnOOBECompleted();
}
void WizardController::OnUserImageSelected() {
@@ -499,8 +592,12 @@ void WizardController::OnUserImageSkipped() {
}
void WizardController::OnRegistrationSuccess() {
- // TODO(nkostylev): Registration screen should be shown on first sign in.
- ShowLoginScreen();
+ MarkDeviceRegistered();
+ if (chromeos::UserManager::Get()->logged_in_user().email().empty()) {
+ chromeos::LoginUtils::Get()->CompleteOffTheRecordLogin(start_url_);
+ } else {
+ ShowUserImageScreen();
+ }
}
void WizardController::OnRegistrationSkipped() {
@@ -508,26 +605,92 @@ void WizardController::OnRegistrationSkipped() {
OnRegistrationSuccess();
}
+void WizardController::OnOOBECompleted() {
+ MarkOobeCompleted();
+ ShowLoginScreen();
+}
+
///////////////////////////////////////////////////////////////////////////////
// WizardController, private:
+views::WidgetGtk* WizardController::CreateScreenWindow(
+ const gfx::Rect& bounds, bool initial_show) {
+ views::WidgetGtk* window =
+ new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
+ widget_ = window;
+ window->MakeTransparent();
+ // Window transparency makes background flicker through controls that
+ // are constantly updating its contents (like image view with video
+ // stream). Hence enabling double buffer.
+ window->EnableDoubleBuffer(true);
+ window->Init(NULL, bounds);
+ std::vector<int> params;
+ // For initial show WM would animate background window.
+ // Otherwise it stays unchaged.
+ params.push_back(initial_show);
+ chromeos::WmIpc::instance()->SetWindowType(
+ window->GetNativeView(),
+ chromeos::WM_IPC_WINDOW_LOGIN_GUEST,
+ &params);
+ window->SetContentsView(contents_);
+ return window;
+}
+
+gfx::Rect WizardController::GetWizardScreenBounds(int screen_width,
+ int screen_height) const {
+ int offset_x = (screen_bounds_.width() - screen_width) / 2;
+ int offset_y = (screen_bounds_.height() - screen_height) / 2;
+ int window_x = screen_bounds_.x() + offset_x;
+ int window_y = screen_bounds_.y() + offset_y;
+ return gfx::Rect(window_x, window_y, screen_width, screen_height);
+}
+
+
void WizardController::SetCurrentScreen(WizardScreen* new_current) {
- if (current_screen_ == new_current)
+ if (current_screen_ == new_current ||
+ new_current == NULL)
return;
- if (current_screen_)
+
+ bool initial_show = true;
+ if (current_screen_) {
+ initial_show = false;
current_screen_->Hide();
+ }
+
current_screen_ = new_current;
- if (current_screen_) {
- current_screen_->Show();
- contents_->Layout();
+ bool force_widget_show = false;
+ views::WidgetGtk* window = NULL;
+
+ gfx::Rect current_bounds;
+ if (widget_)
+ widget_->GetBounds(&current_bounds, false);
+ gfx::Size new_screen_size = current_screen_->GetScreenSize();
+ gfx::Rect new_bounds = GetWizardScreenBounds(new_screen_size.width(),
+ new_screen_size.height());
+ if (new_bounds != current_bounds) {
+ if (widget_)
+ widget_->Close();
+ force_widget_show = true;
+ window = CreateScreenWindow(new_bounds, initial_show);
}
+ current_screen_->Show();
+ contents_->Layout();
contents_->SchedulePaint();
+ if (force_widget_show) {
+ // This keeps the window from flashing at startup.
+ GdkWindow* gdk_window = window->GetNativeView()->window;
+ gdk_window_set_back_pixmap(gdk_window, NULL, false);
+ if (widget_)
+ widget_->Show();
+ }
}
-void WizardController::OnSetUserNamePassword(const std::string& username,
- const std::string& password) {
- username_ = username;
- password_ = password;
+void WizardController::SetStatusAreaVisible(bool visible) {
+ // When ExistingUserController passes background ownership
+ // to WizardController it happens after screen is shown.
+ if (background_view_) {
+ background_view_->SetStatusAreaVisible(visible);
+ }
}
void WizardController::ShowFirstScreen(const std::string& first_screen_name) {
@@ -547,7 +710,14 @@ void WizardController::ShowFirstScreen(const std::string& first_screen_name) {
} else if (first_screen_name == kEulaScreenName) {
ShowEulaScreen();
} else if (first_screen_name == kRegistrationScreenName) {
- ShowRegistrationScreen();
+ if (is_official_build_) {
+ ShowRegistrationScreen();
+ } else {
+ // Just proceed to image screen.
+ OnRegistrationSuccess();
+ }
+ } else if (first_screen_name == kHTMLPageScreenName) {
+ ShowHTMLPageScreen();
} else if (first_screen_name != kTestNoScreenName) {
if (is_out_of_box_) {
ShowNetworkScreen();
@@ -557,6 +727,25 @@ void WizardController::ShowFirstScreen(const std::string& first_screen_name) {
}
}
+void WizardController::Login(const std::string& username,
+ const std::string& password) {
+ chromeos::LoginScreen* login = GetLoginScreen();
+ if (username.empty())
+ return;
+ login->view()->SetUsername(username);
+
+ if (password.empty())
+ return;
+ login->view()->SetPassword(password);
+ login->view()->Login();
+}
+
+// static
+bool WizardController::IsOobeCompleted() {
+ return g_browser_process->local_state()->GetBoolean(kOobeComplete);
+}
+
+// static
void WizardController::MarkOobeCompleted() {
PrefService* prefs = g_browser_process->local_state();
prefs->SetBoolean(kOobeComplete, true);
@@ -564,9 +753,26 @@ void WizardController::MarkOobeCompleted() {
prefs->SavePersistentPrefs();
}
+// static
+bool WizardController::IsDeviceRegistered() {
+ FilePath oobe_complete_flag_file_path(kOobeCompleteFlagFilePath);
+ return file_util::PathExists(oobe_complete_flag_file_path);
+}
+
+// static
+void WizardController::MarkDeviceRegistered() {
+ // Create flag file for boot-time init scripts.
+ FilePath oobe_complete_path(kOobeCompleteFlagFilePath);
+ FILE* oobe_flag_file = file_util::OpenFile(oobe_complete_path, "w+b");
+ DCHECK(oobe_flag_file != NULL) << kOobeCompleteFlagFilePath;
+ if (oobe_flag_file != NULL)
+ file_util::CloseFile(oobe_flag_file);
+}
+
///////////////////////////////////////////////////////////////////////////////
// WizardController, chromeos::ScreenObserver overrides:
void WizardController::OnExit(ExitCodes exit_code) {
+ LOG(INFO) << "Wizard screen exit code: " << exit_code;
switch (exit_code) {
case LOGIN_SIGN_IN_SELECTED:
OnLoginSignInSelected();
@@ -611,6 +817,9 @@ void WizardController::OnExit(ExitCodes exit_code) {
case EULA_ACCEPTED:
OnEulaAccepted();
break;
+ case EULA_BACK:
+ ShowNetworkScreen();
+ break;
case REGISTRATION_SUCCESS:
OnRegistrationSuccess();
break;
@@ -622,6 +831,12 @@ void WizardController::OnExit(ExitCodes exit_code) {
}
}
+void WizardController::OnSetUserNamePassword(const std::string& username,
+ const std::string& password) {
+ username_ = username;
+ password_ = password;
+}
+
///////////////////////////////////////////////////////////////////////////////
// WizardController, WizardScreen overrides:
views::View* WizardController::GetWizardView() {
@@ -639,6 +854,10 @@ void ShowLoginWizard(const std::string& first_screen_name,
const gfx::Size& size) {
LOG(INFO) << "showing login screen: " << first_screen_name;
+ // The login screen will enable alternate keyboard layouts, but we don't want
+ // to start the IME process unless one is selected.
+ chromeos::CrosLibrary::Get()->GetInputMethodLibrary()->
+ SetDeferImeStartup(true);
// Tell the window manager that the user isn't logged in.
chromeos::WmIpc::instance()->SetLoggedInProperty(false);
@@ -648,7 +867,7 @@ void ShowLoginWizard(const std::string& first_screen_name,
const std::string locale = g_browser_process->GetApplicationLocale();
const std::string initial_input_method_id =
g_browser_process->local_state()->GetString(
- chromeos::kPreferredKeyboardLayout);
+ chromeos::language_prefs::kPreferredKeyboardLayout);
chromeos::input_method::EnableInputMethods(
locale, chromeos::input_method::kKeyboardLayoutsOnly,
initial_input_method_id);
@@ -657,8 +876,7 @@ void ShowLoginWizard(const std::string& first_screen_name,
gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(size));
// Check whether we need to execute OOBE process.
- bool oobe_complete = g_browser_process->local_state()->
- GetBoolean(kOobeComplete);
+ bool oobe_complete = WizardController::IsOobeCompleted();
if (first_screen_name.empty() &&
oobe_complete &&
@@ -667,52 +885,73 @@ void ShowLoginWizard(const std::string& first_screen_name,
switches::kEnableLoginImages)) {
std::vector<chromeos::UserManager::User> users =
chromeos::UserManager::Get()->GetUsers();
+
+ // Fix for users who updated device and thus never passed register screen.
+ // If we already have user we assume that it is not a second part of OOBE.
+ // See http://crosbug.com/6289
+ if (!WizardController::IsDeviceRegistered() && !users.empty()) {
+ LOG(INFO) << "Mark device registered because there are remembered users: "
+ << users.size();
+ WizardController::MarkDeviceRegistered();
+ }
+
// ExistingUserController deletes itself.
(new chromeos::ExistingUserController(users, screen_bounds))->Init();
+
+ // Initiate services customization.
+ chromeos::ApplyServicesCustomization::StartIfNeeded();
+
return;
}
- scoped_ptr<chromeos::StartupCustomizationDocument> customization;
-
- if (!oobe_complete) {
- // Load partner customization startup manifest if needed.
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kStartupManifest)) {
- customization.reset(new chromeos::StartupCustomizationDocument());
- FilePath manifest_path =
- CommandLine::ForCurrentProcess()->GetSwitchValuePath(
- switches::kStartupManifest);
- bool manifest_loaded = customization->LoadManifestFromFile(manifest_path);
- DCHECK(manifest_loaded) << manifest_path.value();
- }
+ // Create and show the wizard.
+ WizardController* controller = new WizardController();
- // Do UX customizations if needed.
- if (customization != NULL) {
- // Switch to initial locale if specified by customization.
- const std::string locale = customization->initial_locale();
- if (!locale.empty()) {
- chromeos::LanguageSwitchMenu::SwitchLanguage(locale);
- }
+ // Load startup manifest.
+ controller->SetCustomization(LoadStartupManifest());
- // Set initial timezone if specified by customization.
- const std::string timezone_name = customization->initial_timezone();
- if (!timezone_name.empty()) {
- icu::TimeZone* timezone = icu::TimeZone::createTimeZone(
- icu::UnicodeString::fromUTF8(timezone_name));
- chromeos::CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone);
+ std::string locale;
+ if (controller->GetCustomization()) {
+ // Switch to initial locale if specified by customization
+ // and has not been set yet. We cannot call
+ // chromeos::LanguageSwitchMenu::SwitchLanguage here before
+ // EmitLoginPromptReady.
+ const std::string current_locale =
+ g_browser_process->local_state()->GetString(
+ prefs::kApplicationLocale);
+ LOG(INFO) << "current locale: " << current_locale;
+ if (current_locale.empty()) {
+ locale = controller->GetCustomization()->initial_locale();
+ LOG(INFO) << "initial locale: " << locale;
+ if (!locale.empty()) {
+ ResourceBundle::ReloadSharedInstance(locale);
}
}
}
- // Create and show the wizard.
- WizardController* controller = new WizardController();
- if (!oobe_complete)
- controller->SetCustomization(customization.release());
controller->ShowBackground(screen_bounds);
controller->Init(first_screen_name, screen_bounds);
controller->Show();
+
if (chromeos::CrosLibrary::Get()->EnsureLoaded())
chromeos::CrosLibrary::Get()->GetLoginLibrary()->EmitLoginPromptReady();
+
+ if (controller->GetCustomization()) {
+ if (!locale.empty())
+ chromeos::LanguageSwitchMenu::SwitchLanguage(locale);
+
+ // Set initial timezone if specified by customization.
+ const std::string timezone_name =
+ controller->GetCustomization()->initial_timezone();
+ LOG(INFO) << "initial time zone: " << timezone_name;
+ // Apply locale customizations only once so preserve whatever locale
+ // user has changed to during OOBE.
+ if (!timezone_name.empty()) {
+ icu::TimeZone* timezone = icu::TimeZone::createTimeZone(
+ icu::UnicodeString::fromUTF8(timezone_name));
+ chromeos::CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone);
+ }
+ }
}
} // namespace browser
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 25394ff..44fb432 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_CONTROLLER_H_
+#pragma once
#include <string>
@@ -12,6 +13,8 @@
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/chromeos/login/view_screen.h"
#include "chrome/browser/chromeos/login/wizard_screen.h"
+#include "gfx/rect.h"
+#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
class PrefService;
@@ -22,6 +25,8 @@ namespace chromeos {
class AccountScreen;
class BackgroundView;
class EulaScreen;
+class ExistingUserController;
+class HTMLPageScreen;
class LoginScreen;
class NetworkScreen;
class RegistrationScreen;
@@ -37,6 +42,7 @@ class Rect;
namespace views {
class Views;
class Widget;
+class WidgetGtk;
}
// Class that manages control flow between wizard screens. Wizard controller
@@ -52,6 +58,18 @@ class WizardController : public chromeos::ScreenObserver,
return default_controller_;
}
+ // Returns OOBE completion status.
+ static bool IsOobeCompleted();
+
+ // Marks OOBE process as completed.
+ static void MarkOobeCompleted();
+
+ // Returns device registration completion status, i.e. second part of OOBE.
+ static bool IsDeviceRegistered();
+
+ // Marks device registered. i.e. second part of OOBE is completed.
+ static void MarkDeviceRegistered();
+
// Shows the first screen defined by |first_screen_name| or by default
// if the parameter is empty. |screen_bounds| are used to calculate position
// of the wizard screen.
@@ -79,33 +97,41 @@ class WizardController : public chromeos::ScreenObserver,
chromeos::UserImageScreen* GetUserImageScreen();
chromeos::EulaScreen* GetEulaScreen();
chromeos::RegistrationScreen* GetRegistrationScreen();
+ chromeos::HTMLPageScreen* GetHTMLPageScreen();
// Show specific screen.
void ShowNetworkScreen();
- void ShowLoginScreen();
void ShowAccountScreen();
void ShowUpdateScreen();
void ShowUserImageScreen();
void ShowEulaScreen();
void ShowRegistrationScreen();
+ void ShowHTMLPageScreen();
+ // Shows the default login screen and returns NULL or shows images login
+ // screen and returns the corresponding controller instance for optional
+ // tweaking.
+ chromeos::ExistingUserController* ShowLoginScreen();
// Returns a pointer to the current screen or NULL if there's no such
// screen.
WizardScreen* current_screen() const { return current_screen_; }
- // True if WizardController is in OOBE mode.
- bool is_oobe() { return is_out_of_box_; }
-
// Overrides observer for testing.
void set_observer(ScreenObserver* observer) { observer_ = observer; }
+ // Set URL to open on browser launch.
+ void set_start_url(const GURL& start_url) { start_url_ = start_url; }
+
// Sets partner startup customization. WizardController takes ownership
// of the document object.
void SetCustomization(
const chromeos::StartupCustomizationDocument* customization);
// Returns partner startup customization document owned by WizardController.
- const chromeos::StartupCustomizationDocument* GetCustomization();
+ const chromeos::StartupCustomizationDocument* GetCustomization() const;
+
+ // If being at register screen proceeds to the next one.
+ void SkipRegistration();
// Registers OOBE preferences.
static void RegisterPrefs(PrefService* local_state);
@@ -119,6 +145,7 @@ class WizardController : public chromeos::ScreenObserver,
static const char kOutOfBoxScreenName[];
static const char kTestNoScreenName[];
static const char kEulaScreenName[];
+ static const char kHTMLPageScreenName[];
private:
// Exit handlers:
@@ -138,6 +165,17 @@ class WizardController : public chromeos::ScreenObserver,
void OnUserImageSkipped();
void OnRegistrationSuccess();
void OnRegistrationSkipped();
+ void OnOOBECompleted();
+
+ // Creates wizard screen window with the specified |bounds|.
+ // If |initial_show| initial animation (window & background) is shown.
+ // Otherwise only window is animated.
+ views::WidgetGtk* CreateScreenWindow(const gfx::Rect& bounds,
+ bool initial_show);
+
+ // Returns bounds for the wizard screen host window in screen coordinates.
+ // Calculates bounds using screen_bounds_.
+ gfx::Rect GetWizardScreenBounds(int screen_width, int screen_height) const;
// Switches from one screen to another.
void SetCurrentScreen(WizardScreen* screen);
@@ -158,8 +196,8 @@ class WizardController : public chromeos::ScreenObserver,
// sets it as the current one.
void ShowFirstScreen(const std::string& first_screen_name);
- // Marks OOBE process as completed.
- void MarkOobeCompleted();
+ // Logs in the specified user via default login screen.
+ void Login(const std::string& username, const std::string& password);
// Widget we're showing in.
views::Widget* widget_;
@@ -171,6 +209,9 @@ class WizardController : public chromeos::ScreenObserver,
// Contents view.
views::View* contents_;
+ // Used to calculate position of the wizard screen.
+ gfx::Rect screen_bounds_;
+
// Screens.
scoped_ptr<chromeos::NetworkScreen> network_screen_;
scoped_ptr<chromeos::LoginScreen> login_screen_;
@@ -179,6 +220,7 @@ class WizardController : public chromeos::ScreenObserver,
scoped_ptr<chromeos::UserImageScreen> user_image_screen_;
scoped_ptr<chromeos::EulaScreen> eula_screen_;
scoped_ptr<chromeos::RegistrationScreen> registration_screen_;
+ scoped_ptr<chromeos::HTMLPageScreen> html_page_screen_;
// Screen that's currently active.
WizardScreen* current_screen_;
@@ -186,6 +228,9 @@ class WizardController : public chromeos::ScreenObserver,
std::string username_;
std::string password_;
+ // True if running official BUILD.
+ bool is_official_build_;
+
// True if full OOBE flow should be shown.
bool is_out_of_box_;
@@ -193,6 +238,9 @@ class WizardController : public chromeos::ScreenObserver,
// login screen.
bool is_test_mode_;
+ // Value of the screen name that WizardController was started with.
+ std::string first_screen_name_;
+
// NULL by default - controller itself is observer. Mock could be assigned.
ScreenObserver* observer_;
@@ -202,8 +250,12 @@ class WizardController : public chromeos::ScreenObserver,
// Partner startup customizations.
scoped_ptr<const chromeos::StartupCustomizationDocument> customization_;
+ // URL to open on browser launch.
+ GURL start_url_;
+
FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowErrorNetwork);
FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowErrorUpdate);
+ FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest, ControlFlowEulaDeclined);
FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest,
ControlFlowLanguageOnLogin);
FRIEND_TEST_ALL_PREFIXES(WizardControllerFlowTest,
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 6459286..e38fdda 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -47,7 +47,7 @@ CreateMockWizardScreenHelper<T>::Create(WizardController* wizard) {
template <> MockOutShowHide<chromeos::NetworkScreen>*
CreateMockWizardScreenHelper<chromeos::NetworkScreen>::Create(
WizardController* wizard) {
- return new MockOutShowHide<chromeos::NetworkScreen>(wizard, true);
+ return new MockOutShowHide<chromeos::NetworkScreen>(wizard);
}
#define MOCK(mock_var, screen_name, mocked_class) \
@@ -71,7 +71,7 @@ class WizardControllerTest : public chromeos::WizardInProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(WizardControllerTest, SwitchLanguage) {
WizardController* const wizard = controller();
ASSERT_TRUE(wizard != NULL);
- wizard->ShowFirstScreen(WizardController::kOutOfBoxScreenName);
+ wizard->ShowFirstScreen(WizardController::kNetworkScreenName);
views::View* current_screen = wizard->contents();
ASSERT_TRUE(current_screen != NULL);
@@ -105,6 +105,9 @@ class WizardControllerFlowTest : public WizardControllerTest {
virtual Browser* CreateBrowser(Profile* profile) {
Browser* ret = WizardControllerTest::CreateBrowser(profile);
+ // Make sure that OOBE is run as an "official" build.
+ WizardController::default_controller()->is_official_build_ = true;
+
// Set up the mocks for all screens.
MOCK(mock_account_screen_, account_screen_, chromeos::AccountScreen);
MOCK(mock_login_screen_, login_screen_, chromeos::LoginScreen);
@@ -115,7 +118,7 @@ class WizardControllerFlowTest : public WizardControllerTest {
// Switch to the initial screen.
EXPECT_EQ(NULL, controller()->current_screen());
EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
- controller()->ShowFirstScreen(WizardController::kOutOfBoxScreenName);
+ controller()->ShowFirstScreen(WizardController::kNetworkScreenName);
return ret;
}
@@ -133,19 +136,20 @@ class WizardControllerFlowTest : public WizardControllerTest {
IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowMain) {
EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+ EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+ controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);
+
+ EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
+ EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
- controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);
+ controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);
EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
- EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
- controller()->OnExit(chromeos::ScreenObserver::UPDATE_INSTALLED);
-
- EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
- EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
+ EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
- controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);
+ controller()->OnExit(chromeos::ScreenObserver::UPDATE_INSTALLED);
EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
@@ -163,19 +167,43 @@ IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowMain) {
IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorUpdate) {
EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
- EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
- EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
+ EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
+ EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+ EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);
+ EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
+ EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
+ EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
+ EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
+ controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);
+
EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
- EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+ EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
EXPECT_CALL(*mock_eula_screen_, Hide()).Times(0); // last transition
+ EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
controller()->OnExit(
chromeos::ScreenObserver::UPDATE_ERROR_UPDATING);
+ EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
+}
+
+IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowEulaDeclined) {
+ EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
+ EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
+ EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+ EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+ controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);
+
EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
+ EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
+ EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
+ EXPECT_CALL(*mock_network_screen_, Hide()).Times(0); // last transition
+ controller()->OnExit(chromeos::ScreenObserver::EULA_BACK);
+
+ EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
}
IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorNetwork) {
@@ -191,41 +219,46 @@ IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, Accelerators) {
views::FocusManager* focus_manager =
controller()->contents()->GetFocusManager();
- views::Accelerator accel_account_screen(base::VKEY_A, false, true, true);
- views::Accelerator accel_login_screen(base::VKEY_L, false, true, true);
- views::Accelerator accel_network_screen(base::VKEY_N, false, true, true);
- views::Accelerator accel_update_screen(base::VKEY_U, false, true, true);
- views::Accelerator accel_image_screen(base::VKEY_I, false, true, true);
- views::Accelerator accel_eula_screen(base::VKEY_E, false, true, true);
+ views::Accelerator accel_account_screen(app::VKEY_A, false, true, true);
+ views::Accelerator accel_login_screen(app::VKEY_L, false, true, true);
+ views::Accelerator accel_network_screen(app::VKEY_N, false, true, true);
+ views::Accelerator accel_update_screen(app::VKEY_U, false, true, true);
+ views::Accelerator accel_image_screen(app::VKEY_I, false, true, true);
+ views::Accelerator accel_eula_screen(app::VKEY_E, false, true, true);
EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_account_screen));
EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
+ focus_manager = controller()->contents()->GetFocusManager();
EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_login_screen));
EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
+ focus_manager = controller()->contents()->GetFocusManager();
EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_network_screen));
EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
+ focus_manager = controller()->contents()->GetFocusManager();
EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_update_screen));
EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
+ focus_manager = controller()->contents()->GetFocusManager();
EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_image_screen));
EXPECT_EQ(controller()->GetUserImageScreen(), controller()->current_screen());
+ focus_manager = controller()->contents()->GetFocusManager();
EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_eula_screen));
EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
}
-COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 17,
+COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 18,
add_tests_for_new_control_flow_you_just_introduced);
diff --git a/chrome/browser/chromeos/login/wizard_in_process_browser_test.h b/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
index d9b634e..da23b35 100644
--- a/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
+++ b/chrome/browser/chromeos/login/wizard_in_process_browser_test.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_IN_PROCESS_BROWSER_TEST_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_IN_PROCESS_BROWSER_TEST_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/login/wizard_screen.h b/chrome/browser/chromeos/login/wizard_screen.h
index 3eb3e9e..d0b0d8b 100644
--- a/chrome/browser/chromeos/login/wizard_screen.h
+++ b/chrome/browser/chromeos/login/wizard_screen.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_SCREEN_H_
+#pragma once
#include "gfx/canvas.h"
@@ -11,6 +12,9 @@ class WizardScreen;
namespace chromeos {
class ScreenObserver;
} // namespace chromeos
+namespace gfx {
+class Size;
+} // namespace gfx
namespace views {
class View;
} // namespace views
@@ -36,6 +40,8 @@ class WizardScreen {
virtual void Show() = 0;
// Makes wizard screen invisible.
virtual void Hide() = 0;
+ // Returns the size the screen.
+ virtual gfx::Size GetScreenSize() const = 0;
protected:
explicit WizardScreen(WizardScreenDelegate* delegate): delegate_(delegate) {}
@@ -51,4 +57,3 @@ class WizardScreen {
};
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_WIZARD_SCREEN_H_
-
diff --git a/chrome/browser/chromeos/low_battery_observer.cc b/chrome/browser/chromeos/low_battery_observer.cc
index b923f08..0513cc2 100644
--- a/chrome/browser/chromeos/low_battery_observer.cc
+++ b/chrome/browser/chromeos/low_battery_observer.cc
@@ -72,7 +72,7 @@ void LowBatteryObserver::PowerChanged(PowerLibrary* object) {
void LowBatteryObserver::Show(base::TimeDelta remaining, bool urgent) {
notification_.Show(l10n_util::GetStringFUTF16(IDS_LOW_BATTERY_MESSAGE,
- WideToUTF16(TimeFormat::TimeRemaining(remaining))), urgent);
+ TimeFormat::TimeRemaining(remaining)), urgent, true);
remaining_ = remaining.InMinutes();
}
@@ -81,4 +81,3 @@ void LowBatteryObserver::Hide() {
}
} // namespace chromeos
-
diff --git a/chrome/browser/chromeos/low_battery_observer.h b/chrome/browser/chromeos/low_battery_observer.h
index 5bbed0a..1756f50 100644
--- a/chrome/browser/chromeos/low_battery_observer.h
+++ b/chrome/browser/chromeos/low_battery_observer.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOW_BATTERY_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_LOW_BATTERY_OBSERVER_H_
+#pragma once
#include "base/basictypes.h"
#include "base/time.h"
diff --git a/chrome/browser/chromeos/mock_cros_settings.cc b/chrome/browser/chromeos/mock_cros_settings.cc
deleted file mode 100644
index 5cec066..0000000
--- a/chrome/browser/chromeos/mock_cros_settings.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2010 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/chromeos/mock_cros_settings.h"
-
-namespace chromeos {
-
-MockCrosSettings::MockCrosSettings()
- : dict_(new DictionaryValue) {
- // Some mock settings
- SetBoolean(kAccountsPrefAllowBWSI, true);
- SetBoolean(kAccountsPrefAllowGuest, true);
-
- ListValue* user_list = new ListValue;
-
- DictionaryValue* mock_user = new DictionaryValue;
- mock_user->SetString(L"email", L"mock_user_1@gmail.com");
- user_list->Append(mock_user);
-
- mock_user = new DictionaryValue;
- mock_user->SetString(L"email", L"mock_user_2@gmail.com");
- user_list->Append(mock_user);
-
- Set(kAccountsPrefUsers, user_list);
-}
-
-void MockCrosSettings::Set(const std::wstring& path, Value* in_value) {
- dict_->Set(path, in_value);
-}
-
-bool MockCrosSettings::Get(const std::wstring& path, Value** out_value) const {
- return dict_->Get(path, out_value);
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/mock_cros_settings.h b/chrome/browser/chromeos/mock_cros_settings.h
deleted file mode 100644
index 606dbdf..0000000
--- a/chrome/browser/chromeos/mock_cros_settings.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_MOCK_CROS_SETTINGS_H_
-#define CHROME_BROWSER_CHROMEOS_MOCK_CROS_SETTINGS_H_
-
-#include "base/singleton.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/chromeos/cros_settings.h"
-
-namespace chromeos {
-
-class MockCrosSettings : public CrosSettings {
- public:
- virtual void Set(const std::wstring& path, Value* in_value);
- virtual bool Get(const std::wstring& path, Value** out_value) const;
-
- private:
- scoped_ptr<DictionaryValue> dict_;
-
- MockCrosSettings();
- friend struct DefaultSingletonTraits<MockCrosSettings>;
-
- DISALLOW_COPY_AND_ASSIGN(MockCrosSettings);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_MOCK_CROS_SETTINGS_H_
diff --git a/chrome/browser/chromeos/native_dialog_window.cc b/chrome/browser/chromeos/native_dialog_window.cc
index ec9ffbf..200dd62 100644
--- a/chrome/browser/chromeos/native_dialog_window.cc
+++ b/chrome/browser/chromeos/native_dialog_window.cc
@@ -4,9 +4,12 @@
#include "chrome/browser/chromeos/native_dialog_window.h"
+#include <gtk/gtk.h>
+
#include "app/gtk_signal.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/frame/bubble_window.h"
#include "views/controls/native/native_view_host.h"
#include "views/window/dialog_delegate.h"
#include "views/window/non_client_view.h"
@@ -18,6 +21,30 @@ const int kDialogPadding = 3;
const char kNativeDialogHost[] = "_chromeos_native_dialog_host_";
+// TODO(xiyuan): Use gtk_window_get_default_widget with GTK 2.14+.
+// Gets the default widget of given dialog.
+GtkWidget* GetDialogDefaultWidget(GtkDialog* dialog) {
+ GtkWidget* default_widget = NULL;
+
+ GList* children = gtk_container_get_children(
+ GTK_CONTAINER(dialog->action_area));
+
+ GList* current = children;
+ while (current) {
+ GtkWidget* widget = reinterpret_cast<GtkWidget*>(current->data);
+ if (GTK_WIDGET_HAS_DEFAULT(widget)) {
+ default_widget = widget;
+ break;
+ }
+
+ current = g_list_next(current);
+ }
+
+ g_list_free(children);
+
+ return default_widget;
+}
+
} // namespace
namespace chromeos {
@@ -165,6 +192,12 @@ void NativeDialogHost::Init() {
if (contents_view_)
return;
+ // Get default widget of the dialog.
+ GtkWidget* default_widget = GetDialogDefaultWidget(GTK_DIALOG(dialog_));
+
+ // Get focus widget of the dialog.
+ GtkWidget* focus_widget = gtk_window_get_focus(GTK_WINDOW(dialog_));
+
// Create a GtkAlignment as dialog contents container.
GtkWidget* contents = gtk_alignment_new(0.5, 0.5, 1.0, 1.0);
gtk_alignment_set_padding(GTK_ALIGNMENT(contents),
@@ -185,6 +218,8 @@ void NativeDialogHost::Init() {
gtk_widget_show_all(contents);
contents_view_ = new views::NativeViewHost();
+ contents_view_->set_background(views::Background::CreateSolidBackground(
+ BubbleWindow::kBackgroundColor));
AddChildView(contents_view_);
contents_view_->Attach(contents);
@@ -207,6 +242,12 @@ void NativeDialogHost::Init() {
}
CheckSize();
+
+ if (default_widget)
+ gtk_widget_grab_default(default_widget);
+
+ if (focus_widget)
+ gtk_widget_grab_focus(focus_widget);
}
void NativeDialogHost::CheckSize() {
@@ -224,7 +265,7 @@ void ShowNativeDialog(gfx::NativeWindow parent,
const gfx::Size& min_size) {
NativeDialogHost* native_dialog_host =
new NativeDialogHost(native_dialog, flags, size, min_size);
- views::Window::CreateChromeWindow(parent, gfx::Rect(), native_dialog_host);
+ BubbleWindow::Create(parent, gfx::Rect(), native_dialog_host);
native_dialog_host->window()->Show();
}
diff --git a/chrome/browser/chromeos/native_dialog_window.h b/chrome/browser/chromeos/native_dialog_window.h
index 6792231..47a478b 100644
--- a/chrome/browser/chromeos/native_dialog_window.h
+++ b/chrome/browser/chromeos/native_dialog_window.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_NATIVE_DIALOG_WINDOW_H_
#define CHROME_BROWSER_CHROMEOS_NATIVE_DIALOG_WINDOW_H_
+#pragma once
#include "gfx/native_widget_types.h"
diff --git a/chrome/browser/chromeos/network_list.cc b/chrome/browser/chromeos/network_list.cc
index f92190f..9780642 100644
--- a/chrome/browser/chromeos/network_list.cc
+++ b/chrome/browser/chromeos/network_list.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/chromeos/network_list.h"
#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "grit/generated_resources.h"
diff --git a/chrome/browser/chromeos/network_list.h b/chrome/browser/chromeos/network_list.h
index f08b23a..5b320fc 100644
--- a/chrome/browser/chromeos/network_list.h
+++ b/chrome/browser/chromeos/network_list.h
@@ -4,10 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_LIST_H_
#define CHROME_BROWSER_CHROMEOS_NETWORK_LIST_H_
+#pragma once
#include <string>
#include <vector>
+#include "base/string16.h"
#include "chrome/browser/chromeos/cros/network_library.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/network_message_observer.cc b/chrome/browser/chromeos/network_message_observer.cc
index 192ff28..c87a21b 100644
--- a/chrome/browser/chromeos/network_message_observer.cc
+++ b/chrome/browser/chromeos/network_message_observer.cc
@@ -5,28 +5,125 @@
#include "chrome/browser/chromeos/network_message_observer.h"
#include "app/l10n_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/options/network_config_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
namespace chromeos {
NetworkMessageObserver::NetworkMessageObserver(Profile* profile)
- : notification_(profile, "network_connection.chromeos",
+ : initialized_(false),
+ notification_(profile, "network_connection.chromeos",
IDR_NOTIFICATION_NETWORK_FAILED,
l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE)) {
+ NetworkChanged(CrosLibrary::Get()->GetNetworkLibrary());
+ initialized_ = true;
}
NetworkMessageObserver::~NetworkMessageObserver() {
notification_.Hide();
}
+void NetworkMessageObserver::CreateModalPopup(views::WindowDelegate* view) {
+ Browser* browser = BrowserList::GetLastActive();
+ if (browser && browser->type() != Browser::TYPE_NORMAL) {
+ browser = BrowserList::FindBrowserWithType(browser->profile(),
+ Browser::TYPE_NORMAL,
+ true);
+ }
+ DCHECK(browser);
+ views::Window* window = views::Window::CreateChromeWindow(
+ browser->window()->GetNativeHandle(), gfx::Rect(), view);
+ window->SetIsAlwaysOnTop(true);
+ window->Show();
+}
+
void NetworkMessageObserver::NetworkChanged(NetworkLibrary* obj) {
- // TODO(chocobo): Display open networks notification here.
-// notification_.Show(l10n_util::GetStringFUTF16(
-// IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
-// ASCIIToUTF16(network.name())), true);
+ const WifiNetworkVector& wifi_networks = obj->wifi_networks();
+ const CellularNetworkVector& cellular_networks = obj->cellular_networks();
+
+ NetworkConfigView* view = NULL;
+ std::string new_failed_network;
+ // Check to see if we have any newly failed wifi network.
+ for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
+ it < wifi_networks.end(); it++) {
+ const WifiNetwork& wifi = *it;
+ if (wifi.failed()) {
+ ServicePathWifiMap::iterator iter =
+ wifi_networks_.find(wifi.service_path());
+ // If the network did not previously exist, then don't do anything.
+ // For example, if the user travels to a location and finds a service
+ // that has previously failed, we don't want to show a notification.
+ if (iter == wifi_networks_.end())
+ continue;
+
+ const WifiNetwork& wifi_old = iter->second;
+ // If this network was in a failed state previously, then it's not new.
+ if (wifi_old.failed())
+ continue;
+
+ // Display login box again for bad_passphrase and bad_wepkey errors.
+ if (wifi.error() == ERROR_BAD_PASSPHRASE ||
+ wifi.error() == ERROR_BAD_WEPKEY) {
+ // The NetworkConfigView will show the appropriate error message.
+ view = new NetworkConfigView(wifi, true);
+ // There should only be one wifi network that failed to connect.
+ // If for some reason, we have more than one failure,
+ // we only display the first one. So we break here.
+ break;
+ }
+
+ // If network connection failed, display a notification.
+ // We only do this if we were trying to make a new connection.
+ // So if a previously connected network got disconnected for any reason,
+ // we don't display notification.
+ if (wifi_old.connecting()) {
+ new_failed_network = wifi.name();
+ // Like above, there should only be one newly failed network.
+ break;
+ }
+ }
+
+ // If we find any network connecting, we hide any notifications.
+ if (wifi.connecting()) {
+ notification_.Hide();
+ }
+ }
+
+ // Refresh stored networks.
+ wifi_networks_.clear();
+ for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
+ it < wifi_networks.end(); it++) {
+ const WifiNetwork& wifi = *it;
+ wifi_networks_[wifi.service_path()] = wifi;
+ }
+ cellular_networks_.clear();
+ for (CellularNetworkVector::const_iterator it = cellular_networks.begin();
+ it < cellular_networks.end(); it++) {
+ const CellularNetwork& cellular = *it;
+ cellular_networks_[cellular.service_path()] = cellular;
+ }
+
+ // Show notification if necessary.
+ if (!new_failed_network.empty()) {
+ // Hide if already shown to force show it in case user has closed it.
+ if (notification_.visible())
+ notification_.Hide();
+ notification_.Show(l10n_util::GetStringFUTF16(
+ IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
+ ASCIIToUTF16(new_failed_network)), false, true);
+ }
+
+ // Show login box if necessary.
+ if (view && initialized_)
+ CreateModalPopup(view);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/network_message_observer.h b/chrome/browser/chromeos/network_message_observer.h
index a62e636..554628f 100644
--- a/chrome/browser/chromeos/network_message_observer.h
+++ b/chrome/browser/chromeos/network_message_observer.h
@@ -4,8 +4,9 @@
#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_MESSAGE_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_NETWORK_MESSAGE_OBSERVER_H_
+#pragma once
-#include <set>
+#include <map>
#include <string>
#include "base/basictypes.h"
@@ -13,6 +14,9 @@
#include "chrome/browser/chromeos/notifications/system_notification.h"
class Profile;
+namespace views {
+class WindowDelegate;
+}
namespace chromeos {
@@ -24,10 +28,19 @@ class NetworkMessageObserver : public NetworkLibrary::Observer {
explicit NetworkMessageObserver(Profile* profile);
virtual ~NetworkMessageObserver();
+ typedef std::map<std::string, WifiNetwork> ServicePathWifiMap;
+ typedef std::map<std::string, CellularNetwork> ServicePathCellularMap;
private:
+ virtual void CreateModalPopup(views::WindowDelegate* view);
+
+ // NetworkLibrary::Observer implementation.
virtual void NetworkChanged(NetworkLibrary* obj);
- virtual void NetworkTraffic(NetworkLibrary* obj, int traffic_type) {}
+ bool initialized_;
+ // Wifi networks by service path.
+ ServicePathWifiMap wifi_networks_;
+ // Cellular networks by service path.
+ ServicePathCellularMap cellular_networks_;
SystemNotification notification_;
DISALLOW_COPY_AND_ASSIGN(NetworkMessageObserver);
diff --git a/chrome/browser/chromeos/network_state_notifier.h b/chrome/browser/chromeos/network_state_notifier.h
index a64f264..9d49d94 100644
--- a/chrome/browser/chromeos/network_state_notifier.h
+++ b/chrome/browser/chromeos/network_state_notifier.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_NETWORK_STATE_NOTIFIER_H_
#define CHROME_BROWSER_CHROMEOS_NETWORK_STATE_NOTIFIER_H_
+#pragma once
#include "chrome/browser/chromeos/cros/network_library.h"
@@ -60,7 +61,6 @@ class NetworkStateNotifier : public NetworkLibrary::Observer {
// NetworkLibrary::Observer implementation.
virtual void NetworkChanged(NetworkLibrary* cros);
- virtual void NetworkTraffic(NetworkLibrary* cros, int traffic_type) {}
private:
friend struct DefaultSingletonTraits<NetworkStateNotifier>;
diff --git a/chrome/browser/chromeos/network_state_notifier_browsertest.cc b/chrome/browser/chromeos/network_state_notifier_browsertest.cc
index 520dbcf..4833d48 100644
--- a/chrome/browser/chromeos/network_state_notifier_browsertest.cc
+++ b/chrome/browser/chromeos/network_state_notifier_browsertest.cc
@@ -7,11 +7,11 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
-#include "chrome/common/notification_service.h"
#include "chrome/common/notification_registrar.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "chrome/common/notification_service.h"
#include "chrome/test/ui_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
@@ -21,15 +21,16 @@ using ::testing::_;
class NetworkStateNotifierTest : public CrosInProcessBrowserTest,
public NotificationObserver {
public:
- NetworkStateNotifierTest() {
+ NetworkStateNotifierTest() : mock_network_library_(NULL) {
}
protected:
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
- SetStatusAreaMocksExpectations();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->SetStatusAreaMocksExpectations();
// Initialize network state notifier.
ASSERT_TRUE(CrosLibrary::Get()->EnsureLoaded());
+ mock_network_library_ = cros_mock_->mock_network_library();
ASSERT_TRUE(mock_network_library_);
EXPECT_CALL(*mock_network_library_, Connected())
.Times(1)
@@ -55,6 +56,7 @@ class NetworkStateNotifierTest : public CrosInProcessBrowserTest,
}
protected:
+ MockNetworkLibrary *mock_network_library_;
NetworkStateDetails::State state_;
};
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
index 31a6ef7..1cc3740 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.cc
@@ -61,16 +61,28 @@ void BalloonCollectionImpl::Add(const Notification& notification,
space_change_listener_->OnBalloonSpaceChanged();
}
+bool BalloonCollectionImpl::AddDOMUIMessageCallback(
+ const Notification& notification,
+ const std::string& message,
+ MessageCallback* callback) {
+ Balloons::iterator iter = FindBalloon(notification);
+ if (iter == balloons_.end()) {
+ delete callback;
+ return false;
+ }
+ BalloonViewHost* host =
+ static_cast<BalloonViewHost*>((*iter)->view()->GetHost());
+ return host->AddDOMUIMessageCallback(message, callback);
+}
+
void BalloonCollectionImpl::AddSystemNotification(
const Notification& notification,
Profile* profile,
bool sticky,
bool control) {
- // TODO(oshima): We need to modify BallonCollection/MakeBalloon pattern
- // in order to add unit tests for system notification.
Balloon* new_balloon = new Balloon(notification, profile, this);
new_balloon->set_view(
- new chromeos::BalloonViewImpl(sticky, control));
+ new chromeos::BalloonViewImpl(sticky, control, true));
balloons_.push_back(new_balloon);
new_balloon->Show();
notification_ui_->Add(new_balloon);
@@ -164,7 +176,7 @@ void BalloonCollectionImpl::Shutdown() {
Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification,
Profile* profile) {
Balloon* new_balloon = new Balloon(notification, profile, this);
- new_balloon->set_view(new chromeos::BalloonViewImpl(false, true));
+ new_balloon->set_view(new chromeos::BalloonViewImpl(false, true, false));
return new_balloon;
}
diff --git a/chrome/browser/chromeos/notifications/balloon_collection_impl.h b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
index 7ae7763..79cfe14 100644
--- a/chrome/browser/chromeos/notifications/balloon_collection_impl.h
+++ b/chrome/browser/chromeos/notifications/balloon_collection_impl.h
@@ -4,11 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
+#pragma once
-#include <deque>
+#include <string>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
+#include "chrome/browser/chromeos/notifications/balloon_view_host.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/common/notification_registrar.h"
#include "gfx/point.h"
@@ -70,6 +72,15 @@ class BalloonCollectionImpl : public BalloonCollection,
const NotificationSource& source,
const NotificationDetails& details);
+ // Adds a callback for DOMUI message. Returns true if the callback
+ // is succssfully registered, or false otherwise. It fails to add if
+ // there is no notification that matches NotificationDelegate::id(),
+ // or a callback for given message already exists. The callback
+ // object is owned and deleted by callee.
+ bool AddDOMUIMessageCallback(const Notification& notification,
+ const std::string& message,
+ MessageCallback* callback);
+
// Adds new system notification.
// |sticky| is used to indicate that the notification
// is sticky and cannot be dismissed by a user. |controls| turns on/off
diff --git a/chrome/browser/chromeos/notifications/balloon_view.cc b/chrome/browser/chromeos/notifications/balloon_view.cc
index 6ee8043..24a6004 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.cc
+++ b/chrome/browser/chromeos/notifications/balloon_view.cc
@@ -11,6 +11,7 @@
#include "app/resource_bundle.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/notifications/balloon_view_host.h"
#include "chrome/browser/chromeos/notifications/notification_panel.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
@@ -153,12 +154,12 @@ class NotificationControlView : public views::View,
void CreateOptionsMenu() {
if (options_menu_contents_.get())
return;
- const string16 source_label_text = WideToUTF16Hack(l10n_util::GetStringF(
+ const string16 source_label_text = l10n_util::GetStringFUTF16(
IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
- balloon_view_->balloon_->notification().display_source()));
- const string16 label_text = WideToUTF16Hack(l10n_util::GetStringF(
+ balloon_view_->balloon_->notification().display_source());
+ const string16 label_text = l10n_util::GetStringFUTF16(
IDS_NOTIFICATION_BALLOON_REVOKE_MESSAGE,
- balloon_view_->balloon_->notification().display_source()));
+ balloon_view_->balloon_->notification().display_source());
options_menu_contents_.reset(new menus::SimpleMenuModel(this));
// TODO(oshima): Showing the source info in the menu for now.
@@ -181,14 +182,15 @@ class NotificationControlView : public views::View,
DISALLOW_COPY_AND_ASSIGN(NotificationControlView);
};
-BalloonViewImpl::BalloonViewImpl(bool sticky, bool controls)
+BalloonViewImpl::BalloonViewImpl(bool sticky, bool controls, bool dom_ui)
: balloon_(NULL),
html_contents_(NULL),
method_factory_(this),
stale_(false),
sticky_(sticky),
controls_(controls),
- closed_(false) {
+ closed_(false),
+ dom_ui_(dom_ui) {
// This object is not to be deleted by the views hierarchy,
// as it is owned by the balloon.
set_parent_owned(false);
@@ -208,8 +210,9 @@ BalloonViewImpl::~BalloonViewImpl() {
void BalloonViewImpl::Show(Balloon* balloon) {
balloon_ = balloon;
-
html_contents_ = new BalloonViewHost(balloon);
+ if (dom_ui_)
+ html_contents_->EnableDOMUI();
AddChildView(html_contents_->view());
notification_registrar_.Add(this,
NotificationType::NOTIFY_BALLOON_DISCONNECTED, Source<Balloon>(balloon));
diff --git a/chrome/browser/chromeos/notifications/balloon_view.h b/chrome/browser/chromeos/notifications/balloon_view.h
index c6032e6..e275915 100644
--- a/chrome/browser/chromeos/notifications/balloon_view.h
+++ b/chrome/browser/chromeos/notifications/balloon_view.h
@@ -6,11 +6,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_BALLOON_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_BALLOON_VIEW_H_
+#pragma once
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/notifications/balloon.h"
+#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "gfx/path.h"
@@ -27,13 +29,13 @@ class TextButton;
class WidgetGtk;
} // namespace views
-class BalloonViewHost;
class Notification;
class NotificationDetails;
class NotificationSource;
namespace chromeos {
+class BalloonViewHost;
class NotificationControlView;
// A balloon view is the UI component for a notification panel.
@@ -41,8 +43,8 @@ class BalloonViewImpl : public BalloonView,
public views::View,
public NotificationObserver {
public:
- BalloonViewImpl(bool sticky, bool controls);
- ~BalloonViewImpl();
+ BalloonViewImpl(bool sticky, bool controls, bool dom_ui);
+ virtual ~BalloonViewImpl();
// views::View interface.
virtual void Layout();
@@ -122,6 +124,8 @@ class BalloonViewImpl : public BalloonView,
bool controls_;
// True if the notification is being closed.
bool closed_;
+ // True to enable domui in the notification.
+ bool dom_ui_;
DISALLOW_COPY_AND_ASSIGN(BalloonViewImpl);
};
diff --git a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
index cbdf0e4..6824f97 100644
--- a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.cc
@@ -4,6 +4,10 @@
#include "chrome/browser/chromeos/notifications/desktop_notifications_unittest.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/common/render_messages_params.h"
+
namespace chromeos {
// static
@@ -193,7 +197,7 @@ TEST_F(DesktopNotificationsTest, TestManyNotifications) {
// Request lots of identical notifications.
const int kLotsOfToasts = 20;
for (int id = 1; id <= kLotsOfToasts; ++id) {
- SCOPED_TRACE(StringPrintf("Creation loop: id=%d", id));
+ SCOPED_TRACE(base::StringPrintf("Creation loop: id=%d", id));
ViewHostMsg_ShowNotification_Params params = StandardTestNotification();
params.notification_id = id;
EXPECT_TRUE(service_->ShowDesktopNotification(
@@ -217,7 +221,7 @@ TEST_F(DesktopNotificationsTest, TestManyNotifications) {
for (id = 1;
id <= cancelled;
++id) {
- SCOPED_TRACE(StringPrintf("Cancel half of notifications: id=%d", id));
+ SCOPED_TRACE(base::StringPrintf("Cancel half of notifications: id=%d", id));
service_->CancelDesktopNotification(process_id, route_id, id);
MessageLoopForUI::current()->RunAllPending();
expected_log.append("notification closed by script\n");
@@ -228,7 +232,7 @@ TEST_F(DesktopNotificationsTest, TestManyNotifications) {
// Now cancel the rest. It should empty the balloon space.
for (; id <= kLotsOfToasts; ++id) {
- SCOPED_TRACE(StringPrintf("Cancel loop: id=%d", id));
+ SCOPED_TRACE(base::StringPrintf("Cancel loop: id=%d", id));
service_->CancelDesktopNotification(process_id, route_id, id);
expected_log.append("notification closed by script\n");
MessageLoopForUI::current()->RunAllPending();
@@ -243,7 +247,7 @@ TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
// Create some toasts and then prematurely delete the notification service,
// just to make sure nothing crashes/leaks.
for (int id = 0; id <= 3; ++id) {
- SCOPED_TRACE(StringPrintf("Show Text loop: id=%d", id));
+ SCOPED_TRACE(base::StringPrintf("Show Text loop: id=%d", id));
EXPECT_TRUE(service_->ShowDesktopNotification(
StandardTestNotification(), 0, 0,
diff --git a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.h b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.h
index b424c67..fedd4f0 100644
--- a/chrome/browser/chromeos/notifications/desktop_notifications_unittest.h
+++ b/chrome/browser/chromeos/notifications/desktop_notifications_unittest.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_DESKTOP_NOTIFICATIONS_UNITTEST_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_DESKTOP_NOTIFICATIONS_UNITTEST_H_
+#pragma once
#include <set>
#include <string>
diff --git a/chrome/browser/chromeos/notifications/notification_browsertest.cc b/chrome/browser/chromeos/notifications/notification_browsertest.cc
index a1e1152..2d76a3d 100644
--- a/chrome/browser/chromeos/notifications/notification_browsertest.cc
+++ b/chrome/browser/chromeos/notifications/notification_browsertest.cc
@@ -5,6 +5,11 @@
#include "app/x11_util.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
@@ -26,6 +31,7 @@ class MockNotificationDelegate : public NotificationDelegate {
virtual void Display() {}
virtual void Error() {}
virtual void Close(bool by_user) {}
+ virtual void Click() {}
virtual std::string id() const { return id_; }
private:
@@ -50,6 +56,10 @@ class NotificationTest : public InProcessBrowserTest,
expected_(PanelController::INITIAL) {
}
+ void HandleDOMUIMessage(const ListValue* value) {
+ MessageLoop::current()->Quit();
+ }
+
protected:
virtual void SetUp() {
// Detect if we're running under ChromeOS WindowManager. See
@@ -249,7 +259,7 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestSystemNotification) {
// Dismiss the notification.
// TODO(oshima): Consider updating API to Remove(NotificationDelegate)
// or Remove(std::string id);
- collection->Remove(Notification(GURL(), GURL(), std::wstring(), string16(),
+ collection->Remove(Notification(GURL(), GURL(), string16(), string16(),
delegate.get()));
ui_test_utils::RunAllPendingInMessageLoop();
@@ -414,7 +424,8 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestCloseOpen) {
EXPECT_EQ(NotificationPanel::CLOSED, tester->state());
}
-IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
+// TODO(oshima): bug chromium-os:7139 Fix this flaky test on ChromeOS.
+IN_PROC_BROWSER_TEST_F(NotificationTest, FLAKY_TestScrollBalloonToVisible) {
BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
NotificationPanel* panel = GetNotificationPanel();
NotificationPanelTester* tester = panel->GetTester();
@@ -426,8 +437,8 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
// new notification is always visible
for (int i = 0; i < create_count; i++) {
{
- SCOPED_TRACE(StringPrintf("new n%d", i));
- std::string id = StringPrintf("n%d", i);
+ SCOPED_TRACE(base::StringPrintf("new n%d", i));
+ std::string id = base::StringPrintf("n%d", i);
collection->Add(NewMockNotification(id), profile);
EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state());
BalloonViewImpl* view =
@@ -436,8 +447,8 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
EXPECT_TRUE(tester->IsVisible(view));
}
{
- SCOPED_TRACE(StringPrintf("new s%d", i));
- std::string id = StringPrintf("s%d", i);
+ SCOPED_TRACE(base::StringPrintf("new s%d", i));
+ std::string id = base::StringPrintf("s%d", i);
collection->AddSystemNotification(
NewMockNotification(id), browser()->profile(), true, false);
ui_test_utils::RunAllPendingInMessageLoop();
@@ -450,8 +461,8 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
// Update should not change the visibility
for (int i = 0; i < create_count; i++) {
{
- SCOPED_TRACE(StringPrintf("update n%d", i));
- Notification notify = NewMockNotification(StringPrintf("n%d", i));
+ SCOPED_TRACE(base::StringPrintf("update n%d", i));
+ Notification notify = NewMockNotification(base::StringPrintf("n%d", i));
// The last shown notification is sticky, which makes all non sticky
// invisible.
EXPECT_TRUE(collection->UpdateNotification(notify));
@@ -460,8 +471,8 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
EXPECT_FALSE(tester->IsVisible(view));
}
{
- SCOPED_TRACE(StringPrintf("update s%d", i));
- Notification notify = NewMockNotification(StringPrintf("s%d", i));
+ SCOPED_TRACE(base::StringPrintf("update s%d", i));
+ Notification notify = NewMockNotification(base::StringPrintf("s%d", i));
BalloonViewImpl* view = tester->GetBalloonView(collection, notify);
bool currently_visible = tester->IsVisible(view);
EXPECT_TRUE(collection->UpdateNotification(notify));
@@ -473,16 +484,16 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) {
// UpdateAndShowNotification makes notification visible
for (int i = 0; i < create_count; i++) {
{
- SCOPED_TRACE(StringPrintf("update and show n%d", i));
- Notification notify = NewMockNotification(StringPrintf("n%d", i));
+ SCOPED_TRACE(base::StringPrintf("update and show n%d", i));
+ Notification notify = NewMockNotification(base::StringPrintf("n%d", i));
EXPECT_TRUE(collection->UpdateAndShowNotification(notify));
ui_test_utils::RunAllPendingInMessageLoop();
BalloonViewImpl* view = tester->GetBalloonView(collection, notify);
EXPECT_TRUE(tester->IsVisible(view));
}
{
- SCOPED_TRACE(StringPrintf("update and show s%d", i));
- Notification notify = NewMockNotification(StringPrintf("s%d", i));
+ SCOPED_TRACE(base::StringPrintf("update and show s%d", i));
+ Notification notify = NewMockNotification(base::StringPrintf("s%d", i));
EXPECT_TRUE(collection->UpdateAndShowNotification(notify));
ui_test_utils::RunAllPendingInMessageLoop();
BalloonViewImpl* view = tester->GetBalloonView(collection, notify);
@@ -546,4 +557,58 @@ IN_PROC_BROWSER_TEST_F(NotificationTest, TestCloseDismissAllNonSticky) {
EXPECT_EQ(1, tester->GetStickyNotificationCount());
}
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestAddDOMUIMessageCallback) {
+ BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
+ Profile* profile = browser()->profile();
+
+ collection->AddSystemNotification(
+ NewMockNotification("1"), profile, false, false);
+
+ EXPECT_TRUE(collection->AddDOMUIMessageCallback(
+ NewMockNotification("1"),
+ "test",
+ NewCallback(
+ static_cast<NotificationTest*>(this),
+ &NotificationTest::HandleDOMUIMessage)));
+
+ // Adding callback for the same message twice should fail.
+ EXPECT_FALSE(collection->AddDOMUIMessageCallback(
+ NewMockNotification("1"),
+ "test",
+ NewCallback(
+ static_cast<NotificationTest*>(this),
+ &NotificationTest::HandleDOMUIMessage)));
+
+ // Adding callback to nonexistent notification should fail.
+ EXPECT_FALSE(collection->AddDOMUIMessageCallback(
+ NewMockNotification("2"),
+ "test1",
+ NewCallback(
+ static_cast<NotificationTest*>(this),
+ &NotificationTest::HandleDOMUIMessage)));
+}
+
+IN_PROC_BROWSER_TEST_F(NotificationTest, TestDOMUIMessageCallback) {
+ BalloonCollectionImpl* collection = GetBalloonCollectionImpl();
+ Profile* profile = browser()->profile();
+ // a notification that sends 'test' domui message back to chrome.
+ const GURL content_url(
+ "data:text/html;charset=utf-8,"
+ "<html><script>function send() { chrome.send('test', ['']); }</script>"
+ "<body onload='send()'></body></html>");
+ collection->AddSystemNotification(
+ Notification(GURL(), content_url, string16(), string16(),
+ new MockNotificationDelegate("1")),
+ profile,
+ false,
+ false);
+ EXPECT_TRUE(collection->AddDOMUIMessageCallback(
+ NewMockNotification("1"),
+ "test",
+ NewCallback(
+ static_cast<NotificationTest*>(this),
+ &NotificationTest::HandleDOMUIMessage)));
+ MessageLoop::current()->Run();
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/notification_panel.cc b/chrome/browser/chromeos/notifications/notification_panel.cc
index 0f53f9f..2b48256 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.cc
+++ b/chrome/browser/chromeos/notifications/notification_panel.cc
@@ -10,9 +10,9 @@
#include "app/resource_bundle.h"
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
#include "chrome/browser/chromeos/notifications/balloon_view.h"
+#include "cros/chromeos_wm_ipc_enums.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
-#include "third_party/cros/chromeos_wm_ipc_enums.h"
#include "views/background.h"
#include "views/controls/native/native_view_host.h"
#include "views/controls/scroll_view.h"
diff --git a/chrome/browser/chromeos/notifications/notification_panel.h b/chrome/browser/chromeos/notifications/notification_panel.h
index 7b795e4..96739bc 100644
--- a/chrome/browser/chromeos/notifications/notification_panel.h
+++ b/chrome/browser/chromeos/notifications/notification_panel.h
@@ -6,9 +6,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_
+#pragma once
-#include "base/task.h"
#include "base/scoped_ptr.h"
+#include "base/task.h"
#include "chrome/browser/chromeos/frame/panel_controller.h"
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
#include "chrome/common/notification_registrar.h"
diff --git a/chrome/browser/chromeos/notifications/system_notification.cc b/chrome/browser/chromeos/notifications/system_notification.cc
index f2d9d4a..ad54253 100644
--- a/chrome/browser/chromeos/notifications/system_notification.cc
+++ b/chrome/browser/chromeos/notifications/system_notification.cc
@@ -4,11 +4,10 @@
#include "chrome/browser/chromeos/notifications/system_notification.h"
-#include "app/resource_bundle.h"
-#include "base/base64.h"
#include "base/move.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/notifications/system_notification_factory.h"
+#include "chrome/browser/dom_ui/dom_ui_util.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
@@ -23,15 +22,9 @@ SystemNotification::SystemNotification(Profile* profile, std::string id,
title_(move(title)),
visible_(false),
urgent_(false) {
- // Load resource icon and covert to base64 encoded data url
- scoped_refptr<RefCountedMemory> raw_icon(ResourceBundle::GetSharedInstance().
- LoadDataResourceBytes(icon_resource_id));
- std::string str_gurl;
- std::copy(raw_icon->front(), raw_icon->front() + raw_icon->size(),
- std::back_inserter(str_gurl));
- base::Base64Encode(str_gurl, &str_gurl);
- str_gurl.insert(0, "data:image/png;base64,");
- GURL tmp_gurl(str_gurl);
+ std::string url = dom_ui_util::GetImageDataUrlFromResource(icon_resource_id);
+ DCHECK(!url.empty());
+ GURL tmp_gurl(url);
icon_.Swap(&tmp_gurl);
}
@@ -39,7 +32,9 @@ SystemNotification::~SystemNotification() {
Hide();
}
-void SystemNotification::Show(const string16& message, bool urgent) {
+void SystemNotification::Show(const string16& message,
+ bool urgent,
+ bool sticky) {
Notification notify = SystemNotificationFactory::Create(icon_,
title_, message, delegate_.get());
if (visible_) {
@@ -50,7 +45,8 @@ void SystemNotification::Show(const string16& message, bool urgent) {
collection_->UpdateNotification(notify);
}
} else {
- collection_->AddSystemNotification(notify, profile_, true /* sticky */,
+ collection_->AddSystemNotification(notify, profile_,
+ sticky,
false /* no controls */);
}
visible_ = true;
@@ -59,7 +55,7 @@ void SystemNotification::Show(const string16& message, bool urgent) {
void SystemNotification::Hide() {
if (visible_) {
- collection_->Remove(Notification(GURL(), GURL(), std::wstring(), string16(),
+ collection_->Remove(Notification(GURL(), GURL(), string16(), string16(),
delegate_.get()));
visible_ = false;
diff --git a/chrome/browser/chromeos/notifications/system_notification.h b/chrome/browser/chromeos/notifications/system_notification.h
index ff1efef..a5ac224 100644
--- a/chrome/browser/chromeos/notifications/system_notification.h
+++ b/chrome/browser/chromeos/notifications/system_notification.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
+#pragma once
#include <string>
@@ -29,12 +30,12 @@ class SystemNotification {
SystemNotification(Profile* profile, std::string id, int icon_resource_id,
string16 title);
- ~SystemNotification();
+ virtual ~SystemNotification();
// Show will show or update the message for this notification
// on a transition to urgent, the notification will be shown if it was
// previously hidden or minimized by the user.
- void Show(const string16& message, bool urgent);
+ void Show(const string16& message, bool urgent, bool sticky);
// Hide will dismiss the notification, if the notification is already
// hidden it does nothing
@@ -53,6 +54,7 @@ class SystemNotification {
void Display() {}
void Error() {}
void Close(bool by_user) {}
+ void Click() {}
std::string id() const { return id_; }
private:
@@ -75,4 +77,3 @@ class SystemNotification {
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_H_
-
diff --git a/chrome/browser/chromeos/notifications/system_notification_factory.cc b/chrome/browser/chromeos/notifications/system_notification_factory.cc
index ac01322..51b308f 100644
--- a/chrome/browser/chromeos/notifications/system_notification_factory.cc
+++ b/chrome/browser/chromeos/notifications/system_notification_factory.cc
@@ -15,7 +15,8 @@ Notification SystemNotificationFactory::Create(
NotificationDelegate* delegate) {
string16 content_url = DesktopNotificationService::CreateDataUrl(
icon, title, text, WebKit::WebTextDirectionDefault);
- return Notification(GURL(), GURL(content_url), std::wstring(), string16(),
+ return Notification(GURL(), GURL(content_url), string16(), string16(),
delegate);
}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/notifications/system_notification_factory.h b/chrome/browser/chromeos/notifications/system_notification_factory.h
index 6acd53a..c81b07d 100644
--- a/chrome/browser/chromeos/notifications/system_notification_factory.h
+++ b/chrome/browser/chromeos/notifications/system_notification_factory.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_SYSTEM_NOTIFICATION_FACTORY_H_
+#pragma once
#include "base/basictypes.h"
#include "chrome/browser/notifications/notification.h"
diff --git a/chrome/browser/chromeos/offline/offline_load_page.cc b/chrome/browser/chromeos/offline/offline_load_page.cc
index 0dc9826..ece8fb6 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.cc
+++ b/chrome/browser/chromeos/offline/offline_load_page.cc
@@ -9,6 +9,8 @@
#include "base/histogram.h"
#include "base/i18n/rtl.h"
#include "base/string_piece.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chrome_thread.h"
@@ -27,8 +29,8 @@ namespace {
const int kMaxBlankPeriod = 3000;
// A utility function to set the dictionary's value given by |resource_id|.
-void SetString(DictionaryValue* strings, const wchar_t* name, int resource_id) {
- strings->SetString(name, l10n_util::GetString(resource_id));
+void SetString(DictionaryValue* strings, const char* name, int resource_id) {
+ strings->SetString(name, l10n_util::GetStringUTF16(resource_id));
}
} // namespace
@@ -61,27 +63,28 @@ OfflineLoadPage::OfflineLoadPage(TabContents* tab_contents,
std::string OfflineLoadPage::GetHTMLContents() {
DictionaryValue strings;
- SetString(&strings, L"headLine", IDS_OFFLINE_LOAD_HEADLINE);
- SetString(&strings, L"description", IDS_OFFLINE_LOAD_DESCRIPTION);
- SetString(&strings, L"load_button", IDS_OFFLINE_LOAD_BUTTON);
- SetString(&strings, L"back_button", IDS_OFFLINE_BACK_BUTTON);
+ SetString(&strings, "headLine", IDS_OFFLINE_LOAD_HEADLINE);
+ SetString(&strings, "description", IDS_OFFLINE_LOAD_DESCRIPTION);
+ SetString(&strings, "load_button", IDS_OFFLINE_LOAD_BUTTON);
+ SetString(&strings, "back_button", IDS_OFFLINE_BACK_BUTTON);
// TODO(oshima): tab()->GetTitle() always return url. This has to be
// a cached title.
- strings.SetString(L"title", UTF16ToWide(tab()->GetTitle()));
- strings.SetString(L"textdirection", base::i18n::IsRTL() ? L"rtl" : L"ltr");
- strings.SetString(L"display_go_back",
- tab()->controller().CanGoBack() ? L"inline" : L"none");
+ strings.SetString("title", tab()->GetTitle());
+ strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
+ strings.SetString("display_go_back",
+ tab()->controller().CanGoBack() ? "inline" : "none");
int64 time_to_wait = std::max(
static_cast<int64>(0),
kMaxBlankPeriod -
NetworkStateNotifier::GetOfflineDuration().InMilliseconds());
- strings.SetString(L"on_load",
- StringPrintf(L"startTimer(%ld)", time_to_wait));
+ strings.SetString("on_load",
+ WideToUTF16Hack(base::StringPrintf(L"startTimer(%ld)",
+ time_to_wait)));
// TODO(oshima): thumbnail is not working yet. fix this.
const std::string url = "chrome://thumb/" + GetURL().spec();
- strings.SetString(L"thumbnailUrl", "url(" + url + ")");
+ strings.SetString("thumbnailUrl", "url(" + url + ")");
base::StringPiece html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
diff --git a/chrome/browser/chromeos/offline/offline_load_page.h b/chrome/browser/chromeos/offline/offline_load_page.h
index 3363853..b6eb046 100644
--- a/chrome/browser/chromeos/offline/offline_load_page.h
+++ b/chrome/browser/chromeos/offline/offline_load_page.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_OFFLINE_OFFLINE_LOAD_PAGE_H_
#define CHROME_BROWSER_CHROMEOS_OFFLINE_OFFLINE_LOAD_PAGE_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/offline/offline_load_page_unittest.cc b/chrome/browser/chromeos/offline/offline_load_page_unittest.cc
index a619243..9f5fcfb 100644
--- a/chrome/browser/chromeos/offline/offline_load_page_unittest.cc
+++ b/chrome/browser/chromeos/offline/offline_load_page_unittest.cc
@@ -7,7 +7,9 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/offline/offline_load_page.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/test_tab_contents.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/render_messages_params.h"
static const char* kURL1 = "http://www.google.com/";
static const char* kURL2 = "http://www.gmail.com/";
diff --git a/chrome/browser/chromeos/offline/offline_load_service.cc b/chrome/browser/chromeos/offline/offline_load_service.cc
index 63602f5..a000357 100644
--- a/chrome/browser/chromeos/offline/offline_load_service.cc
+++ b/chrome/browser/chromeos/offline/offline_load_service.cc
@@ -4,13 +4,13 @@
#include "chrome/browser/chromeos/offline/offline_load_service.h"
-#include "base/singleton.h"
#include "base/ref_counted.h"
-#include "chrome/common/notification_service.h"
+#include "base/singleton.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/common/notification_service.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/offline/offline_load_service.h b/chrome/browser/chromeos/offline/offline_load_service.h
index 119475e..d052d51 100644
--- a/chrome/browser/chromeos/offline/offline_load_service.h
+++ b/chrome/browser/chromeos/offline/offline_load_service.h
@@ -4,13 +4,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_OFFLINE_OFFLINE_LOAD_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_OFFLINE_OFFLINE_LOAD_SERVICE_H_
+#pragma once
#include <tr1/unordered_set>
#include "base/ref_counted.h"
#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_type.h"
#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_type.h"
class GURL;
class NavigationController;
diff --git a/chrome/browser/chromeos/options/cellular_config_view.cc b/chrome/browser/chromeos/options/cellular_config_view.cc
index be1e761..725efe8 100644
--- a/chrome/browser/chromeos/options/cellular_config_view.cc
+++ b/chrome/browser/chromeos/options/cellular_config_view.cc
@@ -5,23 +5,83 @@
#include "chrome/browser/chromeos/options/cellular_config_view.h"
#include "app/l10n_util.h"
+#include "base/i18n/time_formatting.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chrome/common/time_format.h"
#include "grit/generated_resources.h"
+#include "views/controls/button/checkbox.h"
+#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
+namespace {
+
+enum PlanPurchaseType {
+ UNKNOWN,
+ NO_PURCHASE, // No purchase happened.
+ PURCHASED_DATA, // Purchased limited data plan.
+ PURCHASED_UNLIMITED_DATA // Purchased unlimited data plan.
+};
+
+struct PlanDetails {
+ PlanPurchaseType last_purchase_type;
+ base::Time last_purchase_time;
+
+ int64 purchased_data;
+ base::TimeDelta purchased_time;
+
+ int64 remaining_data;
+ base::TimeDelta remaining_time;
+};
+
+// TODO(xiyuan): Get real data from libcros when it's ready.
+// Get plan details at the time being called.
+void GetPlanDetails(const chromeos::CellularNetwork& cellular,
+ PlanDetails* details) {
+ // Free 5M 30day plan.
+ details->last_purchase_type = UNKNOWN;
+ details->last_purchase_time = base::Time::Now();
+ details->purchased_data = 5 * 1024 * 1024;
+ details->purchased_time = base::TimeDelta::FromDays(30);
+ details->remaining_data = 2 * 1024 * 1024;
+ details->remaining_time = base::TimeDelta::FromDays(29);
+}
+
+} // namespace
+
namespace chromeos {
CellularConfigView::CellularConfigView(NetworkConfigView* parent,
const CellularNetwork& cellular)
: parent_(parent),
cellular_(cellular),
- autoconnect_checkbox_(NULL) {
+ purchase_info_(NULL),
+ purchase_more_button_(NULL),
+ remaining_data_info_(NULL),
+ expiration_info_(NULL),
+ show_notification_checkbox_(NULL),
+ autoconnect_checkbox_(NULL),
+ customer_support_link_(NULL) {
Init();
}
+void CellularConfigView::ButtonPressed(views::Button* button,
+ const views::Event& event) {
+ if (button == purchase_more_button_) {
+ // TODO(xiyuan): Purchase more...
+ }
+}
+
+void CellularConfigView::LinkActivated(views::Link* source, int event_flags) {
+ if (source == customer_support_link_) {
+ // TODO(xiyuan): Find out where to go.
+ }
+}
+
bool CellularConfigView::Save() {
// Save auto-connect here.
bool auto_connect = autoconnect_checkbox_->checked();
@@ -36,28 +96,128 @@ void CellularConfigView::Init() {
views::GridLayout* layout = CreatePanelGridLayout(this);
SetLayoutManager(layout);
- int column_view_set_id = 0;
- views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
+ purchase_info_ = new views::Label();
+ purchase_more_button_ = new views::NativeButton(this, l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_MORE));
+ views::Label* data_remaining_label = new views::Label(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_DATA_REMAINING));
+ remaining_data_info_ = new views::Label();
+ views::Label* expires_label = new views::Label(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EXPIRES));
+ expiration_info_ = new views::Label();
+ show_notification_checkbox_ = new views::Checkbox(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHOW_MOBILE_NOTIFICATION));
+ autoconnect_checkbox_ = new views::Checkbox(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
+ customer_support_link_ = new views::Link(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CUSTOMER_SUPPORT));
+
+ data_remaining_label->SetFont(data_remaining_label->font().DeriveFont(0,
+ gfx::Font::BOLD));
+ expires_label->SetFont(data_remaining_label->font());
+
+ const int kColumnSetId = 0;
+ views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
+ column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
+ views::GridLayout::USE_PREF, 0, 0);
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0, 0);
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+ column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0, 0);
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetString(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
- views::Label* label = new views::Label(ASCIIToWide(cellular_.name()));
- label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- layout->AddView(label);
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(purchase_info_, 2, 1);
+ layout->AddView(purchase_more_button_);
layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
- // Autoconnect checkbox
- autoconnect_checkbox_ = new views::Checkbox(
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
- autoconnect_checkbox_->SetChecked(cellular_.auto_connect());
- layout->StartRow(0, column_view_set_id);
- layout->AddView(autoconnect_checkbox_, 2, 1);
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(data_remaining_label);
+ layout->AddView(remaining_data_info_, 2, 1);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(expires_label);
+ layout->AddView(expiration_info_, 2, 1);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(show_notification_checkbox_, 3, 1);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(autoconnect_checkbox_, 3, 1);
+ layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+
+ layout->StartRow(0, kColumnSetId);
+ layout->AddView(customer_support_link_, 3, 1,
+ views::GridLayout::LEADING, views::GridLayout::TRAILING);
layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ Update();
+}
+
+void CellularConfigView::Update() {
+ autoconnect_checkbox_->SetChecked(cellular_.auto_connect());
+
+ PlanDetails details;
+ GetPlanDetails(cellular_, &details);
+
+ switch (details.last_purchase_type) {
+ case NO_PURCHASE:
+ purchase_info_->SetText(l10n_util::GetStringF(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_RECEIVED_FREE_DATA,
+ UTF16ToWide(FormatBytes(details.purchased_data,
+ GetByteDisplayUnits(details.purchased_data),
+ true)),
+ base::TimeFormatFriendlyDate(details.last_purchase_time)));
+ remaining_data_info_->SetText(
+ UTF16ToWide(FormatBytes(details.remaining_data,
+ GetByteDisplayUnits(details.remaining_data),
+ true)));
+ expiration_info_->SetText(UTF16ToWide(
+ TimeFormat::TimeRemaining(details.remaining_time)));
+ break;
+ case PURCHASED_DATA:
+ purchase_info_->SetText(l10n_util::GetStringF(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_DATA,
+ UTF16ToWide(FormatBytes(details.purchased_data,
+ GetByteDisplayUnits(details.purchased_data),
+ true)),
+ base::TimeFormatFriendlyDate(details.last_purchase_time)));
+ remaining_data_info_->SetText(
+ UTF16ToWide(FormatBytes(details.remaining_data,
+ GetByteDisplayUnits(details.remaining_data),
+ true)));
+ expiration_info_->SetText(UTF16ToWide(
+ TimeFormat::TimeRemaining(details.remaining_time)));
+ break;
+ case PURCHASED_UNLIMITED_DATA:
+ purchase_info_->SetText(l10n_util::GetStringF(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_UNLIMITED_DATA,
+ UTF16ToWide(FormatBytes(details.purchased_data,
+ GetByteDisplayUnits(details.purchased_data),
+ true)),
+ base::TimeFormatFriendlyDate(details.last_purchase_time)));
+ remaining_data_info_->SetText(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_UNLIMITED));
+ expiration_info_->SetText(UTF16ToWide(
+ TimeFormat::TimeRemaining(details.remaining_time)));
+ break;
+ case UNKNOWN: {
+ // TODO(xiyuan): Remove this when underlying data is provided.
+ const wchar_t kPlanType[] = L"Purchased plan: <Not yet implemented>";
+ const wchar_t kNotImplemented[] = L"<Not yet implemented>";
+ purchase_info_->SetText(kPlanType);
+ remaining_data_info_->SetText(kNotImplemented);
+ expiration_info_->SetText(kNotImplemented);
+ break;
+ }
+ default:
+ NOTREACHED() << "Unknown mobile plan purchase type.";
+ break;
+ }
+
+ Layout();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/options/cellular_config_view.h b/chrome/browser/chromeos/options/cellular_config_view.h
index f2ad38e..9120c6d 100644
--- a/chrome/browser/chromeos/options/cellular_config_view.h
+++ b/chrome/browser/chromeos/options/cellular_config_view.h
@@ -1,28 +1,42 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_CELLULAR_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_CELLULAR_CONFIG_VIEW_H_
-
-#include <string>
+#pragma once
#include "chrome/browser/chromeos/cros/network_library.h"
-#include "views/controls/button/checkbox.h"
+#include "views/controls/button/button.h"
+#include "views/controls/link.h"
#include "views/view.h"
+namespace views {
+class Checkbox;
+class Label;
+class NativeButton;
+} // namespace views
+
namespace chromeos {
class NetworkConfigView;
// A dialog box for showing a password textfield.
-class CellularConfigView : public views::View {
+class CellularConfigView : public views::View,
+ public views::ButtonListener,
+ public views::LinkController {
public:
CellularConfigView(NetworkConfigView* parent,
const CellularNetwork& cellular);
explicit CellularConfigView(NetworkConfigView* parent);
virtual ~CellularConfigView() {}
+ // views::ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* button, const views::Event& event);
+
+ // views::LinkController implementation.
+ virtual void LinkActivated(views::Link* source, int event_flags);
+
// Save network information.
virtual bool Save();
@@ -31,11 +45,20 @@ class CellularConfigView : public views::View {
// Initializes UI.
void Init();
+ // Updates UI.
+ void Update();
+
NetworkConfigView* parent_;
CellularNetwork cellular_;
+ views::Label* purchase_info_;
+ views::NativeButton* purchase_more_button_;
+ views::Label* remaining_data_info_;
+ views::Label* expiration_info_;
+ views::Checkbox* show_notification_checkbox_;
views::Checkbox* autoconnect_checkbox_;
+ views::Link* customer_support_link_;
DISALLOW_COPY_AND_ASSIGN(CellularConfigView);
};
diff --git a/chrome/browser/chromeos/options/internet_page_view.cc b/chrome/browser/chromeos/options/internet_page_view.cc
index 71f3e55..a095f3b 100644
--- a/chrome/browser/chromeos/options/internet_page_view.cc
+++ b/chrome/browser/chromeos/options/internet_page_view.cc
@@ -6,11 +6,14 @@
#include <string>
-#include "app/combobox_model.h"
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "chrome/browser/chromeos/status/network_menu_button.h"
+#include "chrome/browser/chromeos/status/network_menu.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/native_button.h"
@@ -246,7 +249,7 @@ void WiredSection::InitSection() {
SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK);
if (!cros->ethernet_connecting() && !cros->ethernet_connected()) {
- icon = NetworkMenuButton::IconForDisplay(icon,
+ icon = NetworkMenu::IconForDisplay(icon,
*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED));
}
@@ -317,10 +320,10 @@ void WirelessSection::InitSection() {
for (size_t i = 0; i < wifi_networks_.size(); ++i) {
std::wstring name = ASCIIToWide(wifi_networks_[i].name());
- SkBitmap icon = NetworkMenuButton::IconForNetworkStrength(
+ SkBitmap icon = NetworkMenu::IconForNetworkStrength(
wifi_networks_[i].strength(), true);
if (wifi_networks_[i].encrypted()) {
- icon = NetworkMenuButton::IconForDisplay(icon,
+ icon = NetworkMenu::IconForDisplay(icon,
*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
}
@@ -335,12 +338,12 @@ void WirelessSection::InitSection() {
for (size_t i = 0; i < celluar_networks_.size(); ++i) {
std::wstring name = ASCIIToWide(celluar_networks_[i].name());
- SkBitmap icon = NetworkMenuButton::IconForNetworkStrength(
+ SkBitmap icon = NetworkMenu::IconForNetworkStrength(
celluar_networks_[i].strength(), true);
// TODO(chocobo): Check cellular network 3g/edge.
SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G);
// SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_EDGE);
- icon = NetworkMenuButton::IconForDisplay(icon, badge);
+ icon = NetworkMenu::IconForDisplay(icon, badge);
bool connecting = celluar_networks_[i].connecting();
bool connected = celluar_networks_[i].connected();
@@ -446,7 +449,7 @@ void RememberedSection::InitSection() {
SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0);
if (wifi_networks_[i].encrypted()) {
- icon = NetworkMenuButton::IconForDisplay(icon,
+ icon = NetworkMenu::IconForDisplay(icon,
*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
}
@@ -463,7 +466,7 @@ void RememberedSection::InitSection() {
// TODO(chocobo): Check cellular network 3g/edge.
SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G);
// SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_EDGE);
- icon = NetworkMenuButton::IconForDisplay(icon, badge);
+ icon = NetworkMenu::IconForDisplay(icon, badge);
AddNetwork(i, icon, name, false, std::wstring(), FORGET_BUTTON,
TYPE_CELLULAR);
@@ -474,12 +477,12 @@ void RememberedSection::ButtonClicked(int button, int connection_type, int id) {
if (connection_type == TYPE_CELLULAR) {
if (static_cast<int>(celluar_networks_.size()) > id) {
CrosLibrary::Get()->GetNetworkLibrary()->ForgetWirelessNetwork(
- celluar_networks_[id]);
+ celluar_networks_[id].service_path());
}
} else if (connection_type == TYPE_WIFI) {
if (static_cast<int>(wifi_networks_.size()) > id) {
CrosLibrary::Get()->GetNetworkLibrary()->ForgetWirelessNetwork(
- wifi_networks_[id]);
+ wifi_networks_[id].service_path());
}
} else {
NOTREACHED();
@@ -522,7 +525,7 @@ class InternetPageContentView : public SettingsPageView {
InternetPageContentView::InternetPageContentView(Profile* profile)
: SettingsPageView(profile) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- line_height_ = rb.GetFont(ResourceBundle::BaseFont).height();
+ line_height_ = rb.GetFont(ResourceBundle::BaseFont).GetHeight();
}
void InternetPageContentView::RefreshContents() {
diff --git a/chrome/browser/chromeos/options/internet_page_view.h b/chrome/browser/chromeos/options/internet_page_view.h
index 2b6f9ed..71b7399 100644
--- a/chrome/browser/chromeos/options/internet_page_view.h
+++ b/chrome/browser/chromeos/options/internet_page_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_INTERNET_PAGE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_INTERNET_PAGE_VIEW_H_
+#pragma once
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/options/settings_page_view.h"
@@ -25,7 +26,6 @@ class InternetPageView : public SettingsPageView,
// NetworkLibrary::Observer implementation.
virtual void NetworkChanged(NetworkLibrary* obj);
- virtual void NetworkTraffic(NetworkLibrary* obj, int traffic_type) {}
// views::View overrides:
virtual void Layout();
diff --git a/chrome/browser/chromeos/options/ip_config_view.cc b/chrome/browser/chromeos/options/ip_config_view.cc
index 9fb1520..8e596a2 100644
--- a/chrome/browser/chromeos/options/ip_config_view.cc
+++ b/chrome/browser/chromeos/options/ip_config_view.cc
@@ -6,6 +6,7 @@
#include "app/l10n_util.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
diff --git a/chrome/browser/chromeos/options/ip_config_view.h b/chrome/browser/chromeos/options/ip_config_view.h
index f144666..c09fcc3 100644
--- a/chrome/browser/chromeos/options/ip_config_view.h
+++ b/chrome/browser/chromeos/options/ip_config_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_IP_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_IP_CONFIG_VIEW_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/options/language_chewing_config_view.cc b/chrome/browser/chromeos/options/language_chewing_config_view.cc
index 376be8f..40a597e 100644
--- a/chrome/browser/chromeos/options/language_chewing_config_view.cc
+++ b/chrome/browser/chromeos/options/language_chewing_config_view.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/chromeos/options/language_chewing_config_view.h"
-#include "app/combobox_model.h"
#include "app/l10n_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
@@ -26,29 +25,34 @@ namespace chromeos {
LanguageChewingConfigView::LanguageChewingConfigView(Profile* profile)
: OptionsPageView(profile), contents_(NULL) {
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
chewing_boolean_prefs_[i].Init(
- kChewingBooleanPrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kChewingBooleanPrefs[i].pref_name,
+ profile->GetPrefs(), this);
chewing_boolean_checkboxes_[i] = NULL;
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
current.multiple_choice_pref.Init(
- kChewingMultipleChoicePrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kChewingMultipleChoicePrefs[i].pref_name,
+ profile->GetPrefs(), this);
current.combobox_model =
- new LanguageComboboxModel<const char*>(&kChewingMultipleChoicePrefs[i]);
+ new LanguageComboboxModel<const char*>(
+ &language_prefs::kChewingMultipleChoicePrefs[i]);
current.combobox = NULL;
}
hsu_sel_key_type_.multiple_choice_pref.Init(
- kChewingHsuSelKeyType.pref_name, profile->GetPrefs(), this);
+ language_prefs::kChewingHsuSelKeyType.pref_name, profile->GetPrefs(),
+ this);
hsu_sel_key_type_.combobox_model =
- new LanguageComboboxModel<int>(&kChewingHsuSelKeyType);
+ new LanguageComboboxModel<int>(&language_prefs::kChewingHsuSelKeyType);
hsu_sel_key_type_.combobox = NULL;
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
chewing_integer_prefs_[i].Init(
- kChewingIntegerPrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kChewingIntegerPrefs[i].pref_name,
+ profile->GetPrefs(), this);
chewing_integer_sliders_[i] = NULL;
}
}
@@ -60,13 +64,14 @@ void LanguageChewingConfigView::ButtonPressed(
views::Button* sender, const views::Event& event) {
views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
const int pref_id = checkbox->tag();
- DCHECK(pref_id >= 0 && pref_id < static_cast<int>(kNumChewingBooleanPrefs));
+ DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
+ language_prefs::kNumChewingBooleanPrefs));
chewing_boolean_prefs_[pref_id].SetValue(checkbox->checked());
}
void LanguageChewingConfigView::ItemChanged(
views::Combobox* sender, int prev_index, int new_index) {
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
if (current.combobox == sender) {
const std::string config_value =
@@ -88,11 +93,12 @@ void LanguageChewingConfigView::ItemChanged(
void LanguageChewingConfigView::SliderValueChanged(views::Slider* sender) {
size_t pref_id;
- for (pref_id = 0; pref_id < kNumChewingIntegerPrefs; ++pref_id) {
+ for (pref_id = 0; pref_id < language_prefs::kNumChewingIntegerPrefs;
+ ++pref_id) {
if (chewing_integer_sliders_[pref_id] == sender)
break;
}
- DCHECK(pref_id < kNumChewingIntegerPrefs);
+ DCHECK(pref_id < language_prefs::kNumChewingIntegerPrefs);
chewing_integer_prefs_[pref_id].SetValue(sender->value());
}
@@ -145,13 +151,14 @@ void LanguageChewingConfigView::InitControlLayout() {
column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
GridLayout::USE_PREF, 0, 0);
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
chewing_boolean_checkboxes_[i] = new views::Checkbox(
- l10n_util::GetString(kChewingBooleanPrefs[i].message_id));
+ l10n_util::GetString(
+ language_prefs::kChewingBooleanPrefs[i].message_id));
chewing_boolean_checkboxes_[i]->set_listener(this);
chewing_boolean_checkboxes_[i]->set_tag(i);
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
current.combobox = new LanguageCombobox(current.combobox_model);
current.combobox->set_listener(this);
@@ -160,31 +167,32 @@ void LanguageChewingConfigView::InitControlLayout() {
new LanguageCombobox(hsu_sel_key_type_.combobox_model);
hsu_sel_key_type_.combobox->set_listener(this);
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
chewing_integer_sliders_[i] = new views::Slider(
- kChewingIntegerPrefs[i].min_pref_value,
- kChewingIntegerPrefs[i].max_pref_value,
+ language_prefs::kChewingIntegerPrefs[i].min_pref_value,
+ language_prefs::kChewingIntegerPrefs[i].max_pref_value,
1,
static_cast<views::Slider::StyleFlags>(
views::Slider::STYLE_DRAW_VALUE |
views::Slider::STYLE_UPDATE_ON_RELEASE),
this);
}
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
layout->StartRow(0, kColumnSetId);
layout->AddView(chewing_boolean_checkboxes_[i]);
}
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
layout->StartRow(0, kColumnSetId);
layout->AddView(new views::Label(
- l10n_util::GetString(kChewingIntegerPrefs[i].message_id)));
+ l10n_util::GetString(
+ language_prefs::kChewingIntegerPrefs[i].message_id)));
layout->AddView(chewing_integer_sliders_[i]);
}
NotifyPrefChanged();
// Show the comboboxes.
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
const ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
layout->StartRow(0, kColumnSetId);
layout->AddView(new views::Label(current.combobox_model->GetLabel()));
@@ -205,15 +213,15 @@ void LanguageChewingConfigView::Observe(NotificationType type,
}
void LanguageChewingConfigView::NotifyPrefChanged() {
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
const bool checked = chewing_boolean_prefs_[i].GetValue();
chewing_boolean_checkboxes_[i]->SetChecked(checked);
}
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
const int value = chewing_integer_prefs_[i].GetValue();
chewing_integer_sliders_[i]->SetValue(value);
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
ChewingPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
const std::string value = current.multiple_choice_pref.GetValue();
for (int i = 0; i < current.combobox_model->num_items(); ++i) {
diff --git a/chrome/browser/chromeos/options/language_chewing_config_view.h b/chrome/browser/chromeos/options/language_chewing_config_view.h
index cdffac4..d7a33cf 100644
--- a/chrome/browser/chromeos/options/language_chewing_config_view.h
+++ b/chrome/browser/chromeos/options/language_chewing_config_view.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CHEWING_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CHEWING_CONFIG_VIEW_H_
+#pragma once
#include <string>
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/views/options/options_page_view.h"
#include "views/controls/button/checkbox.h"
#include "views/controls/combobox/combobox.h"
@@ -69,20 +70,24 @@ class LanguageChewingConfigView : public views::ButtonListener,
// Updates the chewing checkboxes.
void NotifyPrefChanged();
- BooleanPrefMember chewing_boolean_prefs_[kNumChewingBooleanPrefs];
- IntegerPrefMember chewing_integer_prefs_[kNumChewingIntegerPrefs];
+ BooleanPrefMember chewing_boolean_prefs_[
+ language_prefs::kNumChewingBooleanPrefs];
+ IntegerPrefMember chewing_integer_prefs_[
+ language_prefs::kNumChewingIntegerPrefs];
views::View* contents_;
// Checkboxes for Chewing.
- views::Checkbox* chewing_boolean_checkboxes_[kNumChewingBooleanPrefs];
+ views::Checkbox* chewing_boolean_checkboxes_[
+ language_prefs::kNumChewingBooleanPrefs];
- views::Slider* chewing_integer_sliders_[kNumChewingIntegerPrefs];
+ views::Slider* chewing_integer_sliders_[
+ language_prefs::kNumChewingIntegerPrefs];
struct ChewingPrefAndAssociatedCombobox {
StringPrefMember multiple_choice_pref;
LanguageComboboxModel<const char*>* combobox_model;
LanguageCombobox* combobox;
- } prefs_and_comboboxes_[kNumChewingMultipleChoicePrefs];
+ } prefs_and_comboboxes_[language_prefs::kNumChewingMultipleChoicePrefs];
struct HsuSelKeyTypePrefAndAssociatedCombobox {
IntegerPrefMember multiple_choice_pref;
diff --git a/chrome/browser/chromeos/options/language_config_model.cc b/chrome/browser/chromeos/options/language_config_model.cc
index fafa2f6..3502c2f 100644
--- a/chrome/browser/chromeos/options/language_config_model.cc
+++ b/chrome/browser/chromeos/options/language_config_model.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "app/l10n_util.h"
+#include "base/string_split.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
@@ -16,6 +17,7 @@
#include "chrome/browser/chromeos/preferences.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
namespace chromeos {
@@ -30,14 +32,13 @@ int AddLanguageComboboxModel::GetItemCount() {
return get_languages_count() + 1 - ignore_set_.size();
}
-std::wstring AddLanguageComboboxModel::GetItemAt(int index) {
+string16 AddLanguageComboboxModel::GetItemAt(int index) {
// Show "Add language" as the first item.
if (index == 0) {
- return l10n_util::GetString(
+ return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_COMBOBOX);
}
- return input_method::MaybeRewriteLanguageName(
- GetLanguageNameAt(GetLanguageIndex(index)));
+ return WideToUTF16Hack(GetLanguageNameAt(GetLanguageIndex(index)));
}
int AddLanguageComboboxModel::GetLanguageIndex(int index) const {
@@ -213,10 +214,6 @@ void LanguageConfigModel::GetInputMethodIdsFromLanguageCode(
input_method_ids->clear();
input_method::GetInputMethodIdsFromLanguageCode(
language_code, input_method::kAllInputMethods, input_method_ids);
-
- // Reorder the input methods.
- input_method::ReorderInputMethodIdsForLanguageCode(
- language_code, input_method_ids);
}
void LanguageConfigModel::NotifyPrefChanged() {
diff --git a/chrome/browser/chromeos/options/language_config_model.h b/chrome/browser/chromeos/options/language_config_model.h
index 352208c..05a63ac 100644
--- a/chrome/browser/chromeos/options/language_config_model.h
+++ b/chrome/browser/chromeos/options/language_config_model.h
@@ -4,15 +4,16 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_MODEL_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_MODEL_H_
+#pragma once
-#include <map>
#include <set>
#include <string>
#include <vector>
+#include "base/string16.h"
#include "chrome/browser/language_combobox_model.h"
-#include "chrome/browser/pref_member.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/notification_service.h"
#include "cros/chromeos_input_method.h"
@@ -21,13 +22,13 @@ namespace chromeos {
// The combobox model is used for adding languages in the language config
// view.
-class AddLanguageComboboxModel : public LanguageComboboxModel {
+class AddLanguageComboboxModel : public ::LanguageComboboxModel {
public:
AddLanguageComboboxModel(Profile* profile,
const std::vector<std::string>& locale_codes);
// LanguageComboboxModel overrides.
virtual int GetItemCount();
- virtual std::wstring GetItemAt(int index);
+ virtual string16 GetItemAt(int index);
// Converts the given index (index of the items in the combobox) to the
// index of the internal language list. The returned index can be used
diff --git a/chrome/browser/chromeos/options/language_config_model_unittest.cc b/chrome/browser/chromeos/options/language_config_model_unittest.cc
index e9b593d..0d7e12f 100644
--- a/chrome/browser/chromeos/options/language_config_model_unittest.cc
+++ b/chrome/browser/chromeos/options/language_config_model_unittest.cc
@@ -26,18 +26,18 @@ TEST(AddLanguageComboboxModelTest, AddLanguageComboboxModel) {
ASSERT_EQ(4, model.GetItemCount());
// The first item should be "Add language" labe.
- EXPECT_EQ(l10n_util::GetString(
+ EXPECT_EQ(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_COMBOBOX),
model.GetItemAt(0));
// Other items should be sorted language display names for UI (hence
// French comes before German). Note that the returned display names
// are followed by their native representations. To simplify matching,
// use StartsWith() here.
- EXPECT_TRUE(StartsWith(model.GetItemAt(1), L"French", true))
+ EXPECT_TRUE(StartsWith(model.GetItemAt(1), ASCIIToUTF16("French"), true))
<< model.GetItemAt(1);
- EXPECT_TRUE(StartsWith(model.GetItemAt(2), L"German", true))
+ EXPECT_TRUE(StartsWith(model.GetItemAt(2), ASCIIToUTF16("German"), true))
<< model.GetItemAt(2);
- EXPECT_TRUE(StartsWith(model.GetItemAt(3), L"Korean", true))
+ EXPECT_TRUE(StartsWith(model.GetItemAt(3), ASCIIToUTF16("Korean"), true))
<< model.GetItemAt(3);
// GetLanguageIndex() returns the given index -1 to offset "Add language".
diff --git a/chrome/browser/chromeos/options/language_config_util.h b/chrome/browser/chromeos/options/language_config_util.h
index cc80ee7..6f262cf 100644
--- a/chrome/browser/chromeos/options/language_config_util.h
+++ b/chrome/browser/chromeos/options/language_config_util.h
@@ -4,7 +4,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_UTIL_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_UTIL_H_
+#pragma once
+#include "app/combobox_model.h"
+#include "base/string16.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "views/controls/combobox/combobox.h"
@@ -15,12 +18,14 @@ template <typename DataType>
class LanguageComboboxModel : public ComboboxModel {
public:
explicit LanguageComboboxModel(
- const LanguageMultipleChoicePreference<DataType>* pref_data)
+ const language_prefs::LanguageMultipleChoicePreference<DataType>*
+ pref_data)
: pref_data_(pref_data), num_items_(0) {
// Check how many items are defined in the |pref_data->values_and_ids|
// array.
for (size_t i = 0;
- i < LanguageMultipleChoicePreference<DataType>::kMaxItems; ++i) {
+ i < language_prefs::LanguageMultipleChoicePreference<DataType>::
+ kMaxItems; ++i) {
if ((pref_data_->values_and_ids)[i].item_message_id == 0) {
break;
}
@@ -34,13 +39,13 @@ class LanguageComboboxModel : public ComboboxModel {
}
// Implements ComboboxModel interface.
- virtual std::wstring GetItemAt(int index) {
+ virtual string16 GetItemAt(int index) {
if (index < 0 || index >= num_items_) {
LOG(ERROR) << "Index is out of bounds: " << index;
- return L"";
+ return string16();
}
const int message_id = (pref_data_->values_and_ids)[index].item_message_id;
- return l10n_util::GetString(message_id);
+ return l10n_util::GetStringUTF16(message_id);
}
// Gets a label for the combobox like "Input mode". This function is NOT part
@@ -65,7 +70,7 @@ class LanguageComboboxModel : public ComboboxModel {
}
private:
- const LanguageMultipleChoicePreference<DataType>* pref_data_;
+ const language_prefs::LanguageMultipleChoicePreference<DataType>* pref_data_;
int num_items_;
DISALLOW_COPY_AND_ASSIGN(LanguageComboboxModel);
diff --git a/chrome/browser/chromeos/options/language_config_view.cc b/chrome/browser/chromeos/options/language_config_view.cc
index d9f482e..1ee7845 100644
--- a/chrome/browser/chromeos/options/language_config_view.cc
+++ b/chrome/browser/chromeos/options/language_config_view.cc
@@ -17,7 +17,7 @@
#include "chrome/browser/chromeos/options/options_window_view.h"
#include "chrome/browser/chromeos/preferences.h"
#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/views/restart_message_box.h"
#include "chrome/common/notification_type.h"
@@ -515,8 +515,7 @@ void LanguageConfigView::AddUiLanguageSection(const std::string& language_code,
g_browser_process->GetApplicationLocale();
const string16 language_name16 = l10n_util::GetDisplayNameForLocale(
language_code, application_locale, true);
- const std::wstring language_name
- = input_method::MaybeRewriteLanguageName(UTF16ToWide(language_name16));
+ const std::wstring language_name = UTF16ToWide(language_name16);
views::Label* language_name_label = new views::Label(language_name);
language_name_label->SetFont(
language_name_label->font().DeriveFont(0, gfx::Font::BOLD));
diff --git a/chrome/browser/chromeos/options/language_config_view.h b/chrome/browser/chromeos/options/language_config_view.h
index bd2b0e3..a7dd980 100644
--- a/chrome/browser/chromeos/options/language_config_view.h
+++ b/chrome/browser/chromeos/options/language_config_view.h
@@ -4,11 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_CONFIG_VIEW_H_
+#pragma once
#include <map>
#include <set>
#include <string>
-#include <vector>
#include "app/table_model.h"
#include "chrome/browser/chromeos/options/language_config_model.h"
diff --git a/chrome/browser/chromeos/options/language_hangul_config_view.cc b/chrome/browser/chromeos/options/language_hangul_config_view.cc
index 9158c89..0e8227d 100644
--- a/chrome/browser/chromeos/options/language_hangul_config_view.cc
+++ b/chrome/browser/chromeos/options/language_hangul_config_view.cc
@@ -6,14 +6,15 @@
#include "app/combobox_model.h"
#include "app/l10n_util.h"
+#include "base/string16.h"
#include "base/utf_string_conversions.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/preferences.h"
#include "chrome/browser/profile.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "views/controls/button/checkbox.h"
@@ -28,10 +29,12 @@ namespace chromeos {
class HangulKeyboardComboboxModel : public ComboboxModel {
public:
HangulKeyboardComboboxModel() {
- for (size_t i = 0; i < arraysize(kHangulKeyboardNameIDPairs); ++i) {
+ for (size_t i = 0; i < language_prefs::kNumHangulKeyboardNameIDPairs;
+ ++i) {
layouts_.push_back(std::make_pair(
- l10n_util::GetStringUTF8(kHangulKeyboardNameIDPairs[i].message_id),
- kHangulKeyboardNameIDPairs[i].keyboard_id));
+ l10n_util::GetStringUTF8(
+ language_prefs::kHangulKeyboardNameIDPairs[i].message_id),
+ language_prefs::kHangulKeyboardNameIDPairs[i].keyboard_id));
}
}
@@ -41,12 +44,12 @@ class HangulKeyboardComboboxModel : public ComboboxModel {
}
// Implements ComboboxModel interface.
- virtual std::wstring GetItemAt(int index) {
+ virtual string16 GetItemAt(int index) {
if (index < 0 || index > GetItemCount()) {
LOG(ERROR) << "Index is out of bounds: " << index;
- return L"";
+ return string16();
}
- return UTF8ToWide(layouts_.at(index).first);
+ return UTF8ToUTF16(layouts_.at(index).first);
}
// Gets a keyboard layout ID (e.g. "2", "3f", ..) for an item at zero-origin
diff --git a/chrome/browser/chromeos/options/language_hangul_config_view.h b/chrome/browser/chromeos/options/language_hangul_config_view.h
index 88f3188..58466b0 100644
--- a/chrome/browser/chromeos/options/language_hangul_config_view.h
+++ b/chrome/browser/chromeos/options/language_hangul_config_view.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_HANGUL_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_HANGUL_CONFIG_VIEW_H_
+#pragma once
#include <string>
#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/views/options/options_page_view.h"
#include "views/controls/combobox/combobox.h"
#include "views/controls/label.h"
diff --git a/chrome/browser/chromeos/options/language_mozc_config_view.cc b/chrome/browser/chromeos/options/language_mozc_config_view.cc
index a48f5ec..15fbfdf 100644
--- a/chrome/browser/chromeos/options/language_mozc_config_view.cc
+++ b/chrome/browser/chromeos/options/language_mozc_config_view.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/chromeos/options/language_mozc_config_view.h"
-#include "app/combobox_model.h"
#include "app/l10n_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
@@ -26,7 +25,7 @@ namespace {
enum ButtonTag {
// 0 to kNumMozcBooleanPrefs - 1 are reserved for the checkboxes for integer
// preferences.
- kResetToDefaultsButton = chromeos::kNumMozcBooleanPrefs,
+ kResetToDefaultsButton = chromeos::language_prefs::kNumMozcBooleanPrefs,
};
} // namespace
@@ -36,30 +35,34 @@ LanguageMozcConfigView::LanguageMozcConfigView(Profile* profile)
: OptionsPageView(profile),
contents_(NULL),
reset_to_defaults_button_(NULL) {
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
current.boolean_pref.Init(
- kMozcBooleanPrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kMozcBooleanPrefs[i].pref_name, profile->GetPrefs(),
+ this);
current.checkbox = NULL;
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
current.multiple_choice_pref.Init(
- kMozcMultipleChoicePrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kMozcMultipleChoicePrefs[i].pref_name,
+ profile->GetPrefs(), this);
current.combobox_model =
- new LanguageComboboxModel<const char*>(&kMozcMultipleChoicePrefs[i]);
+ new LanguageComboboxModel<const char*>(
+ &language_prefs::kMozcMultipleChoicePrefs[i]);
current.combobox = NULL;
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
current.integer_pref.Init(
- kMozcIntegerPrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kMozcIntegerPrefs[i].pref_name, profile->GetPrefs(),
+ this);
current.slider = NULL;
}
}
LanguageMozcConfigView::~LanguageMozcConfigView() {
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
delete prefs_and_comboboxes_[i].combobox_model;
}
}
@@ -72,7 +75,8 @@ void LanguageMozcConfigView::ButtonPressed(
return;
}
views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
- DCHECK(pref_id >= 0 && pref_id < static_cast<int>(kNumMozcBooleanPrefs));
+ DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
+ language_prefs::kNumMozcBooleanPrefs));
prefs_and_checkboxes_[pref_id].boolean_pref.SetValue(checkbox->checked());
}
@@ -82,7 +86,7 @@ void LanguageMozcConfigView::ItemChanged(
LOG(ERROR) << "Invalid new_index: " << new_index;
return;
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
if (current.combobox == sender) {
const std::string config_value =
@@ -97,11 +101,12 @@ void LanguageMozcConfigView::ItemChanged(
void LanguageMozcConfigView::SliderValueChanged(views::Slider* sender) {
size_t pref_id;
- for (pref_id = 0; pref_id < kNumMozcIntegerPrefs; ++pref_id) {
+ for (pref_id = 0; pref_id < language_prefs::kNumMozcIntegerPrefs;
+ ++pref_id) {
if (prefs_and_sliders_[pref_id].slider == sender)
break;
}
- DCHECK(pref_id < kNumMozcIntegerPrefs);
+ DCHECK(pref_id < language_prefs::kNumMozcIntegerPrefs);
prefs_and_sliders_[pref_id].integer_pref.SetValue(sender->value());
}
@@ -159,23 +164,23 @@ void LanguageMozcConfigView::InitControlLayout() {
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
GridLayout::USE_PREF, 0, 0);
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
current.checkbox = new views::Checkbox(
- l10n_util::GetString(kMozcBooleanPrefs[i].message_id));
+ l10n_util::GetString(language_prefs::kMozcBooleanPrefs[i].message_id));
current.checkbox->set_listener(this);
current.checkbox->set_tag(i);
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
current.combobox = new LanguageCombobox(current.combobox_model);
current.combobox->set_listener(this);
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
current.slider = new views::Slider(
- kMozcIntegerPrefs[i].min_pref_value,
- kMozcIntegerPrefs[i].max_pref_value,
+ language_prefs::kMozcIntegerPrefs[i].min_pref_value,
+ language_prefs::kMozcIntegerPrefs[i].max_pref_value,
1,
static_cast<views::Slider::StyleFlags>(
views::Slider::STYLE_DRAW_VALUE |
@@ -192,23 +197,24 @@ void LanguageMozcConfigView::InitControlLayout() {
layout->AddView(reset_to_defaults_button_);
// Show the checkboxes.
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
const MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
layout->StartRow(0, kColumnSetId);
layout->AddView(current.checkbox, 3, 1);
}
// Show the comboboxes.
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
const MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
layout->StartRow(0, kColumnSetId);
layout->AddView(new views::Label(current.combobox_model->GetLabel()));
layout->AddView(current.combobox);
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
const MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
layout->StartRow(0, kColumnSetId);
layout->AddView(new views::Label(
- l10n_util::GetString(kMozcIntegerPrefs[i].message_id)));
+ l10n_util::GetString(
+ language_prefs::kMozcIntegerPrefs[i].message_id)));
layout->AddView(current.slider);
}
NotifyPrefChanged(); // Sync the slider with current Chrome prefs.
@@ -225,12 +231,12 @@ void LanguageMozcConfigView::Observe(NotificationType type,
void LanguageMozcConfigView::NotifyPrefChanged() {
// Update comboboxes.
// TODO(yusukes): We don't have to update all UI controls.
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
MozcPrefAndAssociatedCheckbox& current = prefs_and_checkboxes_[i];
const bool checked = current.boolean_pref.GetValue();
current.checkbox->SetChecked(checked);
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
MozcPrefAndAssociatedCombobox& current = prefs_and_comboboxes_[i];
const std::string value = current.multiple_choice_pref.GetValue();
for (int i = 0; i < current.combobox_model->num_items(); ++i) {
@@ -240,7 +246,7 @@ void LanguageMozcConfigView::NotifyPrefChanged() {
}
}
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
MozcPrefAndAssociatedSlider& current = prefs_and_sliders_[i];
const int value = current.integer_pref.GetValue();
current.slider->SetValue(value);
@@ -248,17 +254,17 @@ void LanguageMozcConfigView::NotifyPrefChanged() {
}
void LanguageMozcConfigView::ResetToDefaults() {
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
prefs_and_checkboxes_[i].boolean_pref.SetValue(
- kMozcBooleanPrefs[i].default_pref_value);
+ language_prefs::kMozcBooleanPrefs[i].default_pref_value);
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
prefs_and_comboboxes_[i].multiple_choice_pref.SetValue(
- kMozcMultipleChoicePrefs[i].default_pref_value);
+ language_prefs::kMozcMultipleChoicePrefs[i].default_pref_value);
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
prefs_and_sliders_[i].integer_pref.SetValue(
- kMozcIntegerPrefs[i].default_pref_value);
+ language_prefs::kMozcIntegerPrefs[i].default_pref_value);
}
// Reflect the preference changes to the controls.
NotifyPrefChanged();
diff --git a/chrome/browser/chromeos/options/language_mozc_config_view.h b/chrome/browser/chromeos/options/language_mozc_config_view.h
index 0ee0266..496ec14 100644
--- a/chrome/browser/chromeos/options/language_mozc_config_view.h
+++ b/chrome/browser/chromeos/options/language_mozc_config_view.h
@@ -4,13 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_MOZC_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_MOZC_CONFIG_VIEW_H_
+#pragma once
#include <string>
-#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/views/options/options_page_view.h"
#include "views/controls/combobox/combobox.h"
#include "views/controls/label.h"
@@ -83,18 +83,18 @@ class LanguageMozcConfigView : public views::ButtonListener,
struct MozcPrefAndAssociatedCheckbox {
BooleanPrefMember boolean_pref;
views::Checkbox* checkbox;
- } prefs_and_checkboxes_[kNumMozcBooleanPrefs];
+ } prefs_and_checkboxes_[language_prefs::kNumMozcBooleanPrefs];
struct MozcPrefAndAssociatedCombobox {
StringPrefMember multiple_choice_pref;
LanguageComboboxModel<const char*>* combobox_model;
LanguageCombobox* combobox;
- } prefs_and_comboboxes_[kNumMozcMultipleChoicePrefs];
+ } prefs_and_comboboxes_[language_prefs::kNumMozcMultipleChoicePrefs];
struct MozcPrefAndAssociatedSlider {
IntegerPrefMember integer_pref;
views::Slider* slider;
- } prefs_and_sliders_[kNumMozcIntegerPrefs];
+ } prefs_and_sliders_[language_prefs::kNumMozcIntegerPrefs];
DISALLOW_COPY_AND_ASSIGN(LanguageMozcConfigView);
};
diff --git a/chrome/browser/chromeos/options/language_pinyin_config_view.cc b/chrome/browser/chromeos/options/language_pinyin_config_view.cc
index 48d79d7..2290f4e 100644
--- a/chrome/browser/chromeos/options/language_pinyin_config_view.cc
+++ b/chrome/browser/chromeos/options/language_pinyin_config_view.cc
@@ -4,16 +4,15 @@
#include "chrome/browser/chromeos/options/language_pinyin_config_view.h"
-#include "app/combobox_model.h"
#include "app/l10n_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/pref_names.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/options/language_config_util.h"
#include "chrome/browser/chromeos/preferences.h"
#include "chrome/browser/profile.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "views/controls/button/checkbox.h"
@@ -26,16 +25,19 @@ namespace chromeos {
LanguagePinyinConfigView::LanguagePinyinConfigView(Profile* profile)
: OptionsPageView(profile), contents_(NULL) {
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
pinyin_boolean_prefs_[i].Init(
- kPinyinBooleanPrefs[i].pref_name, profile->GetPrefs(), this);
+ language_prefs::kPinyinBooleanPrefs[i].pref_name, profile->GetPrefs(),
+ this);
pinyin_boolean_checkboxes_[i] = NULL;
}
double_pinyin_schema_.multiple_choice_pref.Init(
- kPinyinDoublePinyinSchema.pref_name, profile->GetPrefs(), this);
+ language_prefs::kPinyinDoublePinyinSchema.pref_name,
+ profile->GetPrefs(), this);
double_pinyin_schema_.combobox_model =
- new LanguageComboboxModel<int>(&kPinyinDoublePinyinSchema);
+ new LanguageComboboxModel<int>(
+ &language_prefs::kPinyinDoublePinyinSchema);
double_pinyin_schema_.combobox = NULL;
}
@@ -46,7 +48,8 @@ void LanguagePinyinConfigView::ButtonPressed(
views::Button* sender, const views::Event& event) {
views::Checkbox* checkbox = static_cast<views::Checkbox*>(sender);
const int pref_id = checkbox->tag();
- DCHECK(pref_id >= 0 && pref_id < static_cast<int>(kNumPinyinBooleanPrefs));
+ DCHECK(pref_id >= 0 && pref_id < static_cast<int>(
+ language_prefs::kNumPinyinBooleanPrefs));
pinyin_boolean_prefs_[pref_id].SetValue(checkbox->checked());
}
@@ -110,9 +113,10 @@ void LanguagePinyinConfigView::InitControlLayout() {
column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
GridLayout::USE_PREF, 0, 0);
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
pinyin_boolean_checkboxes_[i] = new views::Checkbox(
- l10n_util::GetString(kPinyinBooleanPrefs[i].message_id));
+ l10n_util::GetString(
+ language_prefs::kPinyinBooleanPrefs[i].message_id));
pinyin_boolean_checkboxes_[i]->set_listener(this);
pinyin_boolean_checkboxes_[i]->set_tag(i);
}
@@ -121,7 +125,7 @@ void LanguagePinyinConfigView::InitControlLayout() {
double_pinyin_schema_.combobox->set_listener(this);
NotifyPrefChanged();
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
layout->StartRow(0, kColumnSetId);
layout->AddView(pinyin_boolean_checkboxes_[i]);
}
@@ -140,7 +144,7 @@ void LanguagePinyinConfigView::Observe(NotificationType type,
}
void LanguagePinyinConfigView::NotifyPrefChanged() {
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
const bool checked = pinyin_boolean_prefs_[i].GetValue();
pinyin_boolean_checkboxes_[i]->SetChecked(checked);
}
diff --git a/chrome/browser/chromeos/options/language_pinyin_config_view.h b/chrome/browser/chromeos/options/language_pinyin_config_view.h
index 9879f28..6d38bd5 100644
--- a/chrome/browser/chromeos/options/language_pinyin_config_view.h
+++ b/chrome/browser/chromeos/options/language_pinyin_config_view.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_PINYIN_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_LANGUAGE_PINYIN_CONFIG_VIEW_H_
+#pragma once
#include <string>
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/views/options/options_page_view.h"
#include "views/controls/button/checkbox.h"
#include "views/controls/combobox/combobox.h"
@@ -64,12 +65,14 @@ class LanguagePinyinConfigView : public views::ButtonListener,
// Updates the pinyin checkboxes.
void NotifyPrefChanged();
- BooleanPrefMember pinyin_boolean_prefs_[kNumPinyinBooleanPrefs];
+ BooleanPrefMember pinyin_boolean_prefs_[
+ language_prefs::kNumPinyinBooleanPrefs];
// TODO(yusukes): Support integer prefs if needed.
views::View* contents_;
// A checkboxes for Pinyin.
- views::Checkbox* pinyin_boolean_checkboxes_[kNumPinyinBooleanPrefs];
+ views::Checkbox* pinyin_boolean_checkboxes_[
+ language_prefs::kNumPinyinBooleanPrefs];
struct DoublePinyinSchemaPrefAndAssociatedCombobox {
IntegerPrefMember multiple_choice_pref;
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index b139b56..d18006e 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -6,6 +6,7 @@
#include "app/l10n_util.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/options/cellular_config_view.h"
#include "chrome/browser/chromeos/options/ip_config_view.h"
#include "chrome/browser/chromeos/options/wifi_config_view.h"
@@ -178,7 +179,7 @@ void NetworkConfigView::Init() {
if (flags_ & FLAG_CELLULAR) {
cellularconfig_view_ = new CellularConfigView(this, cellular_);
tabs_->AddTab(
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_NETWORK_CONFIG),
+ l10n_util::GetString(IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USAGE),
cellularconfig_view_);
}
if (flags_ & FLAG_WIFI) {
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h
index 2bdd392..2fda171 100644
--- a/chrome/browser/chromeos/options/network_config_view.h
+++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -1,13 +1,13 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_NETWORK_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_NETWORK_CONFIG_VIEW_H_
+#pragma once
#include <string>
-#include "base/string16.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "views/controls/tabbed_pane/tabbed_pane.h"
#include "views/window/dialog_delegate.h"
diff --git a/chrome/browser/chromeos/options/options_window_view.cc b/chrome/browser/chromeos/options/options_window_view.cc
index 4535e8b..b9602f2 100644
--- a/chrome/browser/chromeos/options/options_window_view.cc
+++ b/chrome/browser/chromeos/options/options_window_view.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/options_window.h"
#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -15,8 +14,9 @@
#include "chrome/browser/gtk/options/advanced_page_gtk.h"
#include "chrome/browser/gtk/options/content_page_gtk.h"
#include "chrome/browser/gtk/options/general_page_gtk.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/views/accessible_view_helper.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
@@ -143,6 +143,8 @@ class OptionsWindowView : public views::View,
// The last page the user was on when they opened the Options window.
IntegerPrefMember last_selected_page_;
+ scoped_ptr<AccessibleViewHelper> accessible_view_helper_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(OptionsWindowView);
};
@@ -253,6 +255,9 @@ void OptionsWindowView::Layout() {
tabs_->SetBounds(kDialogPadding, kDialogPadding,
width() - (2 * kDialogPadding),
height() - (2 * kDialogPadding));
+ if (!accessible_view_helper_.get()) {
+ accessible_view_helper_.reset(new AccessibleViewHelper(this, profile_));
+ }
}
gfx::Size OptionsWindowView::GetPreferredSize() {
diff --git a/chrome/browser/chromeos/options/options_window_view.h b/chrome/browser/chromeos/options/options_window_view.h
index a6b31b6..784ec8d 100644
--- a/chrome/browser/chromeos/options/options_window_view.h
+++ b/chrome/browser/chromeos/options/options_window_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_OPTIONS_WINDOW_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_OPTIONS_WINDOW_VIEW_H_
+#pragma once
namespace chromeos {
diff --git a/chrome/browser/chromeos/options/settings_page_view.cc b/chrome/browser/chromeos/options/settings_page_view.cc
index e6afc30..84d9654 100644
--- a/chrome/browser/chromeos/options/settings_page_view.cc
+++ b/chrome/browser/chromeos/options/settings_page_view.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/chromeos/options/settings_page_view.h"
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
#include "gfx/skia_utils_gtk.h"
#include "views/controls/label.h"
#include "views/fill_layout.h"
diff --git a/chrome/browser/chromeos/options/settings_page_view.h b/chrome/browser/chromeos/options/settings_page_view.h
index 5793980..35e9934 100644
--- a/chrome/browser/chromeos/options/settings_page_view.h
+++ b/chrome/browser/chromeos/options/settings_page_view.h
@@ -4,13 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_SETTINGS_PAGE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_SETTINGS_PAGE_VIEW_H_
+#pragma once
#include <gtk/gtk.h>
#include "chrome/browser/views/options/options_page_view.h"
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
diff --git a/chrome/browser/chromeos/options/system_page_view.cc b/chrome/browser/chromeos/options/system_page_view.cc
index f074889..3cd9d40 100644
--- a/chrome/browser/chromeos/options/system_page_view.cc
+++ b/chrome/browser/chromeos/options/system_page_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -8,13 +8,20 @@
#include <vector>
#include "app/combobox_model.h"
+#include "app/l10n_util.h"
#include "base/stl_util-inl.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/cros/system_library.h"
+#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/chromeos/options/language_config_util.h"
#include "chrome/browser/chromeos/options/language_config_view.h"
#include "chrome/browser/chromeos/options/options_window_view.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
@@ -121,14 +128,15 @@ class DateTimeSection : public SettingsPageSection,
return static_cast<int>(timezones_.size());
}
- virtual std::wstring GetItemAt(int index) {
+ virtual string16 GetItemAt(int index) {
icu::UnicodeString name;
timezones_[index]->getDisplayName(name);
std::wstring output;
UTF16ToWide(name.getBuffer(), name.length(), &output);
int hour_offset = timezones_[index]->getRawOffset() / 3600000;
- return StringPrintf(hour_offset == 0 ? L"(GMT) " : (hour_offset > 0 ?
- L"(GMT+%d) " : L"(GMT%d) "), hour_offset) + output;
+ return WideToUTF16Hack(
+ base::StringPrintf(hour_offset == 0 ? L"(GMT) " : (hour_offset > 0 ?
+ L"(GMT+%d) " : L"(GMT%d) "), hour_offset) + output);
}
virtual icu::TimeZone* GetTimeZoneAt(int index) {
@@ -211,7 +219,7 @@ class TouchpadSection : public SettingsPageSection,
protected:
// SettingsPageSection overrides:
virtual void InitContents(GridLayout* layout);
- virtual void NotifyPrefChanged(const std::wstring* pref_name);
+ virtual void NotifyPrefChanged(const std::string* pref_name);
private:
// The View that contains the contents of the section.
@@ -219,14 +227,10 @@ class TouchpadSection : public SettingsPageSection,
// Controls for this section:
views::Checkbox* enable_tap_to_click_checkbox_;
- views::Checkbox* enable_vert_edge_scroll_checkbox_;
- views::Slider* speed_factor_slider_;
views::Slider* sensitivity_slider_;
// Preferences for this section:
BooleanPrefMember tap_to_click_enabled_;
- BooleanPrefMember vert_edge_scroll_enabled_;
- IntegerPrefMember speed_factor_;
IntegerPrefMember sensitivity_;
DISALLOW_COPY_AND_ASSIGN(TouchpadSection);
@@ -235,8 +239,6 @@ class TouchpadSection : public SettingsPageSection,
TouchpadSection::TouchpadSection(Profile* profile)
: SettingsPageSection(profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD),
enable_tap_to_click_checkbox_(NULL),
- enable_vert_edge_scroll_checkbox_(NULL),
- speed_factor_slider_(NULL),
sensitivity_slider_(NULL) {
}
@@ -249,24 +251,11 @@ void TouchpadSection::ButtonPressed(
UserMetricsAction("Options_TapToClickCheckbox_Disable"),
profile()->GetPrefs());
tap_to_click_enabled_.SetValue(enabled);
- } else if (sender == enable_vert_edge_scroll_checkbox_) {
- bool enabled = enable_vert_edge_scroll_checkbox_->checked();
- UserMetricsRecordAction(enabled ?
- UserMetricsAction("Options_VertEdgeScrollCheckbox_Enable") :
- UserMetricsAction("Options_VertEdgeScrollCheckbox_Disable"),
- profile()->GetPrefs());
- vert_edge_scroll_enabled_.SetValue(enabled);
}
}
void TouchpadSection::SliderValueChanged(views::Slider* sender) {
- if (sender == speed_factor_slider_) {
- double value = speed_factor_slider_->value();
- UserMetricsRecordAction(
- UserMetricsAction("Options_SpeedFactorSlider_Changed"),
- profile()->GetPrefs());
- speed_factor_.SetValue(value);
- } else if (sender == sensitivity_slider_) {
+ if (sender == sensitivity_slider_) {
double value = sensitivity_slider_->value();
UserMetricsRecordAction(
UserMetricsAction("Options_SensitivitySlider_Changed"),
@@ -280,18 +269,8 @@ void TouchpadSection::InitContents(GridLayout* layout) {
IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION));
enable_tap_to_click_checkbox_->set_listener(this);
enable_tap_to_click_checkbox_->SetMultiLine(true);
- enable_vert_edge_scroll_checkbox_ = new views::Checkbox(l10n_util::GetString(
- IDS_OPTIONS_SETTINGS_VERT_EDGE_SCROLL_ENABLED_DESCRIPTION));
- enable_vert_edge_scroll_checkbox_->set_listener(this);
- enable_vert_edge_scroll_checkbox_->SetMultiLine(true);
- // Create speed factor slider with values between 1 and 10 step 1
- speed_factor_slider_ = new views::Slider(1, 10, 1,
- static_cast<views::Slider::StyleFlags>(
- views::Slider::STYLE_DRAW_VALUE |
- views::Slider::STYLE_UPDATE_ON_RELEASE),
- this);
- // Create sensitivity slider with values between 1 and 10 step 1
- sensitivity_slider_ = new views::Slider(1, 10, 1,
+ // Create sensitivity slider with values between 1 and 5 step 1
+ sensitivity_slider_ = new views::Slider(1, 5, 1,
static_cast<views::Slider::StyleFlags>(
views::Slider::STYLE_DRAW_VALUE |
views::Slider::STYLE_UPDATE_ON_RELEASE),
@@ -302,42 +281,22 @@ void TouchpadSection::InitContents(GridLayout* layout) {
l10n_util::GetString(IDS_OPTIONS_SETTINGS_SENSITIVITY_DESCRIPTION)));
layout->AddView(sensitivity_slider_);
layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
- layout->StartRow(0, double_column_view_set_id());
- layout->AddView(new views::Label(
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_SPEED_FACTOR_DESCRIPTION)));
- layout->AddView(speed_factor_slider_);
- layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
layout->StartRow(0, single_column_view_set_id());
layout->AddView(enable_tap_to_click_checkbox_);
- layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
- layout->StartRow(0, single_column_view_set_id());
- layout->AddView(enable_vert_edge_scroll_checkbox_);
layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
// Init member prefs so we can update the controls if prefs change.
tap_to_click_enabled_.Init(prefs::kTapToClickEnabled,
profile()->GetPrefs(), this);
- vert_edge_scroll_enabled_.Init(prefs::kVertEdgeScrollEnabled,
- profile()->GetPrefs(), this);
- speed_factor_.Init(prefs::kTouchpadSpeedFactor,
- profile()->GetPrefs(), this);
sensitivity_.Init(prefs::kTouchpadSensitivity,
profile()->GetPrefs(), this);
}
-void TouchpadSection::NotifyPrefChanged(const std::wstring* pref_name) {
+void TouchpadSection::NotifyPrefChanged(const std::string* pref_name) {
if (!pref_name || *pref_name == prefs::kTapToClickEnabled) {
bool enabled = tap_to_click_enabled_.GetValue();
enable_tap_to_click_checkbox_->SetChecked(enabled);
}
- if (!pref_name || *pref_name == prefs::kVertEdgeScrollEnabled) {
- bool enabled = vert_edge_scroll_enabled_.GetValue();
- enable_vert_edge_scroll_checkbox_->SetChecked(enabled);
- }
- if (!pref_name || *pref_name == prefs::kTouchpadSpeedFactor) {
- double value = speed_factor_.GetValue();
- speed_factor_slider_->SetValue(value);
- }
if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) {
double value = sensitivity_.GetValue();
sensitivity_slider_->SetValue(value);
@@ -349,7 +308,8 @@ void TouchpadSection::NotifyPrefChanged(const std::wstring* pref_name) {
// TextInput section for text input settings.
class LanguageSection : public SettingsPageSection,
- public views::ButtonListener {
+ public views::ButtonListener,
+ public views::Combobox::Listener {
public:
explicit LanguageSection(Profile* profile);
virtual ~LanguageSection() {}
@@ -360,28 +320,58 @@ class LanguageSection : public SettingsPageSection,
};
// Overridden from SettingsPageSection:
virtual void InitContents(GridLayout* layout);
+ void NotifyPrefChanged(const std::string* pref_name);
// Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const views::Event& event);
+ // Overridden from views::Combobox::Listener:
+ virtual void ItemChanged(views::Combobox* sender,
+ int prev_index,
+ int new_index);
+
+ IntegerPrefMember xkb_remap_search_key_pref_;
+ IntegerPrefMember xkb_remap_control_key_pref_;
+ IntegerPrefMember xkb_remap_alt_key_pref_;
+ views::Combobox* xkb_modifier_combobox_;
+ chromeos::LanguageComboboxModel<int> xkb_modifier_combobox_model_;
+
DISALLOW_COPY_AND_ASSIGN(LanguageSection);
};
LanguageSection::LanguageSection(Profile* profile)
: SettingsPageSection(profile,
- IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE) {
+ IDS_OPTIONS_SETTINGS_SECTION_TITLE_LANGUAGE),
+ xkb_modifier_combobox_(NULL),
+ xkb_modifier_combobox_model_(
+ &language_prefs::kXkbModifierMultipleChoicePrefs) {
+ xkb_remap_search_key_pref_.Init(
+ prefs::kLanguageXkbRemapSearchKeyTo, profile->GetPrefs(), this);
+ xkb_remap_control_key_pref_.Init(
+ prefs::kLanguageXkbRemapControlKeyTo, profile->GetPrefs(), this);
+ xkb_remap_alt_key_pref_.Init(
+ prefs::kLanguageXkbRemapAltKeyTo, profile->GetPrefs(), this);
}
void LanguageSection::InitContents(GridLayout* layout) {
- // Add the customize button.
- layout->StartRow(0, single_column_view_set_id());
+ // Add the customize button and XKB combobox.
+ layout->StartRow(0, double_column_view_set_id());
views::NativeButton* customize_languages_button = new views::NativeButton(
this,
l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE));
customize_languages_button->set_tag(kCustomizeLanguagesButton);
+
+ xkb_modifier_combobox_ = new views::Combobox(&xkb_modifier_combobox_model_);
+ xkb_modifier_combobox_->set_listener(this);
+
+ // Initialize the combobox to what's saved in user preferences. Otherwise,
+ // ItemChanged() will be called with |new_index| == 0.
+ NotifyPrefChanged(NULL);
+
layout->AddView(customize_languages_button, 1, 1,
GridLayout::LEADING, GridLayout::CENTER);
+ layout->AddView(xkb_modifier_combobox_);
layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
}
@@ -392,6 +382,59 @@ void LanguageSection::ButtonPressed(
}
}
+void LanguageSection::ItemChanged(views::Combobox* sender,
+ int prev_index,
+ int new_index) {
+ LOG(INFO) << "Changing XKB modofier pref to " << new_index;
+ switch (new_index) {
+ default:
+ LOG(ERROR) << "Unexpected mapping: " << new_index;
+ /* fall through */
+ case language_prefs::kNoRemap:
+ xkb_remap_search_key_pref_.SetValue(kSearchKey);
+ xkb_remap_control_key_pref_.SetValue(kLeftControlKey);
+ xkb_remap_alt_key_pref_.SetValue(kLeftAltKey);
+ break;
+ case language_prefs::kSwapCtrlAndAlt:
+ xkb_remap_search_key_pref_.SetValue(kSearchKey);
+ xkb_remap_control_key_pref_.SetValue(kLeftAltKey);
+ xkb_remap_alt_key_pref_.SetValue(kLeftControlKey);
+ break;
+ case language_prefs::kSwapSearchAndCtrl:
+ xkb_remap_search_key_pref_.SetValue(kLeftControlKey);
+ xkb_remap_control_key_pref_.SetValue(kSearchKey);
+ xkb_remap_alt_key_pref_.SetValue(kLeftAltKey);
+ break;
+ }
+}
+
+void LanguageSection::NotifyPrefChanged(const std::string* pref_name) {
+ if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
+ *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
+ *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
+ const int search_remap = xkb_remap_search_key_pref_.GetValue();
+ const int control_remap = xkb_remap_control_key_pref_.GetValue();
+ const int alt_remap = xkb_remap_alt_key_pref_.GetValue();
+ if ((search_remap == kSearchKey) &&
+ (control_remap == kLeftControlKey) &&
+ (alt_remap == kLeftAltKey)) {
+ xkb_modifier_combobox_->SetSelectedItem(language_prefs::kNoRemap);
+ } else if ((search_remap == kLeftControlKey) &&
+ (control_remap == kSearchKey) &&
+ (alt_remap == kLeftAltKey)) {
+ xkb_modifier_combobox_->SetSelectedItem(
+ language_prefs::kSwapSearchAndCtrl);
+ } else if ((search_remap == kSearchKey) &&
+ (control_remap == kLeftAltKey) &&
+ (alt_remap == kLeftControlKey)) {
+ xkb_modifier_combobox_->SetSelectedItem(language_prefs::kSwapCtrlAndAlt);
+ } else {
+ LOG(ERROR) << "Unexpected mapping. The prefs are updated by DOMUI?";
+ xkb_modifier_combobox_->SetSelectedItem(language_prefs::kNoRemap);
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// AccessibilitySection
@@ -409,7 +452,7 @@ class AccessibilitySection : public SettingsPageSection,
// Overridden from SettingsPageSection:
virtual void InitContents(GridLayout* layout);
- virtual void NotifyPrefChanged(const std::wstring* pref_name);
+ virtual void NotifyPrefChanged(const std::string* pref_name);
private:
// The View that contains the contents of the section.
@@ -454,7 +497,7 @@ void AccessibilitySection::ButtonPressed(
}
}
-void AccessibilitySection::NotifyPrefChanged(const std::wstring* pref_name) {
+void AccessibilitySection::NotifyPrefChanged(const std::string* pref_name) {
if (!pref_name || *pref_name == prefs::kAccessibilityEnabled) {
bool enabled = accessibility_enabled_.GetValue();
accessibility_checkbox_->SetChecked(enabled);
diff --git a/chrome/browser/chromeos/options/system_page_view.h b/chrome/browser/chromeos/options/system_page_view.h
index c560a61..933ff98 100644
--- a/chrome/browser/chromeos/options/system_page_view.h
+++ b/chrome/browser/chromeos/options/system_page_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_SYSTEM_PAGE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_SYSTEM_PAGE_VIEW_H_
+#pragma once
#include "chrome/browser/chromeos/options/settings_page_view.h"
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 6486672..4df5d39 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -87,6 +87,16 @@ void WifiConfigView::ContentsChanged(views::Textfield* sender,
UpdateCanLogin();
}
+bool WifiConfigView::HandleKeystroke(
+ views::Textfield* sender,
+ const views::Textfield::Keystroke& keystroke) {
+ if (sender == passphrase_textfield_ &&
+ keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
+ parent_->GetDialogClientView()->AcceptWindow();
+ }
+ return false;
+}
+
void WifiConfigView::ButtonPressed(views::Button* sender,
const views::Event& event) {
if (sender == passphrase_visible_button_) {
@@ -124,7 +134,7 @@ bool WifiConfigView::Login() {
CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
GetSSID(), GetPassphrase(),
identity_string, certificate_path_,
- autoconnect_checkbox_->checked());
+ autoconnect_checkbox_ ? autoconnect_checkbox_->checked() : true);
} else {
Save();
CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
@@ -139,10 +149,12 @@ bool WifiConfigView::Save() {
if (!other_network_) {
bool changed = false;
- bool auto_connect = autoconnect_checkbox_->checked();
- if (auto_connect != wifi_.auto_connect()) {
- wifi_.set_auto_connect(auto_connect);
- changed = true;
+ if (autoconnect_checkbox_) {
+ bool auto_connect = autoconnect_checkbox_->checked();
+ if (auto_connect != wifi_.auto_connect()) {
+ wifi_.set_auto_connect(auto_connect);
+ changed = true;
+ }
}
if (passphrase_textfield_) {
@@ -303,15 +315,34 @@ void WifiConfigView::Init() {
layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
}
+ // If there's an error, add an error message label.
+ // Right now, only displaying bad_passphrase and bad_wepkey errors.
+ if (wifi_.error() == ERROR_BAD_PASSPHRASE ||
+ wifi_.error() == ERROR_BAD_WEPKEY) {
+ layout->StartRow(0, column_view_set_id);
+ layout->SkipColumns(1);
+ int id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE;
+ if (wifi_.error() == ERROR_BAD_WEPKEY)
+ id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY;
+ views::Label* label_error = new views::Label(l10n_util::GetString(id));
+ label_error->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ label_error->SetColor(SK_ColorRED);
+ layout->AddView(label_error);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+ }
+
// Autoconnect checkbox
- autoconnect_checkbox_ = new views::Checkbox(
- l10n_util::GetString(IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
- // For other network, default to autoconnect.
- bool autoconnect = other_network_ || wifi_.auto_connect();
- autoconnect_checkbox_->SetChecked(autoconnect);
- layout->StartRow(0, column_view_set_id);
- layout->AddView(autoconnect_checkbox_, 3, 1);
- layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+ // Only show if this network is already remembered (a favorite).
+ if (wifi_.favorite()) {
+ autoconnect_checkbox_ = new views::Checkbox(l10n_util::GetString(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
+ // For other network, default to autoconnect.
+ bool autoconnect = other_network_ || wifi_.auto_connect();
+ autoconnect_checkbox_->SetChecked(autoconnect);
+ layout->StartRow(0, column_view_set_id);
+ layout->AddView(autoconnect_checkbox_, 3, 1);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+ }
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 18c0f78..43078b7 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -1,13 +1,13 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_OPTIONS_WIFI_CONFIG_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_OPTIONS_WIFI_CONFIG_VIEW_H_
+#pragma once
#include <string>
-#include "base/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/string16.h"
#include "chrome/browser/chromeos/cros/network_library.h"
@@ -19,6 +19,8 @@
#include "views/controls/textfield/textfield.h"
#include "views/view.h"
+class FilePath;
+
namespace chromeos {
class NetworkConfigView;
@@ -37,9 +39,7 @@ class WifiConfigView : public views::View,
virtual void ContentsChanged(views::Textfield* sender,
const string16& new_contents);
virtual bool HandleKeystroke(views::Textfield* sender,
- const views::Textfield::Keystroke& keystroke) {
- return false;
- }
+ const views::Textfield::Keystroke& keystroke);
// views::ButtonListener
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
diff --git a/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc b/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc
index 07e846e..4c26499 100644
--- a/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/options/wifi_config_view.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
@@ -16,11 +18,14 @@ using ::testing::_;
class WifiConfigViewTest : public CrosInProcessBrowserTest {
protected:
+ MockNetworkLibrary *mock_network_library_;
+
WifiConfigViewTest() : CrosInProcessBrowserTest() {}
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
- SetStatusAreaMocksExpectations();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->SetStatusAreaMocksExpectations();
+ mock_network_library_ = cros_mock_->mock_network_library();
}
};
@@ -34,7 +39,10 @@ IN_PROC_BROWSER_TEST_F(WifiConfigViewTest, NoChangeSaveTest) {
// Test that if autoconnect was changed, we call SaveWifiNetwork.
IN_PROC_BROWSER_TEST_F(WifiConfigViewTest, ChangeAutoConnectSaveTest) {
EXPECT_CALL(*mock_network_library_, SaveWifiNetwork(_)).Times(1);
- WifiConfigView* view = new WifiConfigView(NULL, WifiNetwork());
+ WifiNetwork remembered_network = WifiNetwork();
+ remembered_network.set_favorite(true);
+ WifiConfigView* view = new WifiConfigView(NULL, remembered_network);
+ ASSERT_TRUE(view->autoconnect_checkbox_ != NULL);
view->autoconnect_checkbox_->SetChecked(
!view->autoconnect_checkbox_->checked());
view->Save();
diff --git a/chrome/browser/chromeos/panels/panel_scroller.cc b/chrome/browser/chromeos/panels/panel_scroller.cc
index daaa3fc..a568341 100644
--- a/chrome/browser/chromeos/panels/panel_scroller.cc
+++ b/chrome/browser/chromeos/panels/panel_scroller.cc
@@ -8,9 +8,10 @@
#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
-#include "gfx/canvas.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/panels/panel_scroller_container.h"
#include "chrome/browser/chromeos/panels/panel_scroller_header.h"
+#include "gfx/canvas.h"
#include "views/widget/widget_gtk.h"
struct PanelScroller::Panel {
diff --git a/chrome/browser/chromeos/panels/panel_scroller.h b/chrome/browser/chromeos/panels/panel_scroller.h
index 51eedff..cc9befb 100644
--- a/chrome/browser/chromeos/panels/panel_scroller.h
+++ b/chrome/browser/chromeos/panels/panel_scroller.h
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 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.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_H_
#define CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_H_
+#pragma once
#include <vector>
diff --git a/chrome/browser/chromeos/panels/panel_scroller_container.h b/chrome/browser/chromeos/panels/panel_scroller_container.h
index 5007e95..76cca15 100644
--- a/chrome/browser/chromeos/panels/panel_scroller_container.h
+++ b/chrome/browser/chromeos/panels/panel_scroller_container.h
@@ -1,9 +1,10 @@
-// Copyright (c) 2009 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.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_CONTAINER_H_
#define CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_CONTAINER_H_
+#pragma once
#include "base/basictypes.h"
#include "views/view.h"
@@ -34,4 +35,3 @@ class PanelScrollerContainer : public views::View {
};
#endif // CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_CONTAINER_H_
-
diff --git a/chrome/browser/chromeos/panels/panel_scroller_header.h b/chrome/browser/chromeos/panels/panel_scroller_header.h
index 701acb5..fe4d7d4 100644
--- a/chrome/browser/chromeos/panels/panel_scroller_header.h
+++ b/chrome/browser/chromeos/panels/panel_scroller_header.h
@@ -1,11 +1,10 @@
-// Copyright (c) 2009 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.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_HEADER_H_
#define CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_HEADER_H_
-
-#include <string>
+#pragma once
#include "base/basictypes.h"
#include "base/string16.h"
@@ -18,9 +17,7 @@ class PanelScrollerHeader : public views::View {
explicit PanelScrollerHeader(PanelScroller* scroller);
virtual ~PanelScrollerHeader();
- void set_title(const string16& title) {
- title_ = title;
- }
+ void set_title(const string16& title) { title_ = title; }
// views::View overrides.
virtual bool OnMousePressed(const views::MouseEvent& event);
@@ -39,4 +36,3 @@ class PanelScrollerHeader : public views::View {
};
#endif // CHROME_BROWSER_CHROMEOS_PANELS_PANEL_SCROLLER_HEADER_H_
-
diff --git a/chrome/browser/chromeos/pipe_reader.cc b/chrome/browser/chromeos/pipe_reader.cc
index 2ed5e7c..8664e35 100644
--- a/chrome/browser/chromeos/pipe_reader.cc
+++ b/chrome/browser/chromeos/pipe_reader.cc
@@ -1,13 +1,28 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/chromeos/pipe_reader.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "base/file_path.h"
#include "base/scoped_ptr.h"
namespace chromeos {
+PipeReader::PipeReader(const FilePath& pipe_name)
+ : pipe_(NULL),
+ pipe_name_(pipe_name.value()) {
+}
+
+PipeReader::~PipeReader() {
+ if (pipe_)
+ fclose(pipe_);
+}
+
std::string PipeReader::Read(const uint32 bytes_to_read) {
scoped_array<char> buffer(new char[bytes_to_read]);
if (pipe_ || (pipe_ = fopen(pipe_name_.c_str(), "r"))) {
diff --git a/chrome/browser/chromeos/pipe_reader.h b/chrome/browser/chromeos/pipe_reader.h
index d89405d..821fe95 100644
--- a/chrome/browser/chromeos/pipe_reader.h
+++ b/chrome/browser/chromeos/pipe_reader.h
@@ -1,20 +1,19 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_CHROMEOS_PIPE_READER_H_
#define CHROME_BROWSER_CHROMEOS_PIPE_READER_H_
+#pragma once
-#include <fcntl.h>
#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <unistd.h>
#include <string>
#include "base/basictypes.h"
-#include "base/file_path.h"
+
+class FilePath;
namespace chromeos {
@@ -29,14 +28,8 @@ namespace chromeos {
class PipeReader {
public:
- explicit PipeReader(const FilePath& pipe_name)
- : pipe_(NULL),
- pipe_name_(pipe_name.value()) {
- }
- virtual ~PipeReader() {
- if (pipe_)
- fclose(pipe_);
- }
+ explicit PipeReader(const FilePath& pipe_name);
+ virtual ~PipeReader();
// Reads data from the pipe up until either a '\n' or |bytes_to_read| bytes.
virtual std::string Read(const uint32 bytes_to_read);
diff --git a/chrome/browser/chromeos/pipe_reader_unittest.cc b/chrome/browser/chromeos/pipe_reader_unittest.cc
index e745655..3646b30 100644
--- a/chrome/browser/chromeos/pipe_reader_unittest.cc
+++ b/chrome/browser/chromeos/pipe_reader_unittest.cc
@@ -1,10 +1,13 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/chromeos/pipe_reader.h"
#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "base/file_path.h"
#include "base/safe_strerror_posix.h"
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 7a993d9..6881ae9 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -1,18 +1,22 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/chromeos/preferences.h"
+#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
-#include "chrome/browser/chromeos/cros/synaptics_library.h"
+#include "chrome/browser/chromeos/cros/keyboard_library.h"
+#include "chrome/browser/chromeos/cros/touchpad_library.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/pref_member.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profile.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "unicode/timezone.h"
@@ -20,76 +24,102 @@
namespace chromeos {
static const char kFallbackInputMethodLocale[] = "en-US";
+static const char kTalkAppExtensionId[] = "ggnioahjipcehijkhpdjekioddnjoben";
+
+Preferences::Preferences(Profile* profile)
+ : profile_(profile) {
+}
// static
void Preferences::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kTapToClickEnabled, false);
prefs->RegisterBooleanPref(prefs::kLabsMediaplayerEnabled, false);
prefs->RegisterBooleanPref(prefs::kLabsAdvancedFilesystemEnabled, false);
- prefs->RegisterBooleanPref(prefs::kAccessibilityEnabled, false);
- prefs->RegisterBooleanPref(prefs::kVertEdgeScrollEnabled, false);
- prefs->RegisterIntegerPref(prefs::kTouchpadSpeedFactor, 9);
- prefs->RegisterIntegerPref(prefs::kTouchpadSensitivity, 5);
+ // Check if the accessibility pref is already registered, which can happen
+ // in WizardController::RegisterPrefs. We still want to try to register
+ // the pref here in case of Chrome/Linux with ChromeOS=1.
+ if (prefs->FindPreference(prefs::kAccessibilityEnabled) == NULL) {
+ prefs->RegisterBooleanPref(prefs::kAccessibilityEnabled, false);
+ }
+ prefs->RegisterIntegerPref(prefs::kLabsTalkEnabled, 0);
+ prefs->RegisterIntegerPref(prefs::kTouchpadSensitivity, 3);
prefs->RegisterStringPref(prefs::kLanguageCurrentInputMethod, "");
prefs->RegisterStringPref(prefs::kLanguagePreviousInputMethod, "");
prefs->RegisterStringPref(prefs::kLanguageHotkeyNextEngineInMenu,
- kHotkeyNextEngineInMenu);
+ language_prefs::kHotkeyNextEngineInMenu);
prefs->RegisterStringPref(prefs::kLanguageHotkeyPreviousEngine,
- kHotkeyPreviousEngine);
- prefs->RegisterStringPref(prefs::kLanguagePreferredLanguages, "");
+ language_prefs::kHotkeyPreviousEngine);
+ prefs->RegisterStringPref(prefs::kLanguagePreferredLanguages,
+ kFallbackInputMethodLocale);
prefs->RegisterStringPref(prefs::kLanguagePreloadEngines,
kFallbackInputMethodId); // EN layout
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
- prefs->RegisterBooleanPref(kChewingBooleanPrefs[i].pref_name,
- kChewingBooleanPrefs[i].default_pref_value);
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
+ prefs->RegisterBooleanPref(
+ language_prefs::kChewingBooleanPrefs[i].pref_name,
+ language_prefs::kChewingBooleanPrefs[i].default_pref_value);
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
prefs->RegisterStringPref(
- kChewingMultipleChoicePrefs[i].pref_name,
- kChewingMultipleChoicePrefs[i].default_pref_value);
+ language_prefs::kChewingMultipleChoicePrefs[i].pref_name,
+ language_prefs::kChewingMultipleChoicePrefs[i].default_pref_value);
}
- prefs->RegisterIntegerPref(kChewingHsuSelKeyType.pref_name,
- kChewingHsuSelKeyType.default_pref_value);
+ prefs->RegisterIntegerPref(
+ language_prefs::kChewingHsuSelKeyType.pref_name,
+ language_prefs::kChewingHsuSelKeyType.default_pref_value);
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
- prefs->RegisterIntegerPref(kChewingIntegerPrefs[i].pref_name,
- kChewingIntegerPrefs[i].default_pref_value);
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
+ prefs->RegisterIntegerPref(
+ language_prefs::kChewingIntegerPrefs[i].pref_name,
+ language_prefs::kChewingIntegerPrefs[i].default_pref_value);
}
prefs->RegisterStringPref(
prefs::kLanguageHangulKeyboard,
- kHangulKeyboardNameIDPairs[0].keyboard_id);
- prefs->RegisterStringPref(prefs::kLanguageHangulHanjaKeys, kHangulHanjaKeys);
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
- prefs->RegisterBooleanPref(kPinyinBooleanPrefs[i].pref_name,
- kPinyinBooleanPrefs[i].default_pref_value);
- }
- for (size_t i = 0; i < kNumPinyinIntegerPrefs; ++i) {
- prefs->RegisterIntegerPref(kPinyinIntegerPrefs[i].pref_name,
- kPinyinIntegerPrefs[i].default_pref_value);
- }
- prefs->RegisterIntegerPref(kPinyinDoublePinyinSchema.pref_name,
- kPinyinDoublePinyinSchema.default_pref_value);
+ language_prefs::kHangulKeyboardNameIDPairs[0].keyboard_id);
+ prefs->RegisterStringPref(prefs::kLanguageHangulHanjaKeys,
+ language_prefs::kHangulHanjaKeys);
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
+ prefs->RegisterBooleanPref(
+ language_prefs::kPinyinBooleanPrefs[i].pref_name,
+ language_prefs::kPinyinBooleanPrefs[i].default_pref_value);
+ }
+ for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
+ prefs->RegisterIntegerPref(
+ language_prefs::kPinyinIntegerPrefs[i].pref_name,
+ language_prefs::kPinyinIntegerPrefs[i].default_pref_value);
+ }
+ prefs->RegisterIntegerPref(
+ language_prefs::kPinyinDoublePinyinSchema.pref_name,
+ language_prefs::kPinyinDoublePinyinSchema.default_pref_value);
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
- prefs->RegisterBooleanPref(kMozcBooleanPrefs[i].pref_name,
- kMozcBooleanPrefs[i].default_pref_value);
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
+ prefs->RegisterBooleanPref(
+ language_prefs::kMozcBooleanPrefs[i].pref_name,
+ language_prefs::kMozcBooleanPrefs[i].default_pref_value);
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
prefs->RegisterStringPref(
- kMozcMultipleChoicePrefs[i].pref_name,
- kMozcMultipleChoicePrefs[i].default_pref_value);
- }
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
- prefs->RegisterIntegerPref(kMozcIntegerPrefs[i].pref_name,
- kMozcIntegerPrefs[i].default_pref_value);
- }
+ language_prefs::kMozcMultipleChoicePrefs[i].pref_name,
+ language_prefs::kMozcMultipleChoicePrefs[i].default_pref_value);
+ }
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
+ prefs->RegisterIntegerPref(
+ language_prefs::kMozcIntegerPrefs[i].pref_name,
+ language_prefs::kMozcIntegerPrefs[i].default_pref_value);
+ }
+ prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapSearchKeyTo, kSearchKey);
+ prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapControlKeyTo,
+ kLeftControlKey);
+ prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapAltKeyTo, kLeftAltKey);
+ prefs->RegisterBooleanPref(prefs::kLanguageXkbAutoRepeatEnabled, true);
+ prefs->RegisterIntegerPref(prefs::kLanguageXkbAutoRepeatDelay,
+ language_prefs::kXkbAutoRepeatDelayInMs);
+ prefs->RegisterIntegerPref(prefs::kLanguageXkbAutoRepeatInterval,
+ language_prefs::kXkbAutoRepeatIntervalInMs);
}
void Preferences::Init(PrefService* prefs) {
tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, prefs, this);
accessibility_enabled_.Init(prefs::kAccessibilityEnabled, prefs, this);
- vert_edge_scroll_enabled_.Init(prefs::kVertEdgeScrollEnabled, prefs, this);
- speed_factor_.Init(prefs::kTouchpadSpeedFactor, prefs, this);
sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, this);
language_hotkey_next_engine_in_menu_.Init(
prefs::kLanguageHotkeyNextEngineInMenu, prefs, this);
@@ -98,68 +128,59 @@ void Preferences::Init(PrefService* prefs) {
language_preferred_languages_.Init(prefs::kLanguagePreferredLanguages,
prefs, this);
language_preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, this);
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
language_chewing_boolean_prefs_[i].Init(
- kChewingBooleanPrefs[i].pref_name, prefs, this);
+ language_prefs::kChewingBooleanPrefs[i].pref_name, prefs, this);
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
language_chewing_multiple_choice_prefs_[i].Init(
- kChewingMultipleChoicePrefs[i].pref_name, prefs, this);
+ language_prefs::kChewingMultipleChoicePrefs[i].pref_name, prefs, this);
}
language_chewing_hsu_sel_key_type_.Init(
- kChewingHsuSelKeyType.pref_name, prefs, this);
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
+ language_prefs::kChewingHsuSelKeyType.pref_name, prefs, this);
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
language_chewing_integer_prefs_[i].Init(
- kChewingIntegerPrefs[i].pref_name, prefs, this);
+ language_prefs::kChewingIntegerPrefs[i].pref_name, prefs, this);
}
language_hangul_keyboard_.Init(prefs::kLanguageHangulKeyboard, prefs, this);
language_hangul_hanja_keys_.Init(
prefs::kLanguageHangulHanjaKeys, prefs, this);
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
language_pinyin_boolean_prefs_[i].Init(
- kPinyinBooleanPrefs[i].pref_name, prefs, this);
+ language_prefs::kPinyinBooleanPrefs[i].pref_name, prefs, this);
}
- for (size_t i = 0; i < kNumPinyinIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
language_pinyin_int_prefs_[i].Init(
- kPinyinIntegerPrefs[i].pref_name, prefs, this);
+ language_prefs::kPinyinIntegerPrefs[i].pref_name, prefs, this);
}
language_pinyin_double_pinyin_schema_.Init(
- kPinyinDoublePinyinSchema.pref_name, prefs, this);
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
+ language_prefs::kPinyinDoublePinyinSchema.pref_name, prefs, this);
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
language_mozc_boolean_prefs_[i].Init(
- kMozcBooleanPrefs[i].pref_name, prefs, this);
+ language_prefs::kMozcBooleanPrefs[i].pref_name, prefs, this);
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
language_mozc_multiple_choice_prefs_[i].Init(
- kMozcMultipleChoicePrefs[i].pref_name, prefs, this);
+ language_prefs::kMozcMultipleChoicePrefs[i].pref_name, prefs, this);
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
language_mozc_integer_prefs_[i].Init(
- kMozcIntegerPrefs[i].pref_name, prefs, this);
- }
+ language_prefs::kMozcIntegerPrefs[i].pref_name, prefs, this);
+ }
+ language_xkb_remap_search_key_to_.Init(
+ prefs::kLanguageXkbRemapSearchKeyTo, prefs, this);
+ language_xkb_remap_control_key_to_.Init(
+ prefs::kLanguageXkbRemapControlKeyTo, prefs, this);
+ language_xkb_remap_alt_key_to_.Init(
+ prefs::kLanguageXkbRemapAltKeyTo, prefs, this);
+ language_xkb_auto_repeat_enabled_.Init(
+ prefs::kLanguageXkbAutoRepeatEnabled, prefs, this);
+ language_xkb_auto_repeat_delay_pref_.Init(
+ prefs::kLanguageXkbAutoRepeatDelay, prefs, this);
+ language_xkb_auto_repeat_interval_pref_.Init(
+ prefs::kLanguageXkbAutoRepeatInterval, prefs, this);
- std::string locale(g_browser_process->GetApplicationLocale());
- // Add input methods based on the application locale when the user first
- // logs in. For instance, if the user chooses Japanese as the UI
- // language at the first login, we'll add input methods associated with
- // Japanese, such as mozc.
- if (locale != kFallbackInputMethodLocale &&
- !prefs->HasPrefPath(prefs::kLanguagePreloadEngines)) {
- std::string preload_engines(language_preload_engines_.GetValue());
- std::vector<std::string> input_method_ids;
- input_method::GetInputMethodIdsFromLanguageCode(
- locale, input_method::kAllInputMethods, &input_method_ids);
- if (!input_method_ids.empty()) {
- if (!preload_engines.empty())
- preload_engines += ',';
- preload_engines += JoinString(input_method_ids, ',');
- }
- language_preload_engines_.SetValue(preload_engines);
- }
- // Add the UI language to the preferred languages the user first logs in.
- if (!prefs->HasPrefPath(prefs::kLanguagePreferredLanguages)) {
- language_preferred_languages_.SetValue(locale);
- }
+ labs_talk_enabled_.Init(prefs::kLabsTalkEnabled, prefs, this);
// Initialize touchpad settings to what's saved in user preferences.
NotifyPrefChanged(NULL);
@@ -169,29 +190,17 @@ void Preferences::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
if (type == NotificationType::PREF_CHANGED)
- NotifyPrefChanged(Details<std::wstring>(details).ptr());
+ NotifyPrefChanged(Details<std::string>(details).ptr());
}
-void Preferences::NotifyPrefChanged(const std::wstring* pref_name) {
+void Preferences::NotifyPrefChanged(const std::string* pref_name) {
if (!pref_name || *pref_name == prefs::kTapToClickEnabled) {
- CrosLibrary::Get()->GetSynapticsLibrary()->SetBoolParameter(
- PARAM_BOOL_TAP_TO_CLICK,
+ CrosLibrary::Get()->GetTouchpadLibrary()->SetTapToClick(
tap_to_click_enabled_.GetValue());
}
- if (!pref_name || *pref_name == prefs::kVertEdgeScrollEnabled) {
- CrosLibrary::Get()->GetSynapticsLibrary()->SetBoolParameter(
- PARAM_BOOL_VERTICAL_EDGE_SCROLLING,
- vert_edge_scroll_enabled_.GetValue());
- }
- if (!pref_name || *pref_name == prefs::kTouchpadSpeedFactor) {
- CrosLibrary::Get()->GetSynapticsLibrary()->SetRangeParameter(
- PARAM_RANGE_SPEED_SENSITIVITY,
- speed_factor_.GetValue());
- }
if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) {
- CrosLibrary::Get()->GetSynapticsLibrary()->SetRangeParameter(
- PARAM_RANGE_TOUCH_SENSITIVITY,
- sensitivity_.GetValue());
+ CrosLibrary::Get()->GetTouchpadLibrary()->SetSensitivity(
+ sensitivity_.GetValue());
}
// We don't handle prefs::kLanguageCurrentInputMethod and PreviousInputMethod
@@ -199,14 +208,14 @@ void Preferences::NotifyPrefChanged(const std::wstring* pref_name) {
if (!pref_name || *pref_name == prefs::kLanguageHotkeyNextEngineInMenu) {
SetLanguageConfigStringListAsCSV(
- kHotKeySectionName,
- kNextEngineInMenuConfigName,
+ language_prefs::kHotKeySectionName,
+ language_prefs::kNextEngineInMenuConfigName,
language_hotkey_next_engine_in_menu_.GetValue());
}
if (!pref_name || *pref_name == prefs::kLanguageHotkeyPreviousEngine) {
SetLanguageConfigStringListAsCSV(
- kHotKeySectionName,
- kPreviousEngineConfigName,
+ language_prefs::kHotKeySectionName,
+ language_prefs::kPreviousEngineConfigName,
language_hotkey_previous_engine_.GetValue());
}
if (!pref_name || *pref_name == prefs::kLanguagePreferredLanguages) {
@@ -214,88 +223,126 @@ void Preferences::NotifyPrefChanged(const std::wstring* pref_name) {
// preferencs, we don't need to send this to ibus-daemon.
}
if (!pref_name || *pref_name == prefs::kLanguagePreloadEngines) {
- SetLanguageConfigStringListAsCSV(kGeneralSectionName,
- kPreloadEnginesConfigName,
+ SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName,
+ language_prefs::kPreloadEnginesConfigName,
language_preload_engines_.GetValue());
}
- for (size_t i = 0; i < kNumChewingBooleanPrefs; ++i) {
- if (!pref_name || *pref_name == kChewingBooleanPrefs[i].pref_name) {
- SetLanguageConfigBoolean(kChewingSectionName,
- kChewingBooleanPrefs[i].ibus_config_name,
- language_chewing_boolean_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kChewingBooleanPrefs[i].pref_name) {
+ SetLanguageConfigBoolean(
+ language_prefs::kChewingSectionName,
+ language_prefs::kChewingBooleanPrefs[i].ibus_config_name,
+ language_chewing_boolean_prefs_[i].GetValue());
}
}
- for (size_t i = 0; i < kNumChewingMultipleChoicePrefs; ++i) {
- if (!pref_name || *pref_name == kChewingMultipleChoicePrefs[i].pref_name) {
+ for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
+ if (!pref_name ||
+ *pref_name ==
+ language_prefs::kChewingMultipleChoicePrefs[i].pref_name) {
SetLanguageConfigString(
- kChewingSectionName,
- kChewingMultipleChoicePrefs[i].ibus_config_name,
+ language_prefs::kChewingSectionName,
+ language_prefs::kChewingMultipleChoicePrefs[i].ibus_config_name,
language_chewing_multiple_choice_prefs_[i].GetValue());
}
}
- if (!pref_name || *pref_name == kChewingHsuSelKeyType.pref_name) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kChewingHsuSelKeyType.pref_name) {
SetLanguageConfigInteger(
- kChewingSectionName,
- kChewingHsuSelKeyType.ibus_config_name,
+ language_prefs::kChewingSectionName,
+ language_prefs::kChewingHsuSelKeyType.ibus_config_name,
language_chewing_hsu_sel_key_type_.GetValue());
}
- for (size_t i = 0; i < kNumChewingIntegerPrefs; ++i) {
- if (!pref_name || *pref_name == kChewingIntegerPrefs[i].pref_name) {
- SetLanguageConfigInteger(kChewingSectionName,
- kChewingIntegerPrefs[i].ibus_config_name,
- language_chewing_integer_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kChewingIntegerPrefs[i].pref_name) {
+ SetLanguageConfigInteger(
+ language_prefs::kChewingSectionName,
+ language_prefs::kChewingIntegerPrefs[i].ibus_config_name,
+ language_chewing_integer_prefs_[i].GetValue());
}
}
- if (!pref_name || *pref_name == prefs::kLanguageHangulKeyboard) {
- SetLanguageConfigString(kHangulSectionName, kHangulKeyboardConfigName,
+ if (!pref_name ||
+ *pref_name == prefs::kLanguageHangulKeyboard) {
+ SetLanguageConfigString(language_prefs::kHangulSectionName,
+ language_prefs::kHangulKeyboardConfigName,
language_hangul_keyboard_.GetValue());
}
if (!pref_name || *pref_name == prefs::kLanguageHangulHanjaKeys) {
- SetLanguageConfigString(kHangulSectionName, kHangulHanjaKeysConfigName,
+ SetLanguageConfigString(language_prefs::kHangulSectionName,
+ language_prefs::kHangulHanjaKeysConfigName,
language_hangul_hanja_keys_.GetValue());
}
- for (size_t i = 0; i < kNumPinyinBooleanPrefs; ++i) {
- if (!pref_name || *pref_name == kPinyinBooleanPrefs[i].pref_name) {
- SetLanguageConfigBoolean(kPinyinSectionName,
- kPinyinBooleanPrefs[i].ibus_config_name,
- language_pinyin_boolean_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kPinyinBooleanPrefs[i].pref_name) {
+ SetLanguageConfigBoolean(
+ language_prefs::kPinyinSectionName,
+ language_prefs::kPinyinBooleanPrefs[i].ibus_config_name,
+ language_pinyin_boolean_prefs_[i].GetValue());
}
}
- for (size_t i = 0; i < kNumPinyinIntegerPrefs; ++i) {
- if (!pref_name || *pref_name == kPinyinIntegerPrefs[i].pref_name) {
- SetLanguageConfigInteger(kPinyinSectionName,
- kPinyinIntegerPrefs[i].ibus_config_name,
- language_pinyin_int_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kPinyinIntegerPrefs[i].pref_name) {
+ SetLanguageConfigInteger(
+ language_prefs::kPinyinSectionName,
+ language_prefs::kPinyinIntegerPrefs[i].ibus_config_name,
+ language_pinyin_int_prefs_[i].GetValue());
}
}
- if (!pref_name || *pref_name == kPinyinDoublePinyinSchema.pref_name) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kPinyinDoublePinyinSchema.pref_name) {
SetLanguageConfigInteger(
- kPinyinSectionName,
- kPinyinDoublePinyinSchema.ibus_config_name,
+ language_prefs::kPinyinSectionName,
+ language_prefs::kPinyinDoublePinyinSchema.ibus_config_name,
language_pinyin_double_pinyin_schema_.GetValue());
}
- for (size_t i = 0; i < kNumMozcBooleanPrefs; ++i) {
- if (!pref_name || *pref_name == kMozcBooleanPrefs[i].pref_name) {
- SetLanguageConfigBoolean(kMozcSectionName,
- kMozcBooleanPrefs[i].ibus_config_name,
- language_mozc_boolean_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kMozcBooleanPrefs[i].pref_name) {
+ SetLanguageConfigBoolean(
+ language_prefs::kMozcSectionName,
+ language_prefs::kMozcBooleanPrefs[i].ibus_config_name,
+ language_mozc_boolean_prefs_[i].GetValue());
}
}
- for (size_t i = 0; i < kNumMozcMultipleChoicePrefs; ++i) {
- if (!pref_name || *pref_name == kMozcMultipleChoicePrefs[i].pref_name) {
+ for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kMozcMultipleChoicePrefs[i].pref_name) {
SetLanguageConfigString(
- kMozcSectionName,
- kMozcMultipleChoicePrefs[i].ibus_config_name,
+ language_prefs::kMozcSectionName,
+ language_prefs::kMozcMultipleChoicePrefs[i].ibus_config_name,
language_mozc_multiple_choice_prefs_[i].GetValue());
}
}
- for (size_t i = 0; i < kNumMozcIntegerPrefs; ++i) {
- if (!pref_name || *pref_name == kMozcIntegerPrefs[i].pref_name) {
- SetLanguageConfigInteger(kMozcSectionName,
- kMozcIntegerPrefs[i].ibus_config_name,
- language_mozc_integer_prefs_[i].GetValue());
+ for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
+ if (!pref_name ||
+ *pref_name == language_prefs::kMozcIntegerPrefs[i].pref_name) {
+ SetLanguageConfigInteger(
+ language_prefs::kMozcSectionName,
+ language_prefs::kMozcIntegerPrefs[i].ibus_config_name,
+ language_mozc_integer_prefs_[i].GetValue());
}
}
+ if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
+ *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
+ *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
+ UpdateModifierKeyMapping();
+ }
+ if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) {
+ const bool enabled = language_xkb_auto_repeat_enabled_.GetValue();
+ CrosLibrary::Get()->GetKeyboardLibrary()->SetAutoRepeatEnabled(enabled);
+ }
+ if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) ||
+ (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) {
+ UpdateAutoRepeatRate();
+ }
+
+ // Listen for explicit changes as ExtensionsService handles startup case.
+ if (pref_name && *pref_name == prefs::kLabsTalkEnabled) {
+ UpdateTalkApp();
+ }
}
void Preferences::SetLanguageConfigBoolean(const char* section,
@@ -355,4 +402,48 @@ void Preferences::SetLanguageConfigStringListAsCSV(const char* section,
SetLanguageConfigStringList(section, name, split_values);
}
+void Preferences::UpdateModifierKeyMapping() {
+ const int search_remap = language_xkb_remap_search_key_to_.GetValue();
+ const int control_remap = language_xkb_remap_control_key_to_.GetValue();
+ const int alt_remap = language_xkb_remap_alt_key_to_.GetValue();
+ if ((search_remap < kNumModifierKeys) && (search_remap >= 0) &&
+ (control_remap < kNumModifierKeys) && (control_remap >= 0) &&
+ (alt_remap < kNumModifierKeys) && (alt_remap >= 0)) {
+ chromeos::ModifierMap modifier_map;
+ modifier_map.push_back(
+ ModifierKeyPair(kSearchKey, ModifierKey(search_remap)));
+ modifier_map.push_back(
+ ModifierKeyPair(kLeftControlKey, ModifierKey(control_remap)));
+ modifier_map.push_back(
+ ModifierKeyPair(kLeftAltKey, ModifierKey(alt_remap)));
+ CrosLibrary::Get()->GetKeyboardLibrary()->RemapModifierKeys(modifier_map);
+ } else {
+ LOG(ERROR) << "Failed to remap modifier keys. Unexpected value(s): "
+ << search_remap << ", " << control_remap << ", " << alt_remap;
+ }
+}
+
+void Preferences::UpdateAutoRepeatRate() {
+ AutoRepeatRate rate;
+ rate.initial_delay_in_ms = language_xkb_auto_repeat_delay_pref_.GetValue();
+ rate.repeat_interval_in_ms =
+ language_xkb_auto_repeat_interval_pref_.GetValue();
+ DCHECK(rate.initial_delay_in_ms > 0);
+ DCHECK(rate.repeat_interval_in_ms > 0);
+ CrosLibrary::Get()->GetKeyboardLibrary()->SetAutoRepeatRate(rate);
+}
+
+void Preferences::UpdateTalkApp() {
+ if (!profile_->GetExtensionsService()->is_ready()) {
+ NOTREACHED() << "Extensions service should be ready";
+ return;
+ }
+
+ if (labs_talk_enabled_.GetValue() == 0) {
+ profile_->GetExtensionsService()->DisableExtension(kTalkAppExtensionId);
+ } else {
+ profile_->GetExtensionsService()->EnableExtension(kTalkAppExtensionId);
+ }
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/preferences.h b/chrome/browser/chromeos/preferences.h
index a9a2250..2226a3a 100644
--- a/chrome/browser/chromeos/preferences.h
+++ b/chrome/browser/chromeos/preferences.h
@@ -4,15 +4,17 @@
#ifndef CHROME_BROWSER_CHROMEOS_PREFERENCES_H_
#define CHROME_BROWSER_CHROMEOS_PREFERENCES_H_
+#pragma once
#include <string>
#include <vector>
#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/common/notification_observer.h"
class PrefService;
+class Profile;
namespace chromeos {
@@ -22,7 +24,7 @@ namespace chromeos {
// When the preferences change, we change the settings to reflect the new value.
class Preferences : public NotificationObserver {
public:
- Preferences() {}
+ explicit Preferences(Profile* profile);
virtual ~Preferences() {}
// This method will register the prefs associated with Chrome OS settings.
@@ -36,13 +38,12 @@ class Preferences : public NotificationObserver {
const NotificationSource& source,
const NotificationDetails& details);
- protected:
+ private:
// This will set the OS settings when the preference changes.
// If this method is called with NULL, it will set all OS settings to what's
// stored in the preferences.
- virtual void NotifyPrefChanged(const std::wstring* pref_name);
+ void NotifyPrefChanged(const std::string* pref_name);
- private:
// Writes boolean |value| to the input method (IBus) configuration daemon.
// |section| (e.g. "general") and |name| (e.g. "use_global_engine") should
// not be NULL.
@@ -74,6 +75,19 @@ class Preferences : public NotificationObserver {
const char* name,
const std::string& value);
+ // Updates the mapping of modifier keys following current prefs values.
+ void UpdateModifierKeyMapping();
+
+ // Updates the initial key repeat delay and key repeat interval following
+ // current prefs values. We set the delay and interval at once since an
+ // underlying XKB API requires it.
+ void UpdateAutoRepeatRate();
+
+ // Updates whether the Talk app is enabled.
+ void UpdateTalkApp();
+
+ Profile* profile_;
+
BooleanPrefMember tap_to_click_enabled_;
BooleanPrefMember vert_edge_scroll_enabled_;
BooleanPrefMember accessibility_enabled_;
@@ -85,20 +99,35 @@ class Preferences : public NotificationObserver {
StringPrefMember language_hotkey_previous_engine_;
StringPrefMember language_preferred_languages_;
StringPrefMember language_preload_engines_;
- BooleanPrefMember language_chewing_boolean_prefs_[kNumChewingBooleanPrefs];
+ BooleanPrefMember language_chewing_boolean_prefs_[
+ language_prefs::kNumChewingBooleanPrefs];
StringPrefMember language_chewing_multiple_choice_prefs_[
- kNumChewingMultipleChoicePrefs];
+ language_prefs::kNumChewingMultipleChoicePrefs];
IntegerPrefMember language_chewing_hsu_sel_key_type_;
- IntegerPrefMember language_chewing_integer_prefs_[kNumChewingIntegerPrefs];
+ IntegerPrefMember language_chewing_integer_prefs_[
+ language_prefs::kNumChewingIntegerPrefs];
StringPrefMember language_hangul_keyboard_;
StringPrefMember language_hangul_hanja_keys_;
- BooleanPrefMember language_pinyin_boolean_prefs_[kNumPinyinBooleanPrefs];
- IntegerPrefMember language_pinyin_int_prefs_[kNumPinyinIntegerPrefs];
+ BooleanPrefMember language_pinyin_boolean_prefs_[
+ language_prefs::kNumPinyinBooleanPrefs];
+ IntegerPrefMember language_pinyin_int_prefs_[
+ language_prefs::kNumPinyinIntegerPrefs];
IntegerPrefMember language_pinyin_double_pinyin_schema_;
- BooleanPrefMember language_mozc_boolean_prefs_[kNumMozcBooleanPrefs];
+ BooleanPrefMember language_mozc_boolean_prefs_[
+ language_prefs::kNumMozcBooleanPrefs];
StringPrefMember language_mozc_multiple_choice_prefs_[
- kNumMozcMultipleChoicePrefs];
- IntegerPrefMember language_mozc_integer_prefs_[kNumMozcIntegerPrefs];
+ language_prefs::kNumMozcMultipleChoicePrefs];
+ IntegerPrefMember language_mozc_integer_prefs_[
+ language_prefs::kNumMozcIntegerPrefs];
+ IntegerPrefMember language_xkb_remap_search_key_to_;
+ IntegerPrefMember language_xkb_remap_control_key_to_;
+ IntegerPrefMember language_xkb_remap_alt_key_to_;
+ BooleanPrefMember language_xkb_auto_repeat_enabled_;
+ IntegerPrefMember language_xkb_auto_repeat_delay_pref_;
+ IntegerPrefMember language_xkb_auto_repeat_interval_pref_;
+
+ // Labs preferences.
+ IntegerPrefMember labs_talk_enabled_;
DISALLOW_COPY_AND_ASSIGN(Preferences);
};
diff --git a/chrome/browser/chromeos/pulse_audio_mixer.cc b/chrome/browser/chromeos/pulse_audio_mixer.cc
index a091c8c..7cc4d3e 100644
--- a/chrome/browser/chromeos/pulse_audio_mixer.cc
+++ b/chrome/browser/chromeos/pulse_audio_mixer.cc
@@ -21,8 +21,6 @@ namespace chromeos {
// synchronously get the value back.
//
// TODO(davej): Serialize volume/mute to preserve settings when restarting?
-// TODO(davej): Check if we need some thread safety mechanism (will someone be
-// calling GetVolume while another process is calling SetVolume?)
namespace {
@@ -30,14 +28,15 @@ const int kInvalidDeviceId = -1;
// Used for passing custom data to the PulseAudio callbacks.
struct CallbackWrapper {
- pa_threaded_mainloop* mainloop;
- void* data;
+ PulseAudioMixer* instance;
+ bool done;
+ void* userdata;
};
} // namespace
// AudioInfo contains all the values we care about when getting info for a
-// Sink (output device) used by GetAudioInfo()
+// Sink (output device) used by GetAudioInfo().
struct PulseAudioMixer::AudioInfo {
pa_cvolume cvolume;
bool muted;
@@ -46,6 +45,8 @@ struct PulseAudioMixer::AudioInfo {
PulseAudioMixer::PulseAudioMixer()
: device_id_(kInvalidDeviceId),
last_channels_(0),
+ mainloop_lock_count_(0),
+ mixer_state_lock_(),
mixer_state_(UNINITIALIZED),
pa_context_(NULL),
pa_mainloop_(NULL),
@@ -55,48 +56,48 @@ PulseAudioMixer::PulseAudioMixer()
PulseAudioMixer::~PulseAudioMixer() {
PulseAudioFree();
thread_->Stop();
+ thread_.reset();
}
bool PulseAudioMixer::Init(InitDoneCallback* callback) {
- // Just start up worker thread, then post the task of starting up, which can
- // block for 200-500ms, so best not to do it on this thread.
- if (mixer_state_ != UNINITIALIZED)
+ if (!InitThread())
return false;
- mixer_state_ = INITIALIZING;
- if (thread_ == NULL) {
- thread_.reset(new base::Thread("PulseAudioMixer"));
- if (!thread_->Start()) {
- thread_.reset();
- return false;
- }
- }
+ // Post the task of starting up, which can block for 200-500ms,
+ // so best not to do it on the caller's thread.
thread_->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &PulseAudioMixer::DoInit,
- callback));
+ NewRunnableMethod(this, &PulseAudioMixer::DoInit, callback));
return true;
}
+bool PulseAudioMixer::InitSync() {
+ if (!InitThread())
+ return false;
+ return PulseAudioInit();
+}
+
double PulseAudioMixer::GetVolumeDb() const {
- if (!PulseAudioValid())
- return pa_sw_volume_to_dB(0); // this returns -inf
+ if (!MainloopLockIfReady())
+ return pa_sw_volume_to_dB(0); // this returns -inf.
AudioInfo data;
GetAudioInfo(&data);
+ MainloopUnlock();
return pa_sw_volume_to_dB(data.cvolume.values[0]);
}
-void PulseAudioMixer::GetVolumeDbAsync(GetVolumeCallback* callback,
+bool PulseAudioMixer::GetVolumeDbAsync(GetVolumeCallback* callback,
void* user) {
- if (!PulseAudioValid())
- return;
+ if (CheckState() != READY)
+ return false;
thread_->message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(this,
&PulseAudioMixer::DoGetVolume,
callback, user));
+ return true;
}
void PulseAudioMixer::SetVolumeDb(double vol_db) {
- if (!PulseAudioValid())
+ if (!MainloopLockIfReady())
return;
// last_channels_ determines the number of channels on the main output device,
@@ -110,40 +111,38 @@ void PulseAudioMixer::SetVolumeDb(double vol_db) {
pa_operation* pa_op;
pa_cvolume cvolume;
pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db));
- pa_threaded_mainloop_lock(pa_mainloop_);
pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_,
&cvolume, NULL, NULL);
pa_operation_unref(pa_op);
- pa_threaded_mainloop_unlock(pa_mainloop_);
+ MainloopUnlock();
}
bool PulseAudioMixer::IsMute() const {
- if (!PulseAudioValid())
+ if (!MainloopLockIfReady())
return false;
AudioInfo data;
GetAudioInfo(&data);
+ MainloopUnlock();
return data.muted;
}
void PulseAudioMixer::SetMute(bool mute) {
- if (!PulseAudioValid())
+ if (!MainloopLockIfReady())
return;
pa_operation* pa_op;
- pa_threaded_mainloop_lock(pa_mainloop_);
pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_,
mute ? 1 : 0, NULL, NULL);
pa_operation_unref(pa_op);
- pa_threaded_mainloop_unlock(pa_mainloop_);
+ MainloopUnlock();
}
-bool PulseAudioMixer::IsValid() const {
- if (mixer_state_ == READY)
- return true;
- if (!pa_context_)
- return false;
- if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY)
- return false;
- return true;
+PulseAudioMixer::State PulseAudioMixer::CheckState() const {
+ AutoLock lock(mixer_state_lock_);
+ // If we think it's ready, verify it is actually so.
+ if ((mixer_state_ == READY) &&
+ (pa_context_get_state(pa_context_) != PA_CONTEXT_READY))
+ mixer_state_ = IN_ERROR;
+ return mixer_state_;
}
////////////////////////////////////////////////////////////////////////////////
@@ -161,17 +160,23 @@ void PulseAudioMixer::DoGetVolume(GetVolumeCallback* callback,
delete callback;
}
-struct ConnectToPulseCallbackData {
- PulseAudioMixer* instance;
- bool connect_done;
-};
+bool PulseAudioMixer::InitThread() {
+ if (thread_ == NULL) {
+ thread_.reset(new base::Thread("PulseAudioMixer"));
+ if (!thread_->Start()) {
+ thread_.reset();
+ return false;
+ }
+ }
+ return true;
+}
// static
void PulseAudioMixer::ConnectToPulseCallbackThunk(
pa_context* context, void* userdata) {
- ConnectToPulseCallbackData* data =
- static_cast<ConnectToPulseCallbackData*>(userdata);
- data->instance->OnConnectToPulseCallback(context, &data->connect_done);
+ CallbackWrapper* data =
+ static_cast<CallbackWrapper*>(userdata);
+ data->instance->OnConnectToPulseCallback(context, &data->done);
}
void PulseAudioMixer::OnConnectToPulseCallback(
@@ -182,13 +187,20 @@ void PulseAudioMixer::OnConnectToPulseCallback(
state == PA_CONTEXT_TERMINATED) {
// Connection process has reached a terminal state. Wake PulseAudioInit().
*connect_done = true;
- pa_threaded_mainloop_signal(pa_mainloop_, 0);
+ MainloopSignal();
}
}
bool PulseAudioMixer::PulseAudioInit() {
pa_context_state_t state = PA_CONTEXT_FAILED;
+ {
+ AutoLock lock(mixer_state_lock_);
+ if (mixer_state_ != UNINITIALIZED)
+ return false;
+ mixer_state_ = INITIALIZING;
+ }
+
while (true) {
// Create connection to default server.
pa_mainloop_ = pa_threaded_mainloop_new();
@@ -202,7 +214,8 @@ bool PulseAudioMixer::PulseAudioInit() {
break;
}
- pa_threaded_mainloop_lock(pa_mainloop_);
+ if (!MainloopSafeLock())
+ return false;
while (true) {
pa_mainloop_api* pa_mlapi = pa_threaded_mainloop_get_api(pa_mainloop_);
@@ -217,10 +230,11 @@ bool PulseAudioMixer::PulseAudioInit() {
break;
}
- ConnectToPulseCallbackData data;
- data.instance = this;
- data.connect_done = false;
+ MainloopUnlock();
+ if (!MainloopSafeLock())
+ return false;
+ CallbackWrapper data = {this, false, NULL};
pa_context_set_state_callback(pa_context_,
&ConnectToPulseCallbackThunk,
&data);
@@ -231,13 +245,13 @@ bool PulseAudioMixer::PulseAudioInit() {
} else {
// Wait until we have a completed connection or fail.
do {
- pa_threaded_mainloop_wait(pa_mainloop_);
- } while (!data.connect_done);
+ MainloopWait();
+ } while (!data.done);
state = pa_context_get_state(pa_context_);
if (state == PA_CONTEXT_FAILED) {
- LOG(ERROR) << "PulseAudio context connection failed";
+ LOG(ERROR) << "PulseAudio connection failed (daemon not running?)";
} else if (state == PA_CONTEXT_TERMINATED) {
LOG(ERROR) << "PulseAudio connection terminated early";
} else if (state != PA_CONTEXT_READY) {
@@ -249,15 +263,20 @@ bool PulseAudioMixer::PulseAudioInit() {
break;
}
- pa_threaded_mainloop_unlock(pa_mainloop_);
+ MainloopUnlock();
if (state != PA_CONTEXT_READY)
break;
- last_channels_ = 0;
+ if (!MainloopSafeLock())
+ return false;
GetDefaultPlaybackDevice();
- mixer_state_ = READY;
+ MainloopUnlock();
+ if (device_id_ == kInvalidDeviceId)
+ break;
+
+ set_mixer_state(READY);
return true;
}
@@ -270,78 +289,76 @@ void PulseAudioMixer::PulseAudioFree() {
if (!pa_mainloop_)
return;
- DCHECK_NE(mixer_state_, UNINITIALIZED);
- mixer_state_ = SHUTTING_DOWN;
+ {
+ AutoLock lock(mixer_state_lock_);
+ DCHECK_NE(mixer_state_, UNINITIALIZED);
+ if (mixer_state_ == SHUTTING_DOWN)
+ return;
+ // If still initializing on another thread, this will cause it to exit.
+ mixer_state_ = SHUTTING_DOWN;
+ }
+ MainloopLock();
if (pa_context_) {
- pa_threaded_mainloop_lock(pa_mainloop_);
pa_context_disconnect(pa_context_);
pa_context_unref(pa_context_);
- pa_threaded_mainloop_unlock(pa_mainloop_);
pa_context_ = NULL;
}
+ MainloopUnlock();
pa_threaded_mainloop_stop(pa_mainloop_);
pa_threaded_mainloop_free(pa_mainloop_);
pa_mainloop_ = NULL;
- mixer_state_ = UNINITIALIZED;
-}
-
-bool PulseAudioMixer::PulseAudioValid() const {
- if (mixer_state_ != READY)
- return false;
- if (!pa_context_) {
- DLOG(ERROR) << "Trying to use PulseAudio when no context";
- return false;
- }
- if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY) {
- LOG(ERROR) << "PulseAudio context not ready ("
- << pa_context_get_state(pa_context_) << ")";
- return false;
- }
- if (device_id_ == kInvalidDeviceId)
- return false;
-
- return true;
+ set_mixer_state(UNINITIALIZED);
}
-void PulseAudioMixer::CompleteOperationAndUnlock(pa_operation* pa_op) const {
+void PulseAudioMixer::CompleteOperation(pa_operation* pa_op,
+ bool* done) const {
// After starting any operation, this helper checks if it started OK, then
// waits for it to complete by iterating through the mainloop until the
// operation is not running anymore.
CHECK(pa_op);
while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
- pa_threaded_mainloop_wait(pa_mainloop_);
+ // If operation still running, but we got what we needed, cancel it now.
+ if (*done) {
+ pa_operation_cancel(pa_op);
+ break;
+ }
+ MainloopWait();
}
pa_operation_unref(pa_op);
- pa_threaded_mainloop_unlock(pa_mainloop_);
}
+// Must be called with mainloop lock held
void PulseAudioMixer::GetDefaultPlaybackDevice() {
+ DCHECK_GT(mainloop_lock_count_, 0);
DCHECK(pa_context_);
DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY);
- pa_threaded_mainloop_lock(pa_mainloop_);
+ CallbackWrapper data = {this, false, NULL};
+
pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_,
EnumerateDevicesCallback,
- this);
- CompleteOperationAndUnlock(pa_op);
+ &data);
+ CompleteOperation(pa_op, &data.done);
return;
}
void PulseAudioMixer::OnEnumerateDevices(const pa_sink_info* sink_info,
- int eol) {
- // If eol is set to a positive number, you're at the end of the list.
- if (eol > 0)
+ int eol, bool* done) {
+ if (device_id_ != kInvalidDeviceId)
return;
// TODO(davej): Should we handle cases of more than one output sink device?
- if (device_id_ == kInvalidDeviceId)
- device_id_ = sink_info->index;
- pa_threaded_mainloop_signal(pa_mainloop_, 0);
+ // eol is < 0 for error, > 0 for end of list, ==0 while listing.
+ if (eol == 0) {
+ device_id_ = sink_info->index;
+ }
+ *done = true;
+ MainloopSignal();
}
// static
@@ -349,19 +366,20 @@ void PulseAudioMixer::EnumerateDevicesCallback(pa_context* unused,
const pa_sink_info* sink_info,
int eol,
void* userdata) {
- PulseAudioMixer* inst = static_cast<PulseAudioMixer*>(userdata);
- inst->OnEnumerateDevices(sink_info, eol);
+ CallbackWrapper* data =
+ static_cast<CallbackWrapper*>(userdata);
+ data->instance->OnEnumerateDevices(sink_info, eol, &data->done);
}
+// Must be called with lock held
void PulseAudioMixer::GetAudioInfo(AudioInfo* info) const {
- CallbackWrapper cb_data = {pa_mainloop_, info};
- pa_threaded_mainloop_lock(pa_mainloop_);
- pa_operation* pa_op;
- pa_op = pa_context_get_sink_info_by_index(pa_context_,
- device_id_,
- GetAudioInfoCallback,
- &cb_data);
- CompleteOperationAndUnlock(pa_op);
+ DCHECK_GT(mainloop_lock_count_, 0);
+ CallbackWrapper data = {const_cast<PulseAudioMixer*>(this), false, info};
+ pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_,
+ device_id_,
+ GetAudioInfoCallback,
+ &data);
+ CompleteOperation(pa_op, &data.done);
}
// static
@@ -369,15 +387,58 @@ void PulseAudioMixer::GetAudioInfoCallback(pa_context* unused,
const pa_sink_info* sink_info,
int eol,
void* userdata) {
- CallbackWrapper* cb_data = static_cast<CallbackWrapper*>(userdata);
- AudioInfo* data = static_cast<AudioInfo*>(cb_data->data);
+ CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata);
+ AudioInfo* info = static_cast<AudioInfo*>(data->userdata);
// Copy just the information we care about.
if (eol == 0) {
- data->cvolume = sink_info->volume;
- data->muted = sink_info->mute ? true : false;
+ info->cvolume = sink_info->volume;
+ info->muted = sink_info->mute ? true : false;
+ data->done = true;
}
- pa_threaded_mainloop_signal(cb_data->mainloop, 0);
+ data->instance->MainloopSignal();
+}
+
+inline void PulseAudioMixer::MainloopLock() const {
+ pa_threaded_mainloop_lock(pa_mainloop_);
+ ++mainloop_lock_count_;
+}
+
+inline void PulseAudioMixer::MainloopUnlock() const {
+ --mainloop_lock_count_;
+ pa_threaded_mainloop_unlock(pa_mainloop_);
+}
+
+// Must be called with the lock held.
+inline void PulseAudioMixer::MainloopWait() const {
+ DCHECK_GT(mainloop_lock_count_, 0);
+ pa_threaded_mainloop_wait(pa_mainloop_);
+}
+
+// Must be called with the lock held.
+inline void PulseAudioMixer::MainloopSignal() const {
+ DCHECK_GT(mainloop_lock_count_, 0);
+ pa_threaded_mainloop_signal(pa_mainloop_, 0);
+}
+
+inline bool PulseAudioMixer::MainloopSafeLock() const {
+ AutoLock lock(mixer_state_lock_);
+ if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_))
+ return false;
+ pa_threaded_mainloop_lock(pa_mainloop_);
+ ++mainloop_lock_count_;
+ return true;
+}
+
+inline bool PulseAudioMixer::MainloopLockIfReady() const {
+ AutoLock lock(mixer_state_lock_);
+ if (mixer_state_ != READY)
+ return false;
+ if (!pa_mainloop_)
+ return false;
+ pa_threaded_mainloop_lock(pa_mainloop_);
+ ++mainloop_lock_count_;
+ return true;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/pulse_audio_mixer.h b/chrome/browser/chromeos/pulse_audio_mixer.h
index 223fe33..5d7de39 100644
--- a/chrome/browser/chromeos/pulse_audio_mixer.h
+++ b/chrome/browser/chromeos/pulse_audio_mixer.h
@@ -4,9 +4,11 @@
#ifndef CHROME_BROWSER_CHROMEOS_PULSE_AUDIO_MIXER_H_
#define CHROME_BROWSER_CHROMEOS_PULSE_AUDIO_MIXER_H_
+#pragma once
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/lock.h"
#include "base/scoped_ptr.h"
#include "base/thread.h"
@@ -20,6 +22,14 @@ namespace chromeos {
class PulseAudioMixer {
public:
+ enum State {
+ UNINITIALIZED = 0,
+ INITIALIZING,
+ READY,
+ SHUTTING_DOWN,
+ IN_ERROR
+ };
+
PulseAudioMixer();
~PulseAudioMixer();
@@ -28,12 +38,16 @@ class PulseAudioMixer {
typedef Callback1<bool>::Type InitDoneCallback;
bool Init(InitDoneCallback* callback);
+ // Blocking init call guarantees PulseAudio is started before returning.
+ bool InitSync();
+
// Blocking call. Returns a default of -inf on error.
double GetVolumeDb() const;
- // Non-blocking, volume sent in as first param to callback
+ // Non-blocking, volume sent in as first param to callback. The callback is
+ // only called if the function returns true.
typedef Callback2<double, void*>::Type GetVolumeCallback;
- void GetVolumeDbAsync(GetVolumeCallback* callback, void* user);
+ bool GetVolumeDbAsync(GetVolumeCallback* callback, void* user);
// Non-blocking call.
void SetVolumeDb(double vol_db);
@@ -45,20 +59,14 @@ class PulseAudioMixer {
// Non-Blocking call.
void SetMute(bool mute);
- // Call any time to see if we have a valid working connection to PulseAudio.
- // Non-blocking call.
- bool IsValid() const;
+ // Returns READY if we have a valid working connection to PulseAudio.
+ // This can return IN_ERROR if we lose the connection, even after an original
+ // successful init. Non-blocking call.
+ State CheckState() const;
private:
struct AudioInfo;
- enum State {
- UNINITIALIZED = 0,
- INITIALIZING,
- READY,
- SHUTTING_DOWN
- };
-
// These are the tasks to be run in the background on the worker thread.
void DoInit(InitDoneCallback* callback);
void DoGetVolume(GetVolumeCallback* callback, void* user);
@@ -66,6 +74,9 @@ class PulseAudioMixer {
static void ConnectToPulseCallbackThunk(pa_context* c, void* userdata);
void OnConnectToPulseCallback(pa_context* c, bool* connect_done);
+ // Helper function to just get our messsage loop thread going.
+ bool InitThread();
+
// This goes through sequence of connecting to the default PulseAudio server.
// We will block until we either have a valid connection or something failed.
// If a connection is lost for some reason, delete and recreate the object.
@@ -74,14 +85,9 @@ class PulseAudioMixer {
// PulseAudioFree. Disconnect from server.
void PulseAudioFree();
- // Check if the PA system is ready for communication, as well as if a default
- // device is available to talk to. This can return false if we lose the
- // connection, even after an original successful init.
- bool PulseAudioValid() const;
-
// Iterates the PA mainloop and only returns once an operation has completed
- // (successfully or unsuccessfully). This call only blocks the worker thread.
- void CompleteOperationAndUnlock(pa_operation* pa_op) const;
+ // (successfully or unsuccessfully) or *done is true.
+ void CompleteOperation(pa_operation* pa_op, bool* done) const;
// For now, this just gets the first device returned from the enumeration
// request. This will be the 'default' or 'master' device that all further
@@ -91,7 +97,7 @@ class PulseAudioMixer {
const pa_sink_info* sink_info,
int eol,
void* userdata);
- void OnEnumerateDevices(const pa_sink_info* sink_info, int eol);
+ void OnEnumerateDevices(const pa_sink_info* sink_info, int eol, bool* done);
// Get the info we're interested in from the default device. Currently this
// is an array of volumes, and the mute state. Blocking call.
@@ -101,12 +107,34 @@ class PulseAudioMixer {
int eol,
void* userdata);
+ void set_mixer_state(State state) {
+ AutoLock lock(mixer_state_lock_);
+ mixer_state_ = state;
+ }
+
+ // These call down to PulseAudio's mainloop locking functions
+ void MainloopLock() const;
+ void MainloopUnlock() const;
+ void MainloopWait() const;
+ void MainloopSignal() const;
+
+ // Same as Lock(), but we fail if we are shutting down or mainloop invalid.
+ bool MainloopSafeLock() const;
+
+ // Lock the mainloop pa_lock_ if mixer_state_ is READY.
+ bool MainloopLockIfReady() const;
+
// The PulseAudio index of the main device being used.
- mutable int device_id_;
+ int device_id_;
// Set to the number of channels on the main device.
int last_channels_;
- State mixer_state_;
+
+ // For informational purposes only, just used to assert lock is held.
+ mutable int mainloop_lock_count_;
+
+ mutable Lock mixer_state_lock_;
+ mutable State mixer_state_;
// Cached contexts for use in PulseAudio calls.
pa_context* pa_context_;
diff --git a/chrome/browser/chromeos/status/clock_menu_button.cc b/chrome/browser/chromeos/status/clock_menu_button.cc
index 9576490..f63593f 100644
--- a/chrome/browser/chromeos/status/clock_menu_button.cc
+++ b/chrome/browser/chromeos/status/clock_menu_button.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -9,6 +9,7 @@
#include "base/i18n/time_formatting.h"
#include "base/string_util.h"
#include "base/time.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
@@ -25,17 +26,18 @@ namespace chromeos {
const int kTimerSlopSeconds = 1;
ClockMenuButton::ClockMenuButton(StatusAreaHost* host)
- : MenuButton(NULL, std::wstring(), this, false),
+ : StatusAreaButton(this),
host_(host) {
// Add as SystemLibrary observer. We update the clock if timezone changes.
CrosLibrary::Get()->GetSystemLibrary()->AddObserver(this);
set_border(NULL);
+ set_use_menu_button_paint(true);
SetFont(ResourceBundle::GetSharedInstance().GetFont(
ResourceBundle::BaseFont).DeriveFont(1, gfx::Font::BOLD));
SetEnabledColor(0xB3FFFFFF); // White with 70% Alpha
- SetShowHighlighted(false);
- set_alignment(TextButton::ALIGN_RIGHT);
+ SetShowMultipleIconStates(false);
+ set_alignment(TextButton::ALIGN_CENTER);
UpdateTextAndSetNextTimer();
}
@@ -68,18 +70,9 @@ void ClockMenuButton::UpdateTextAndSetNextTimer() {
}
void ClockMenuButton::UpdateText() {
- int cur_width = GetPreferredSize().width();
- SetText(base::TimeFormatTimeOfDay(base::Time::Now()));
- // TextButtons normally remember the max text size, so the button's preferred
- // size will always be as large as the largest text ever put in it.
- // We clear that max text size, so we can adjust the size to fit the text.
- ClearMaxTextSize();
- int new_width = GetPreferredSize().width();
-
- // If width has changed, we want to relayout the StatusAreaView.
- if (new_width != cur_width)
- PreferredSizeChanged();
-
+ base::Time time(base::Time::Now());
+ SetText(base::TimeFormatTimeOfDay(time));
+ SetTooltipText(base::TimeFormatShortDate(time));
SchedulePaint();
}
diff --git a/chrome/browser/chromeos/status/clock_menu_button.h b/chrome/browser/chromeos/status/clock_menu_button.h
index b5daa2c..405d00a 100644
--- a/chrome/browser/chromeos/status/clock_menu_button.h
+++ b/chrome/browser/chromeos/status/clock_menu_button.h
@@ -4,10 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_CLOCK_MENU_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_CLOCK_MENU_BUTTON_H_
+#pragma once
#include "base/scoped_ptr.h"
#include "base/timer.h"
#include "chrome/browser/chromeos/cros/system_library.h"
+#include "chrome/browser/chromeos/status/status_area_button.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_service.h"
#include "unicode/calendar.h"
@@ -21,7 +23,7 @@ class StatusAreaHost;
// The clock menu button in the status area.
// This button shows the current time.
-class ClockMenuButton : public views::MenuButton,
+class ClockMenuButton : public StatusAreaButton,
public views::ViewMenuDelegate,
public menus::MenuModel,
public SystemLibrary::Observer {
diff --git a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
index b0a3106..f7a6f1c 100644
--- a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
+++ b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc
@@ -12,7 +12,7 @@
#include "chrome/browser/chromeos/frame/browser_view.h"
#include "chrome/browser/chromeos/status/status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/in_process_browser_test.h"
@@ -25,6 +25,11 @@ namespace chromeos {
class ClockMenuButtonTest : public InProcessBrowserTest {
protected:
ClockMenuButtonTest() : InProcessBrowserTest() {}
+ virtual void SetUpInProcessBrowserTestFixture() {
+ // This test requires actual libcros, but InProcessBrowserTest has set
+ // to use stub, so reset it here.
+ CrosLibrary::Get()->GetTestApi()->ResetUseStubImpl();
+ }
ClockMenuButton* GetClockMenuButton() {
BrowserView* view = static_cast<BrowserView*>(browser()->window());
return static_cast<StatusAreaView*>(view->
@@ -35,13 +40,18 @@ class ClockMenuButtonTest : public InProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(ClockMenuButtonTest, TimezoneTest) {
ClockMenuButton* clock = GetClockMenuButton();
ASSERT_TRUE(clock != NULL);
+
// Update timezone and make sure clock text changes.
- std::wstring text_before = clock->text();
- scoped_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone(
+ scoped_ptr<icu::TimeZone> timezone_first(icu::TimeZone::createTimeZone(
icu::UnicodeString::fromUTF8("Asia/Hong_Kong")));
- CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone.get());
+ CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone_first.get());
+ std::wstring text_before = clock->text();
+ scoped_ptr<icu::TimeZone> timezone_second(icu::TimeZone::createTimeZone(
+ icu::UnicodeString::fromUTF8("Pacific/Samoa")));
+ CrosLibrary::Get()->GetSystemLibrary()->SetTimezone(timezone_second.get());
std::wstring text_after = clock->text();
EXPECT_NE(text_before, text_after);
+
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/status/feedback_menu_button.cc b/chrome/browser/chromeos/status/feedback_menu_button.cc
index 1b8ead6..d3b14d3 100644
--- a/chrome/browser/chromeos/status/feedback_menu_button.cc
+++ b/chrome/browser/chromeos/status/feedback_menu_button.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
@@ -22,6 +23,7 @@ FeedbackMenuButton::FeedbackMenuButton(StatusAreaHost* host)
: StatusAreaButton(this),
host_(host) {
DCHECK(host_);
+ SetTooltipText(l10n_util::GetString(IDS_STATUSBAR_FEEDBACK_TOOLTIP));
}
FeedbackMenuButton::~FeedbackMenuButton() {
diff --git a/chrome/browser/chromeos/status/feedback_menu_button.h b/chrome/browser/chromeos/status/feedback_menu_button.h
index 1b6b1df..9e1590b 100644
--- a/chrome/browser/chromeos/status/feedback_menu_button.h
+++ b/chrome/browser/chromeos/status/feedback_menu_button.h
@@ -4,8 +4,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_FEEDBACK_MENU_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_FEEDBACK_MENU_BUTTON_H_
+#pragma once
-#include "app/menus/simple_menu_model.h"
#include "chrome/browser/chromeos/status/status_area_button.h"
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/view_menu_delegate.h"
diff --git a/chrome/browser/chromeos/status/language_menu_button.cc b/chrome/browser/chromeos/status/language_menu_button.cc
index 169640d..24f2da5 100644
--- a/chrome/browser/chromeos/status/language_menu_button.cc
+++ b/chrome/browser/chromeos/status/language_menu_button.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -8,6 +8,7 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/string_split.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
@@ -15,10 +16,12 @@
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -71,7 +74,6 @@ enum {
// input method list to avoid conflict.
const int kRadioGroupLanguage = 1 << 16;
const int kRadioGroupNone = -1;
-const wchar_t kSpacer[] = L"MMM";
// A mapping from an input method id to a text for the language indicator. The
// mapping is necessary since some input methods belong to the same language.
@@ -91,13 +93,9 @@ const struct {
// For traditional Chinese input methods
{ "chewing", "\xe9\x85\xb7" }, // U+9177
{ "m17n:zh:cangjie", "\xe5\x80\x89" }, // U+5009
- // TODO(yusukes): Add m17n:zh:quick if there's a good Hanzi character for it.
-
- // Handle "m17n:t" input methods here since ICU is not able to handle the
- // language code "t". Note: most users use either latn-pre or latn-post
- // methods, not both. The same is true for mozc/mozc-jp.
- { "m17n:t:latn-pre", "LAT" },
- { "m17n:t:latn-post", "LAT" },
+ { "m17n:zh:quick", "\xe9\x80\x9f" }, // U+901F
+ // For Hangul input method.
+ { "hangul", "\xed\x95\x9c" }, // U+D55C
};
const size_t kMappingFromIdToIndicatorTextLen =
ARRAYSIZE_UNSAFE(kMappingFromIdToIndicatorText);
@@ -126,7 +124,7 @@ namespace chromeos {
// LanguageMenuButton
LanguageMenuButton::LanguageMenuButton(StatusAreaHost* host)
- : MenuButton(NULL, std::wstring(), this, false),
+ : StatusAreaButton(this),
input_method_descriptors_(CrosLibrary::Get()->GetInputMethodLibrary()->
GetActiveInputMethods()),
model_(NULL),
@@ -139,15 +137,16 @@ LanguageMenuButton::LanguageMenuButton(StatusAreaHost* host)
DCHECK(input_method_descriptors_.get() &&
!input_method_descriptors_->empty());
set_border(NULL);
+ set_use_menu_button_paint(true);
SetFont(ResourceBundle::GetSharedInstance().GetFont(
ResourceBundle::BaseFont).DeriveFont(1, gfx::Font::BOLD));
SetEnabledColor(0xB3FFFFFF); // White with 70% Alpha
SetDisabledColor(0x00FFFFFF); // White with 00% Alpha (invisible)
- SetShowHighlighted(false);
+ SetShowMultipleIconStates(false);
+ set_alignment(TextButton::ALIGN_CENTER);
+
// Update the model
RebuildModel();
- // Grab the real estate.
- UpdateIndicator(kSpacer, L"" /* no tooltip */);
// Draw the default indicator "US". The default indicator "US" is used when
// |pref_service| is not available (for example, unit tests) or |pref_service|
@@ -325,12 +324,7 @@ string16 LanguageMenuButton::GetLabelAt(int index) const {
std::wstring name;
if (IndexIsInInputMethodList(index)) {
- const std::string language_code =
- input_method::GetLanguageCodeFromDescriptor(
- input_method_descriptors_->at(index));
- bool need_method_name = (need_method_name_.count(language_code) > 0);
- name = GetTextForMenu(input_method_descriptors_->at(index),
- need_method_name);
+ name = GetTextForMenu(input_method_descriptors_->at(index));
} else if (GetPropertyIndex(index, &index)) {
const ImePropertyList& property_list
= CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
@@ -398,6 +392,22 @@ void LanguageMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
GetActiveInputMethods());
RebuildModel();
language_menu_.Rebuild();
+
+ // Disallow the menu widget to grab the keyboard focus. This is necessary to
+ // enable users to change status of an input method (e.g. change the input
+ // mode from Japanese Hiragana to Japanese Katakana) without discarding a
+ // preedit string. See crosbug.com/5796 for details. Note that menus other
+ // than this one should not call the Gtk+ API since it is a special API only
+ // for a menu related to IME/keyboard. See the Gtk+ API reference at:
+ // http://library.gnome.org/devel/gtk/stable/GtkMenuShell.html
+ gfx::NativeMenu native_menu = language_menu_.GetNativeMenu();
+ if (native_menu) {
+ gtk_menu_shell_set_take_focus(GTK_MENU_SHELL(native_menu), FALSE);
+ } else {
+ LOG(ERROR)
+ << "Can't call gtk_menu_shell_set_take_focus since NativeMenu is NULL";
+ }
+
language_menu_.UpdateStates();
language_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
}
@@ -428,7 +438,7 @@ void LanguageMenuButton::InputMethodChanged(InputMethodLibrary* obj) {
// buttun for the login screen is destroyed.
if (!logged_in_ && g_browser_process && g_browser_process->local_state()) {
g_browser_process->local_state()->SetString(
- kPreferredKeyboardLayout, current_input_method.id);
+ language_prefs::kPreferredKeyboardLayout, current_input_method.id);
g_browser_process->local_state()->SavePersistentPrefs();
}
}
@@ -446,7 +456,8 @@ void LanguageMenuButton::ImePropertiesChanged(InputMethodLibrary* obj) {
////////////////////////////////////////////////////////////////////////////////
// views::View implementation:
-void LanguageMenuButton::LocaleChanged() {
+void LanguageMenuButton::OnLocaleChanged() {
+ input_method::OnLocaleChanged();
const InputMethodDescriptor& input_method =
CrosLibrary::Get()->GetInputMethodLibrary()->current_input_method();
UpdateIndicatorFromInputMethod(input_method);
@@ -474,15 +485,13 @@ void LanguageMenuButton::UpdateIndicator(
SetTooltipText(tooltip);
}
SetText(name);
- set_alignment(TextButton::ALIGN_RIGHT);
SchedulePaint();
}
void LanguageMenuButton::UpdateIndicatorFromInputMethod(
const InputMethodDescriptor& input_method) {
const std::wstring name = GetTextForIndicator(input_method);
- const std::wstring tooltip =
- GetTextForMenu(input_method, true /* add_method_name */);
+ const std::wstring tooltip = GetTextForMenu(input_method);
UpdateIndicator(name, tooltip);
}
@@ -492,26 +501,14 @@ void LanguageMenuButton::RebuildModel() {
// Indicates if separator's needed before each section.
bool need_separator = false;
- need_method_name_.clear();
- std::set<std::string> languages_seen;
if (!input_method_descriptors_->empty()) {
// We "abuse" the command_id and group_id arguments of AddRadioItem method.
// A COMMAND_ID_XXX enum value is passed as command_id, and array index of
// |input_method_descriptors_| or |property_list| is passed as group_id.
for (size_t i = 0; i < input_method_descriptors_->size(); ++i) {
model_->AddRadioItem(COMMAND_ID_INPUT_METHODS, dummy_label, i);
-
- const std::string language_code
- = input_method::GetLanguageCodeFromDescriptor(
- input_method_descriptors_->at(i));
- // If there is more than one input method for this language, then we need
- // to display the method name.
- if (languages_seen.find(language_code) == languages_seen.end()) {
- languages_seen.insert(language_code);
- } else {
- need_method_name_.insert(language_code);
- }
}
+
need_separator = true;
}
@@ -634,31 +631,33 @@ std::wstring LanguageMenuButton::GetTextForIndicator(
}
std::wstring LanguageMenuButton::GetTextForMenu(
- const InputMethodDescriptor& input_method, bool add_method_name) {
+ const InputMethodDescriptor& input_method) {
+ // We don't show language here. Name of keyboard layout or input method
+ // usually imply (or explicitly include) its language.
+
+ // Special case for Dutch, French and German: these languages have multiple
+ // keyboard layouts and share the same laout of keyboard (Belgian). We need to
+ // show explicitly the language for the layout.
+ // For Arabic and Hindi: they share "Standard Input Method".
const std::string language_code
= input_method::GetLanguageCodeFromDescriptor(input_method);
-
std::wstring text;
- if (language_code == "t") {
- text = UTF8ToWide(input_method.display_name);
+ if (language_code == "ar" ||
+ language_code == "hi" ||
+ language_code == "nl" ||
+ language_code == "fr" ||
+ language_code == "de") {
+ text = GetLanguageName(language_code) + L" - ";
}
+ text += input_method::GetString(input_method.display_name);
- // For the drop-down menu and tooltip, we'll show language names like
- // "Chinese (Simplified)" and "Japanese", instead of input method names
- // like "Pinyin" and "Mozc".
- if (text.empty()) {
- text = GetLanguageName(language_code);
- if (add_method_name) {
- text += L" - ";
- text += input_method::GetString(input_method.display_name);
- }
- }
DCHECK(!text.empty());
return text;
}
void LanguageMenuButton::RegisterPrefs(PrefService* local_state) {
- local_state->RegisterStringPref(kPreferredKeyboardLayout, "");
+ local_state->RegisterStringPref(language_prefs::kPreferredKeyboardLayout,
+ "");
}
void LanguageMenuButton::Observe(NotificationType type,
diff --git a/chrome/browser/chromeos/status/language_menu_button.h b/chrome/browser/chromeos/status/language_menu_button.h
index dcafac1..7610e8c 100644
--- a/chrome/browser/chromeos/status/language_menu_button.h
+++ b/chrome/browser/chromeos/status/language_menu_button.h
@@ -4,11 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_LANGUAGE_MENU_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_LANGUAGE_MENU_BUTTON_H_
+#pragma once
#include "app/menus/simple_menu_model.h"
#include "chrome/browser/chromeos/cros/input_method_library.h"
#include "chrome/browser/chromeos/status/status_area_button.h"
-#include "chrome/browser/pref_member.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
@@ -24,7 +25,7 @@ class StatusAreaHost;
// The language menu button in the status area.
// This class will handle getting the IME/XKB status and populating the menu.
-class LanguageMenuButton : public views::MenuButton,
+class LanguageMenuButton : public StatusAreaButton,
public views::ViewMenuDelegate,
public menus::MenuModel,
public InputMethodLibrary::Observer,
@@ -69,15 +70,14 @@ class LanguageMenuButton : public views::MenuButton,
// Converts an InputMethodDescriptor object into human readable string.
// Returns a string for the drop-down menu and the tooltip for the indicator.
- static std::wstring GetTextForMenu(
- const InputMethodDescriptor& input_method, bool add_method_name);
+ static std::wstring GetTextForMenu(const InputMethodDescriptor& input_method);
// Registers input method preferences for the login screen.
static void RegisterPrefs(PrefService* local_state);
protected:
// views::View implementation.
- virtual void LocaleChanged();
+ virtual void OnLocaleChanged();
private:
// views::ViewMenuDelegate implementation.
@@ -114,9 +114,6 @@ class LanguageMenuButton : public views::MenuButton,
StringPrefMember previous_input_method_pref_;
StringPrefMember current_input_method_pref_;
- // Languages that need the input method name displayed.
- std::set<std::string> need_method_name_;
-
// We borrow menus::SimpleMenuModel implementation to maintain the current
// content of the pop-up menu. The menus::MenuModel is implemented using this
// |model_|.
diff --git a/chrome/browser/chromeos/status/language_menu_button_browsertest.cc b/chrome/browser/chromeos/status/language_menu_button_browsertest.cc
index 452e598..2176997 100644
--- a/chrome/browser/chromeos/status/language_menu_button_browsertest.cc
+++ b/chrome/browser/chromeos/status/language_menu_button_browsertest.cc
@@ -23,8 +23,8 @@ class LanguageMenuButtonTest : public CrosInProcessBrowserTest {
}
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
- SetStatusAreaMocksExpectations();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->SetStatusAreaMocksExpectations();
}
LanguageMenuButton* GetLanguageMenuButton() {
diff --git a/chrome/browser/chromeos/status/language_menu_button_unittest.cc b/chrome/browser/chromeos/status/language_menu_button_unittest.cc
index 2f4044a..b760fbc 100644
--- a/chrome/browser/chromeos/status/language_menu_button_unittest.cc
+++ b/chrome/browser/chromeos/status/language_menu_button_unittest.cc
@@ -20,7 +20,8 @@ TEST(LanguageMenuButtonTest, GetTextForIndicatorTest) {
}
{
InputMethodDescriptor desc("hangul", "Korean", "us", "ko");
- EXPECT_EQ(L"KO", LanguageMenuButton::GetTextForIndicator(desc));
+ EXPECT_EQ(UTF8ToWide("\xed\x95\x9c"),
+ LanguageMenuButton::GetTextForIndicator(desc));
}
{
InputMethodDescriptor desc("invalid-id", "unregistered string", "us", "xx");
@@ -30,7 +31,7 @@ TEST(LanguageMenuButtonTest, GetTextForIndicatorTest) {
// Test special cases.
{
- InputMethodDescriptor desc("xkb:us:dvorak:eng", "Dvorak", "us", "us");
+ InputMethodDescriptor desc("xkb:us:dvorak:eng", "Dvorak", "us", "eng");
EXPECT_EQ(L"DV", LanguageMenuButton::GetTextForIndicator(desc));
}
{
@@ -60,39 +61,97 @@ TEST(LanguageMenuButtonTest, GetTextForIndicatorTest) {
}
{
InputMethodDescriptor desc("m17n:zh:quick", "Quick", "us", "zh-TW");
- EXPECT_EQ(UTF8ToWide("TW"),
- LanguageMenuButton::GetTextForIndicator(desc));
- }
- {
- InputMethodDescriptor desc("m17n:t:latn-pre", "latn-pre", "us", "t");
- EXPECT_EQ(L"LAT",
+ EXPECT_EQ(UTF8ToWide("\xe9\x80\x9f"),
LanguageMenuButton::GetTextForIndicator(desc));
}
}
-TEST(LanguageMenuButtonTest, GetTextForTooltipTest) {
- const bool kAddMethodName = true;
+
+// Test whether the function returns language name for non-ambiguous languages.
+TEST(LanguageMenuButtonTest, GetTextForMenuTest) {
+ // For most languages input method or keyboard layout name is returned.
+ // See below for exceptions.
{
InputMethodDescriptor desc("m17n:fa:isiri", "isiri (m17n)", "us", "fa");
- EXPECT_EQ(L"Persian - Persian input method (ISIRI 2901 layout)",
- LanguageMenuButton::GetTextForMenu(desc, kAddMethodName));
+ EXPECT_EQ(L"Persian input method (ISIRI 2901 layout)",
+ LanguageMenuButton::GetTextForMenu(desc));
}
{
InputMethodDescriptor desc("hangul", "Korean", "us", "ko");
- EXPECT_EQ(L"Korean - Korean input method",
- LanguageMenuButton::GetTextForMenu(desc, kAddMethodName));
+ EXPECT_EQ(L"Korean input method",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("m17n:vi:tcvn", "tcvn (m17n)", "us", "vi");
+ EXPECT_EQ(L"Vietnamese input method (TCVN6064)",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("mozc", "Mozc (US keyboard layout)", "us", "ja");
+ EXPECT_EQ(L"Japanese input method (for US keyboard)",
+ LanguageMenuButton::GetTextForMenu(desc));
}
{
+ InputMethodDescriptor desc("xkb:jp::jpn", "Japan", "jp", "jpn");
+ EXPECT_EQ(L"Japanese keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:us:dvorak:eng", "USA - Dvorak",
+ "us(dvorak)", "eng");
+ EXPECT_EQ(L"English (Dvorak)",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+
+ // For Arabic, Dutch, French, German and Hindi,
+ // "language - keyboard layout" pair is returned.
+ {
+ InputMethodDescriptor desc("m17n:ar:kbd", "kbd (m17n)", "us", "ar");
+ EXPECT_EQ(L"Arabic - Standard input method",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:nl::nld", "Netherlands", "nl", "nld");
+ EXPECT_EQ(L"Dutch - Dutch keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:be::nld", "Belgium", "be", "nld");
+ EXPECT_EQ(L"Dutch - Belgian keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:fr::fra", "France", "fr", "fra");
+ EXPECT_EQ(L"French - French keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:be::fra", "Belgium", "be", "fra");
+ EXPECT_EQ(L"French - Belgian keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:de::ger", "Germany", "de", "ger");
+ EXPECT_EQ(L"German - German keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("xkb:be::ger", "Belgium", "be", "ger");
+ EXPECT_EQ(L"German - Belgian keyboard layout",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+ {
+ InputMethodDescriptor desc("m17n:hi:itrans", "itrans (m17n)", "us", "hi");
+ EXPECT_EQ(L"Hindi - Standard input method",
+ LanguageMenuButton::GetTextForMenu(desc));
+ }
+
+ {
InputMethodDescriptor desc("invalid-id", "unregistered string", "us", "xx");
// You can safely ignore the "Resouce ID is not found for: unregistered
// string" error.
- EXPECT_EQ(L"xx - unregistered string",
- LanguageMenuButton::GetTextForMenu(desc, kAddMethodName));
- }
- {
- InputMethodDescriptor desc("m17n:t:latn-pre", "latn-pre", "us", "t");
- EXPECT_EQ(L"latn-pre",
- LanguageMenuButton::GetTextForMenu(desc, kAddMethodName));
+ EXPECT_EQ(L"unregistered string",
+ LanguageMenuButton::GetTextForMenu(desc));
}
}
diff --git a/chrome/browser/chromeos/status/network_menu_button.cc b/chrome/browser/chromeos/status/network_menu_button.cc
index 7ea165e..9ed0854 100644
--- a/chrome/browser/chromeos/status/network_menu_button.cc
+++ b/chrome/browser/chromeos/status/network_menu_button.cc
@@ -4,19 +4,19 @@
#include "chrome/browser/chromeos/status/network_menu_button.h"
+#include <algorithm>
#include <limits>
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
#include "gfx/canvas_skia.h"
-#include "gfx/skbitmap_operations.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "views/widget/widget.h"
#include "views/window/window.h"
namespace chromeos {
@@ -25,13 +25,12 @@ namespace chromeos {
// NetworkMenuButton
// static
-const int NetworkMenuButton::kNumWifiImages = 9;
const int NetworkMenuButton::kThrobDuration = 1000;
NetworkMenuButton::NetworkMenuButton(StatusAreaHost* host)
: StatusAreaButton(this),
+ NetworkMenu(),
host_(host),
- ALLOW_THIS_IN_INITIALIZER_LIST(network_menu_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(animation_connecting_(this)) {
animation_connecting_.SetThrobDuration(kThrobDuration);
animation_connecting_.SetTweenType(Tween::LINEAR);
@@ -44,142 +43,6 @@ NetworkMenuButton::~NetworkMenuButton() {
}
////////////////////////////////////////////////////////////////////////////////
-// NetworkMenuButton, menus::MenuModel implementation:
-
-int NetworkMenuButton::GetItemCount() const {
- return static_cast<int>(menu_items_.size());
-}
-
-menus::MenuModel::ItemType NetworkMenuButton::GetTypeAt(int index) const {
- return menu_items_[index].type;
-}
-
-string16 NetworkMenuButton::GetLabelAt(int index) const {
- return menu_items_[index].label;
-}
-
-const gfx::Font* NetworkMenuButton::GetLabelFontAt(int index) const {
- return (menu_items_[index].flags & FLAG_ASSOCIATED) ?
- &ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BoldFont) :
- NULL;
-}
-
-bool NetworkMenuButton::IsItemCheckedAt(int index) const {
- // All menus::MenuModel::TYPE_CHECK menu items are checked.
- return true;
-}
-
-bool NetworkMenuButton::GetIconAt(int index, SkBitmap* icon) const {
- if (!menu_items_[index].icon.empty()) {
- *icon = menu_items_[index].icon;
- return true;
- }
- return false;
-}
-
-bool NetworkMenuButton::IsEnabledAt(int index) const {
- return !(menu_items_[index].flags & FLAG_DISABLED);
-}
-
-void NetworkMenuButton::ActivatedAt(int index) {
- // When we are refreshing the menu, ignore menu item activation.
- if (refreshing_menu_)
- return;
-
- NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
- int flags = menu_items_[index].flags;
- if (flags & FLAG_OPTIONS) {
- host_->OpenButtonOptions(this);
- } else if (flags & FLAG_TOGGLE_ETHERNET) {
- cros->EnableEthernetNetworkDevice(!cros->ethernet_enabled());
- } else if (flags & FLAG_TOGGLE_WIFI) {
- cros->EnableWifiNetworkDevice(!cros->wifi_enabled());
- } else if (flags & FLAG_TOGGLE_CELLULAR) {
- cros->EnableCellularNetworkDevice(!cros->cellular_enabled());
- } else if (flags & FLAG_TOGGLE_OFFLINE) {
- cros->EnableOfflineMode(!cros->offline_mode());
- } else if (flags & FLAG_OTHER_NETWORK) {
- NetworkConfigView* view = new NetworkConfigView();
- view->set_browser_mode(host_->IsBrowserMode());
- views::Window* window = views::Window::CreateChromeWindow(
- host_->GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- view->SetLoginTextfieldFocus();
- } else if (flags & FLAG_ETHERNET) {
- if (cros->ethernet_connected()) {
- NetworkConfigView* view = new NetworkConfigView(cros->ethernet_network());
- view->set_browser_mode(host_->IsBrowserMode());
- views::Window* window = views::Window::CreateChromeWindow(
- host_->GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- }
- } else if (flags & FLAG_WIFI) {
- WifiNetwork wifi;
- bool wifi_exists = cros->FindWifiNetworkByPath(
- menu_items_[index].wireless_path, &wifi);
- if (!wifi_exists) {
- // If we are attempting to connect to a network that no longer exists,
- // display a notification.
- // TODO(stevenjb): Show notification.
- } else if (wifi.name() == cros->wifi_name()) {
- if (cros->wifi_connected()) {
- // If we are already connected, open the config dialog.
- NetworkConfigView* view = new NetworkConfigView(wifi, false);
- view->set_browser_mode(host_->IsBrowserMode());
- views::Window* window = views::Window::CreateChromeWindow(
- host_->GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- } else {
- // TODO(stevenjb): Connection in progress. Show dialog?
- }
- } else {
- // If wifi network is not encrypted, then directly connect.
- // Otherwise, we open password dialog window.
- if (!wifi.encrypted()) {
- cros->ConnectToWifiNetwork(wifi, std::string(),
- std::string(), std::string());
- } else {
- NetworkConfigView* view = new NetworkConfigView(wifi, true);
- view->set_browser_mode(host_->IsBrowserMode());
- views::Window* window = views::Window::CreateChromeWindow(
- host_->GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- view->SetLoginTextfieldFocus();
- }
- }
- } else if (flags & FLAG_CELLULAR) {
- CellularNetwork cellular;
- bool cellular_exists = cros->FindCellularNetworkByPath(
- menu_items_[index].wireless_path, &cellular);
-
- if (!cellular_exists) {
- // If we are attempting to connect to a network that no longer exists,
- // display a notification.
- // TODO(stevenjb): Show notification.
- } else if (cellular.name() == cros->cellular_name()) {
- // If clicked on a network that we are already connected to or we are
- // currently trying to connect to, then open config dialog.
- if (cros->cellular_connected()) {
- NetworkConfigView* view = new NetworkConfigView(cellular);
- view->set_browser_mode(host_->IsBrowserMode());
- views::Window* window = views::Window::CreateChromeWindow(
- host_->GetNativeWindow(), gfx::Rect(), view);
- window->SetIsAlwaysOnTop(true);
- window->Show();
- } else {
- // TODO(stevenjb): Connection in progress. Show dialog?
- }
- } else {
- cros->ConnectToCellularNetwork(cellular);
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
// NetworkMenuButton, AnimationDelegate implementation:
void NetworkMenuButton::AnimationProgressed(const Animation* animation) {
@@ -221,144 +84,6 @@ void NetworkMenuButton::DrawIcon(gfx::Canvas* canvas) {
canvas->DrawBitmapInt(IconForDisplay(icon(), badge()), 0, 0);
}
-// Override the DrawIcon method to draw the wifi icon.
-// The wifi icon is composed of 1 or more alpha-blended icons to show the
-// network strength. We also draw an animation for when there's upload/download
-// traffic.
-/* TODO(chocobo): Add this code back in when UI is finalized.
-void NetworkMenuButton::DrawIcon(gfx::Canvas* canvas) {
-
- // First draw the base icon.
- canvas->DrawBitmapInt(icon(), 0, 0);
-
- // If wifi, we draw the wifi signal bars.
- NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
- if (cros->wifi_connecting() ||
- (!cros->ethernet_connected() && cros->wifi_connected())) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- // We want a value between 0-1.
- // 0 reperesents no signal and 1 represents full signal strength.
- double value = cros->wifi_connecting() ?
- animation_connecting_.GetCurrentValue() :
- cros->wifi_strength() / 100.0;
- if (value < 0)
- value = 0;
- else if (value > 1)
- value = 1;
-
- // If we are animating network traffic and not connecting, then we need to
- // figure out if we are to also draw the extra image.
- int downloading_index = -1;
- int uploading_index = -1;
- if (!animation_connecting_.is_animating()) {
- // For network animation, we only show animation in one direction.
- // So when we are hiding, we just use 1 minus the value.
- // We have kNumWifiImages + 1 number of states. For the first state, where
- // we are not adding any images, we set the index to -1.
- if (animation_downloading_.is_animating()) {
- double value_downloading = animation_downloading_.IsShowing() ?
- animation_downloading_.GetCurrentValue() :
- 1.0 - animation_downloading_.GetCurrentValue();
- downloading_index = static_cast<int>(value_downloading *
- nextafter(static_cast<float>(kNumWifiImages + 1), 0)) - 1;
- }
- if (animation_uploading_.is_animating()) {
- double value_uploading = animation_uploading_.IsShowing() ?
- animation_uploading_.GetCurrentValue() :
- 1.0 - animation_uploading_.GetCurrentValue();
- uploading_index = static_cast<int>(value_uploading *
- nextafter(static_cast<float>(kNumWifiImages + 1), 0)) - 1;
- }
- }
-
- // We need to determine opacity for each of the kNumWifiImages images.
- // We split the range (0-1) into equal ranges per kNumWifiImages images.
- // For example if kNumWifiImages is 3, then [0-0.33) is the first image and
- // [0.33-0.66) is the second image and [0.66-1] is the last image.
- // For each of the image:
- // If value < the range of this image, draw at kMinOpacity opacity.
- // If value > the range of this image, draw at kMaxOpacity-1 opacity.
- // If value within the range of this image, draw at an opacity value
- // between kMinOpacity and kMaxOpacity-1 relative to where in the range
- // value is at.
- // NOTE: Use an array rather than just calculating a resource number to
- // avoid creating implicit ordering dependencies on the resource values.
- static const int kWifiUpImages[kNumWifiImages] = {
- IDR_STATUSBAR_WIFI_UP1,
- IDR_STATUSBAR_WIFI_UP2,
- IDR_STATUSBAR_WIFI_UP3,
- IDR_STATUSBAR_WIFI_UP4,
- IDR_STATUSBAR_WIFI_UP5,
- IDR_STATUSBAR_WIFI_UP6,
- IDR_STATUSBAR_WIFI_UP7,
- IDR_STATUSBAR_WIFI_UP8,
- IDR_STATUSBAR_WIFI_UP9,
- };
- static const int kWifiUpPImages[kNumWifiImages] = {
- IDR_STATUSBAR_WIFI_UP1P,
- IDR_STATUSBAR_WIFI_UP2P,
- IDR_STATUSBAR_WIFI_UP3P,
- IDR_STATUSBAR_WIFI_UP4P,
- IDR_STATUSBAR_WIFI_UP5P,
- IDR_STATUSBAR_WIFI_UP6P,
- IDR_STATUSBAR_WIFI_UP7P,
- IDR_STATUSBAR_WIFI_UP8P,
- IDR_STATUSBAR_WIFI_UP9P,
- };
- static const int kWifiDownImages[kNumWifiImages] = {
- IDR_STATUSBAR_WIFI_DOWN1,
- IDR_STATUSBAR_WIFI_DOWN2,
- IDR_STATUSBAR_WIFI_DOWN3,
- IDR_STATUSBAR_WIFI_DOWN4,
- IDR_STATUSBAR_WIFI_DOWN5,
- IDR_STATUSBAR_WIFI_DOWN6,
- IDR_STATUSBAR_WIFI_DOWN7,
- IDR_STATUSBAR_WIFI_DOWN8,
- IDR_STATUSBAR_WIFI_DOWN9,
- };
- static const int kWifiDownPImages[kNumWifiImages] = {
- IDR_STATUSBAR_WIFI_DOWN1P,
- IDR_STATUSBAR_WIFI_DOWN2P,
- IDR_STATUSBAR_WIFI_DOWN3P,
- IDR_STATUSBAR_WIFI_DOWN4P,
- IDR_STATUSBAR_WIFI_DOWN5P,
- IDR_STATUSBAR_WIFI_DOWN6P,
- IDR_STATUSBAR_WIFI_DOWN7P,
- IDR_STATUSBAR_WIFI_DOWN8P,
- IDR_STATUSBAR_WIFI_DOWN9P,
- };
-
- double value_per_image = 1.0 / kNumWifiImages;
- SkPaint paint;
- for (int i = 0; i < kNumWifiImages; i++) {
- if (value > value_per_image) {
- paint.setAlpha(kMaxOpacity - 1);
- value -= value_per_image;
- } else {
- // Map value between 0 and value_per_image to [kMinOpacity,kMaxOpacity).
- paint.setAlpha(kMinOpacity + static_cast<int>(value / value_per_image *
- nextafter(static_cast<float>(kMaxOpacity - kMinOpacity), 0)));
- // For following iterations, we want to draw at kMinOpacity.
- // So we set value to 0 here.
- value = 0;
- }
- canvas->DrawBitmapInt(*rb.GetBitmapNamed(kWifiUpImages[i]), 0, 0, paint);
- canvas->DrawBitmapInt(*rb.GetBitmapNamed(kWifiDownImages[i]), 0, 0,
- paint);
-
- // Draw network traffic downloading/uploading image if necessary.
- if (i == downloading_index) {
- canvas->DrawBitmapInt(*rb.GetBitmapNamed(kWifiDownPImages[i]), 0, 0,
- paint);
- }
- if (i == uploading_index) {
- canvas->DrawBitmapInt(*rb.GetBitmapNamed(kWifiUpPImages[i]), 0, 0,
- paint);
- }
- }
- }
-}
-*/
////////////////////////////////////////////////////////////////////////////////
// NetworkMenuButton, NetworkLibrary::Observer implementation:
@@ -372,19 +97,37 @@ void NetworkMenuButton::NetworkChanged(NetworkLibrary* cros) {
animation_connecting_.StartThrobbing(std::numeric_limits<int>::max());
SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS1));
}
+ std::string network_name = cros->wifi_connecting() ?
+ cros->wifi_name() : cros->cellular_name();
+ SetTooltipText(
+ l10n_util::GetStringF(IDS_STATUSBAR_NETWORK_CONNECTING_TOOLTIP,
+ UTF8ToWide(network_name)));
} else {
// Stop connecting animation since we are not connecting.
animation_connecting_.Stop();
// Always show the higher priority connection first. Ethernet then wifi.
- if (cros->ethernet_connected())
+ if (cros->ethernet_connected()) {
SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_WIRED));
- else if (cros->wifi_connected())
+ SetTooltipText(
+ l10n_util::GetStringF(
+ IDS_STATUSBAR_NETWORK_CONNECTED_TOOLTIP,
+ l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET)));
+ } else if (cros->wifi_connected()) {
SetIcon(IconForNetworkStrength(cros->wifi_strength(), false));
- else if (cros->cellular_connected())
+ SetTooltipText(l10n_util::GetStringF(
+ IDS_STATUSBAR_NETWORK_CONNECTED_TOOLTIP,
+ UTF8ToWide(cros->wifi_name())));
+ } else if (cros->cellular_connected()) {
SetIcon(IconForNetworkStrength(cros->cellular_strength(), false));
- else
+ SetTooltipText(l10n_util::GetStringF(
+ IDS_STATUSBAR_NETWORK_CONNECTED_TOOLTIP,
+ UTF8ToWide(cros->cellular_name())));
+ } else {
SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0));
+ SetTooltipText(l10n_util::GetString(
+ IDS_STATUSBAR_NETWORK_NO_NETWORK_TOOLTIP));
+ }
}
if (!cros->Connected() && !cros->Connecting()) {
@@ -400,211 +143,34 @@ void NetworkMenuButton::NetworkChanged(NetworkLibrary* cros) {
} else {
SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0));
SetBadge(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_WARNING));
+ SetTooltipText(l10n_util::GetString(
+ IDS_STATUSBAR_NETWORK_NO_NETWORK_TOOLTIP));
}
SchedulePaint();
}
-void NetworkMenuButton::NetworkTraffic(NetworkLibrary* cros, int traffic_type) {
-/* TODO(chocobo): Add this code back in when network traffic UI is finalized.
- if (!cros->ethernet_connected() && cros->wifi_connected() &&
- !cros->wifi_connecting()) {
- // For downloading/uploading animation, we want to force at least one cycle
- // so that it looks smooth. And if we keep downloading/uploading, we will
- // keep calling StartThrobbing which will update the cycle count back to 2.
- if (traffic_type & TRAFFIC_DOWNLOAD)
- animation_downloading_.StartThrobbing(2);
- if (traffic_type & TRAFFIC_UPLOAD)
- animation_uploading_.StartThrobbing(2);
- }
- */
-}
-
void NetworkMenuButton::SetBadge(const SkBitmap& badge) {
badge_ = badge;
}
-// static
-SkBitmap NetworkMenuButton::IconForNetworkStrength(int strength, bool black) {
- // Compose wifi icon by superimposing various icons.
- // NOTE: Use an array rather than just calculating a resource number to avoid
- // creating implicit ordering dependencies on the resource values.
- static const int kBarsImages[kNumWifiImages] = {
- IDR_STATUSBAR_NETWORK_BARS1,
- IDR_STATUSBAR_NETWORK_BARS2,
- IDR_STATUSBAR_NETWORK_BARS3,
- IDR_STATUSBAR_NETWORK_BARS4,
- IDR_STATUSBAR_NETWORK_BARS5,
- IDR_STATUSBAR_NETWORK_BARS6,
- IDR_STATUSBAR_NETWORK_BARS7,
- IDR_STATUSBAR_NETWORK_BARS8,
- IDR_STATUSBAR_NETWORK_BARS9,
- };
- static const int kBarsBlackImages[kNumWifiImages] = {
- IDR_STATUSBAR_NETWORK_BARS1_BLACK,
- IDR_STATUSBAR_NETWORK_BARS2_BLACK,
- IDR_STATUSBAR_NETWORK_BARS3_BLACK,
- IDR_STATUSBAR_NETWORK_BARS4_BLACK,
- IDR_STATUSBAR_NETWORK_BARS5_BLACK,
- IDR_STATUSBAR_NETWORK_BARS6_BLACK,
- IDR_STATUSBAR_NETWORK_BARS7_BLACK,
- IDR_STATUSBAR_NETWORK_BARS8_BLACK,
- IDR_STATUSBAR_NETWORK_BARS9_BLACK,
- };
+////////////////////////////////////////////////////////////////////////////////
+// NetworkMenuButton, NetworkMenu implementation:
- int index = static_cast<int>(strength / 100.0 *
- nextafter(static_cast<float>(kNumWifiImages), 0));
- index = std::max(std::min(index, kNumWifiImages - 1), 0);
- return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
- black ? kBarsBlackImages[index] : kBarsImages[index]);
+bool NetworkMenuButton::IsBrowserMode() const {
+ return host_->IsBrowserMode();
}
-// static
-SkBitmap NetworkMenuButton::IconForDisplay(SkBitmap icon, SkBitmap badge) {
- // Icons are 24x24.
- static const int kIconWidth = 24;
- static const int kIconHeight = 24;
- // Draw the network icon 3 pixels down to center it.
- static const int kIconX = 0;
- static const int kIconY = 3;
- // Draw badge at (14,14).
- static const int kBadgeX = 14;
- static const int kBadgeY = 14;
-
- gfx::CanvasSkia canvas(kIconWidth, kIconHeight, false);
- canvas.DrawBitmapInt(icon, kIconX, kIconY);
- if (!badge.empty())
- canvas.DrawBitmapInt(badge, kBadgeX, kBadgeY);
- return canvas.ExtractBitmap();
+gfx::NativeWindow NetworkMenuButton::GetNativeWindow() const {
+ return host_->GetNativeWindow();
}
-////////////////////////////////////////////////////////////////////////////////
-// NetworkMenuButton, views::ViewMenuDelegate implementation:
-
-void NetworkMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
- refreshing_menu_ = true;
- NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
- cros->RequestWifiScan();
- cros->UpdateSystemInfo();
- InitMenuItems();
- network_menu_.Rebuild();
- network_menu_.UpdateStates();
- refreshing_menu_ = false;
- network_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
+void NetworkMenuButton::OpenButtonOptions() const {
+ host_->OpenButtonOptions(this);
}
-void NetworkMenuButton::InitMenuItems() {
- menu_items_.clear();
- // Populate our MenuItems with the current list of wifi networks.
- NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
- // Ethernet
- string16 label = l10n_util::GetStringUTF16(
- IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
- SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK);
- SkBitmap badge = cros->ethernet_connecting() || cros->ethernet_connected() ?
- SkBitmap() : *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED);
- int flag = (cros->ethernet_connecting() || cros->ethernet_connected()) ?
- FLAG_ETHERNET | FLAG_ASSOCIATED : FLAG_ETHERNET;
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- IconForDisplay(icon, badge), std::string(), flag));
-
- // Wifi
- const WifiNetworkVector& wifi_networks = cros->wifi_networks();
- // Wifi networks ssids.
- for (size_t i = 0; i < wifi_networks.size(); ++i) {
- label = ASCIIToUTF16(wifi_networks[i].name());
- SkBitmap icon = IconForNetworkStrength(wifi_networks[i].strength(), true);
- SkBitmap badge = wifi_networks[i].encrypted() ?
- *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE) : SkBitmap();
- flag = (wifi_networks[i].name() == cros->wifi_name()) ?
- FLAG_WIFI | FLAG_ASSOCIATED : FLAG_WIFI;
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- IconForDisplay(icon, badge), wifi_networks[i].service_path(), flag));
- }
-
- // Cellular
- const CellularNetworkVector& cell_networks = cros->cellular_networks();
- // Cellular networks ssids.
- for (size_t i = 0; i < cell_networks.size(); ++i) {
- label = ASCIIToUTF16(cell_networks[i].name());
- SkBitmap icon = IconForNetworkStrength(cell_networks[i].strength(), true);
- // TODO(chocobo): Check cellular network 3g/edge.
- SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G);
-// SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_EDGE);
- flag = (cell_networks[i].name() == cros->cellular_name()) ?
- FLAG_CELLULAR | FLAG_ASSOCIATED : FLAG_CELLULAR;
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- IconForDisplay(icon, badge), cell_networks[i].service_path(), flag));
- }
-
- // No networks available message.
- if (wifi_networks.empty() && cell_networks.empty()) {
- label = l10n_util::GetStringFUTF16(IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
- l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE));
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- SkBitmap(), std::string(), FLAG_DISABLED));
- }
-
- // Other networks
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND,
- l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS),
- IconForDisplay(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0),
- SkBitmap()),
- std::string(), FLAG_OTHER_NETWORK));
-
- if (cros->wifi_available() || cros->cellular_available()) {
- // Separator.
- menu_items_.push_back(MenuItem());
-
- // Turn Wifi Off. (only if wifi available)
- if (cros->wifi_available()) {
- int id = cros->wifi_enabled() ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
- IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
- label = l10n_util::GetStringFUTF16(id,
- l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- SkBitmap(), std::string(), FLAG_TOGGLE_WIFI));
- }
-
- // Turn Cellular Off. (only if cellular available)
- if (cros->cellular_available()) {
- int id = cros->cellular_enabled() ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
- IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
- label = l10n_util::GetStringFUTF16(id,
- l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- SkBitmap(), std::string(), FLAG_TOGGLE_CELLULAR));
- }
- }
-
- // TODO(chocobo): Uncomment once we figure out how to do offline mode.
- // Offline mode.
-// menu_items_.push_back(MenuItem(cros->offline_mode() ?
-// menus::MenuModel::TYPE_CHECK : menus::MenuModel::TYPE_COMMAND,
-// l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OFFLINE_MODE),
-// SkBitmap(), std::string(), FLAG_TOGGLE_OFFLINE));
-
- if (cros->Connected() || host_->ShouldOpenButtonOptions(this)) {
- // Separator.
- menu_items_.push_back(MenuItem());
-
- // IP address
- if (cros->Connected()) {
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND,
- ASCIIToUTF16(cros->IPAddress()), SkBitmap(),
- std::string(), FLAG_DISABLED));
- }
-
- // Network settings.
- if (host_->ShouldOpenButtonOptions(this)) {
- label =
- l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG);
- menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
- SkBitmap(), std::string(), FLAG_OPTIONS));
- }
- }
+bool NetworkMenuButton::ShouldOpenButtonOptions() const {
+ return host_->ShouldOpenButtonOptions(this);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/status/network_menu_button.h b/chrome/browser/chromeos/status/network_menu_button.h
index e5325ad..bb5ff96 100644
--- a/chrome/browser/chromeos/status/network_menu_button.h
+++ b/chrome/browser/chromeos/status/network_menu_button.h
@@ -4,19 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_NETWORK_MENU_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_NETWORK_MENU_BUTTON_H_
-
-#include <string>
-#include <vector>
+#pragma once
#include "app/throb_animation.h"
#include "base/timer.h"
#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chrome/browser/chromeos/status/network_menu.h"
#include "chrome/browser/chromeos/status/status_area_button.h"
-#include "views/controls/menu/menu_2.h"
-#include "views/controls/menu/view_menu_delegate.h"
-
-class SkBitmap;
namespace gfx {
class Canvas;
@@ -51,50 +45,17 @@ class StatusAreaHost;
// <icon> will show the strength of the wifi/cellular networks.
// The label will be BOLD if the network is currently connected.
class NetworkMenuButton : public StatusAreaButton,
- public views::ViewMenuDelegate,
- public menus::MenuModel,
+ public NetworkMenu,
public NetworkLibrary::Observer {
public:
explicit NetworkMenuButton(StatusAreaHost* host);
virtual ~NetworkMenuButton();
- // menus::MenuModel implementation.
- virtual bool HasIcons() const { return true; }
- virtual int GetItemCount() const;
- virtual menus::MenuModel::ItemType GetTypeAt(int index) const;
- virtual int GetCommandIdAt(int index) const { return index; }
- virtual string16 GetLabelAt(int index) const;
- virtual bool IsLabelDynamicAt(int index) const { return true; }
- virtual const gfx::Font* GetLabelFontAt(int index) const;
- virtual bool GetAcceleratorAt(int index,
- menus::Accelerator* accelerator) const { return false; }
- virtual bool IsItemCheckedAt(int index) const;
- virtual int GetGroupIdAt(int index) const { return 0; }
- virtual bool GetIconAt(int index, SkBitmap* icon) const;
- virtual menus::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const {
- return NULL;
- }
- virtual bool IsEnabledAt(int index) const;
- virtual menus::MenuModel* GetSubmenuModelAt(int index) const { return NULL; }
- virtual void HighlightChangedTo(int index) {}
- virtual void ActivatedAt(int index);
- virtual void MenuWillShow() {}
-
// AnimationDelegate implementation.
virtual void AnimationProgressed(const Animation* animation);
// NetworkLibrary::Observer implementation.
virtual void NetworkChanged(NetworkLibrary* obj);
- virtual void NetworkTraffic(NetworkLibrary* cros, int traffic_type);
-
- // Returns the Icon for a network strength between 0 and 100.
- // |black| is used to specify whether to return a black icon for display
- // on a light background or a white icon for display on a dark background.
- static SkBitmap IconForNetworkStrength(int strength, bool black);
-
- // This method will convert the |icon| bitmap to the correct size for display.
- // If the |badge| icon is not empty, it will draw that on top of the icon.
- static SkBitmap IconForDisplay(SkBitmap icon, SkBitmap badge);
// Sets the badge icon.
void SetBadge(const SkBitmap& badge);
@@ -105,62 +66,16 @@ class NetworkMenuButton : public StatusAreaButton,
virtual void DrawPressed(gfx::Canvas* canvas);
virtual void DrawIcon(gfx::Canvas* canvas);
- private:
- enum MenuItemFlags {
- FLAG_DISABLED = 1 << 0,
- FLAG_TOGGLE_ETHERNET = 1 << 1,
- FLAG_TOGGLE_WIFI = 1 << 2,
- FLAG_TOGGLE_CELLULAR = 1 << 3,
- FLAG_TOGGLE_OFFLINE = 1 << 4,
- FLAG_ASSOCIATED = 1 << 5,
- FLAG_ETHERNET = 1 << 6,
- FLAG_WIFI = 1 << 7,
- FLAG_CELLULAR = 1 << 8,
- FLAG_OPTIONS = 1 << 9,
- FLAG_OTHER_NETWORK = 1 << 10,
- };
-
- struct MenuItem {
- MenuItem()
- : type(menus::MenuModel::TYPE_SEPARATOR),
- flags(0) {}
- MenuItem(menus::MenuModel::ItemType type, string16 label, SkBitmap icon,
- const std::string& wireless_path, int flags)
- : type(type),
- label(label),
- icon(icon),
- wireless_path(wireless_path),
- flags(flags) {}
-
- menus::MenuModel::ItemType type;
- string16 label;
- SkBitmap icon;
- std::string wireless_path;
- int flags;
- };
- typedef std::vector<MenuItem> MenuItemVector;
-
- // views::ViewMenuDelegate implementation.
- virtual void RunMenu(views::View* source, const gfx::Point& pt);
-
- // Called by RunMenu to initialize our list of menu items.
- void InitMenuItems();
-
- // Set to true if we are currently refreshing the menu.
- bool refreshing_menu_;
-
- // The number of wifi strength images.
- static const int kNumWifiImages;
-
- // Our menu items.
- MenuItemVector menu_items_;
+ // NetworkMenu implementation:
+ virtual bool IsBrowserMode() const;
+ virtual gfx::NativeWindow GetNativeWindow() const;
+ virtual void OpenButtonOptions() const;
+ virtual bool ShouldOpenButtonOptions() const;
+ private:
// The status area host,
StatusAreaHost* host_;
- // The network menu.
- views::Menu2 network_menu_;
-
// A badge icon displayed on top of the icon.
SkBitmap badge_;
diff --git a/chrome/browser/chromeos/status/power_menu_button.cc b/chrome/browser/chromeos/status/power_menu_button.cc
index de10159..de942cb 100644
--- a/chrome/browser/chromeos/status/power_menu_button.cc
+++ b/chrome/browser/chromeos/status/power_menu_button.cc
@@ -6,7 +6,9 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/string_number_conversions.h"
#include "base/time.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
@@ -22,9 +24,13 @@ const int PowerMenuButton::kNumPowerImages = 12;
PowerMenuButton::PowerMenuButton()
: StatusAreaButton(this),
- ALLOW_THIS_IN_INITIALIZER_LIST(power_menu_(this)),
- icon_id_(-1) {
- UpdateIcon();
+ battery_is_present_(false),
+ line_power_on_(false),
+ battery_fully_charged_(false),
+ battery_percentage_(0.0),
+ icon_id_(-1),
+ ALLOW_THIS_IN_INITIALIZER_LIST(power_menu_(this)) {
+ UpdateIconAndLabelInfo();
CrosLibrary::Get()->GetPowerLibrary()->AddObserver(this);
}
@@ -44,45 +50,44 @@ menus::MenuModel::ItemType PowerMenuButton::GetTypeAt(int index) const {
}
string16 PowerMenuButton::GetLabelAt(int index) const {
- PowerLibrary* cros = CrosLibrary::Get()->GetPowerLibrary();
// The first item shows the percentage of battery left.
if (index == 0) {
- // If fully charged, always show 100% even if internal number is a bit less.
- double percent = cros->battery_fully_charged() ? 100 :
- cros->battery_percentage();
return l10n_util::GetStringFUTF16(IDS_STATUSBAR_BATTERY_PERCENTAGE,
- IntToString16(static_cast<int>(percent)));
- }
-
- // The second item shows the battery is charged if it is.
- if (cros->battery_fully_charged())
- return l10n_util::GetStringUTF16(IDS_STATUSBAR_BATTERY_IS_CHARGED);
-
- // If battery is in an intermediate charge state, we show how much time left.
- base::TimeDelta time = cros->line_power_on() ? cros->battery_time_to_full() :
- cros->battery_time_to_empty();
- if (time.InSeconds() == 0) {
- // If time is 0, then that means we are still calculating how much time.
- // Depending if line power is on, we either show a message saying that we
- // are calculating time until full or calculating remaining time.
- int msg = cros->line_power_on() ?
- IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_FULL :
- IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_EMPTY;
- return l10n_util::GetStringUTF16(msg);
+ base::IntToString16(static_cast<int>(battery_percentage_)));
+ } else if (index == 1) {
+ // The second item shows the battery is charged if it is.
+ if (battery_fully_charged_)
+ return l10n_util::GetStringUTF16(IDS_STATUSBAR_BATTERY_IS_CHARGED);
+
+ // If battery is in an intermediate charge state, show how much time left.
+ base::TimeDelta time = line_power_on_ ? battery_time_to_full_ :
+ battery_time_to_empty_;
+ if (time.InSeconds() == 0) {
+ // If time is 0, then that means we are still calculating how much time.
+ // Depending if line power is on, we either show a message saying that we
+ // are calculating time until full or calculating remaining time.
+ int msg = line_power_on_ ?
+ IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_FULL :
+ IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_EMPTY;
+ return l10n_util::GetStringUTF16(msg);
+ } else {
+ // Depending if line power is on, we either show a message saying XX:YY
+ // until full or XX:YY remaining where XX is number of hours and YY is
+ // number of minutes.
+ int msg = line_power_on_ ? IDS_STATUSBAR_BATTERY_TIME_UNTIL_FULL :
+ IDS_STATUSBAR_BATTERY_TIME_UNTIL_EMPTY;
+ int hour = time.InHours();
+ int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
+ string16 hour_str = base::IntToString16(hour);
+ string16 min_str = base::IntToString16(min);
+ // Append a "0" before the minute if it's only a single digit.
+ if (min < 10)
+ min_str = ASCIIToUTF16("0") + min_str;
+ return l10n_util::GetStringFUTF16(msg, hour_str, min_str);
+ }
} else {
- // Depending if line power is on, we either show a message saying XX:YY
- // until full or XX:YY remaining where XX is number of hours and YY is
- // number of minutes.
- int msg = cros->line_power_on() ? IDS_STATUSBAR_BATTERY_TIME_UNTIL_FULL :
- IDS_STATUSBAR_BATTERY_TIME_UNTIL_EMPTY;
- int hour = time.InHours();
- int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
- string16 hour_str = IntToString16(hour);
- string16 min_str = IntToString16(min);
- // Append a "0" before the minute if it's only a single digit.
- if (min < 10)
- min_str = ASCIIToUTF16("0") + min_str;
- return l10n_util::GetStringFUTF16(msg, hour_str, min_str);
+ NOTREACHED();
+ return string16();
}
}
@@ -99,7 +104,7 @@ void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
// PowerMenuButton, PowerLibrary::Observer implementation:
void PowerMenuButton::PowerChanged(PowerLibrary* obj) {
- UpdateIcon();
+ UpdateIconAndLabelInfo();
}
////////////////////////////////////////////////////////////////////////////////
@@ -120,59 +125,74 @@ void PowerMenuButton::DrawPowerIcon(gfx::Canvas* canvas, SkBitmap icon) {
canvas->DrawBitmapInt(icon, 0, kIconVerticalPadding);
}
-void PowerMenuButton::UpdateIcon() {
+void PowerMenuButton::UpdateIconAndLabelInfo() {
PowerLibrary* cros = CrosLibrary::Get()->GetPowerLibrary();
- icon_id_ = IDR_STATUSBAR_BATTERY_UNKNOWN;
- if (CrosLibrary::Get()->EnsureLoaded()) {
- if (!cros->battery_is_present()) {
- icon_id_ = IDR_STATUSBAR_BATTERY_MISSING;
- } else if (cros->line_power_on() && cros->battery_fully_charged()) {
- icon_id_ = IDR_STATUSBAR_BATTERY_CHARGED;
- } else {
- // Get the power image depending on battery percentage. Percentage is
- // from 0 to 100, so we need to convert that to 0 to kNumPowerImages - 1.
- // NOTE: Use an array rather than just calculating a resource number to
- // avoid creating implicit ordering dependencies on the resource values.
- static const int kChargingImages[kNumPowerImages] = {
- IDR_STATUSBAR_BATTERY_CHARGING_1,
- IDR_STATUSBAR_BATTERY_CHARGING_2,
- IDR_STATUSBAR_BATTERY_CHARGING_3,
- IDR_STATUSBAR_BATTERY_CHARGING_4,
- IDR_STATUSBAR_BATTERY_CHARGING_5,
- IDR_STATUSBAR_BATTERY_CHARGING_6,
- IDR_STATUSBAR_BATTERY_CHARGING_7,
- IDR_STATUSBAR_BATTERY_CHARGING_8,
- IDR_STATUSBAR_BATTERY_CHARGING_9,
- IDR_STATUSBAR_BATTERY_CHARGING_10,
- IDR_STATUSBAR_BATTERY_CHARGING_11,
- IDR_STATUSBAR_BATTERY_CHARGING_12,
- };
- static const int kDischargingImages[kNumPowerImages] = {
- IDR_STATUSBAR_BATTERY_DISCHARGING_1,
- IDR_STATUSBAR_BATTERY_DISCHARGING_2,
- IDR_STATUSBAR_BATTERY_DISCHARGING_3,
- IDR_STATUSBAR_BATTERY_DISCHARGING_4,
- IDR_STATUSBAR_BATTERY_DISCHARGING_5,
- IDR_STATUSBAR_BATTERY_DISCHARGING_6,
- IDR_STATUSBAR_BATTERY_DISCHARGING_7,
- IDR_STATUSBAR_BATTERY_DISCHARGING_8,
- IDR_STATUSBAR_BATTERY_DISCHARGING_9,
- IDR_STATUSBAR_BATTERY_DISCHARGING_10,
- IDR_STATUSBAR_BATTERY_DISCHARGING_11,
- IDR_STATUSBAR_BATTERY_DISCHARGING_12,
- };
-
- // If fully charged, always show 100% even if percentage is a bit less.
- double percent = cros->battery_fully_charged() ?
- 100 : cros->battery_percentage();
- int index = static_cast<int>(percent / 100.0 *
- nextafter(static_cast<float>(kNumPowerImages), 0));
- index = std::max(std::min(index, kNumPowerImages - 1), 0);
- icon_id_ = cros->line_power_on() ?
- kChargingImages[index] : kDischargingImages[index];
- }
+ if (!cros)
+ return;
+
+ bool cros_loaded = CrosLibrary::Get()->EnsureLoaded();
+ if (cros_loaded) {
+ battery_is_present_ = cros->battery_is_present();
+ line_power_on_ = cros->line_power_on();
+ battery_fully_charged_ = cros->battery_fully_charged();
+ battery_percentage_ = cros->battery_percentage();
+ // If fully charged, always show 100% even if internal number is a bit less.
+ // Note: we always call cros->battery_percentage() for test predictability.
+ if (battery_fully_charged_)
+ battery_percentage_ = 100.0;
+ battery_time_to_full_ = cros->battery_time_to_full();
+ battery_time_to_empty_ = cros->battery_time_to_empty();
+ }
+
+ if (!cros_loaded) {
+ icon_id_ = IDR_STATUSBAR_BATTERY_UNKNOWN;
+ } else if (!battery_is_present_) {
+ icon_id_ = IDR_STATUSBAR_BATTERY_MISSING;
+ } else if (line_power_on_ && battery_fully_charged_) {
+ icon_id_ = IDR_STATUSBAR_BATTERY_CHARGED;
+ } else {
+ // Get the power image depending on battery percentage. Percentage is
+ // from 0 to 100, so we need to convert that to 0 to kNumPowerImages - 1.
+ // NOTE: Use an array rather than just calculating a resource number to
+ // avoid creating implicit ordering dependencies on the resource values.
+ static const int kChargingImages[kNumPowerImages] = {
+ IDR_STATUSBAR_BATTERY_CHARGING_1,
+ IDR_STATUSBAR_BATTERY_CHARGING_2,
+ IDR_STATUSBAR_BATTERY_CHARGING_3,
+ IDR_STATUSBAR_BATTERY_CHARGING_4,
+ IDR_STATUSBAR_BATTERY_CHARGING_5,
+ IDR_STATUSBAR_BATTERY_CHARGING_6,
+ IDR_STATUSBAR_BATTERY_CHARGING_7,
+ IDR_STATUSBAR_BATTERY_CHARGING_8,
+ IDR_STATUSBAR_BATTERY_CHARGING_9,
+ IDR_STATUSBAR_BATTERY_CHARGING_10,
+ IDR_STATUSBAR_BATTERY_CHARGING_11,
+ IDR_STATUSBAR_BATTERY_CHARGING_12,
+ };
+ static const int kDischargingImages[kNumPowerImages] = {
+ IDR_STATUSBAR_BATTERY_DISCHARGING_1,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_2,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_3,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_4,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_5,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_6,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_7,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_8,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_9,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_10,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_11,
+ IDR_STATUSBAR_BATTERY_DISCHARGING_12,
+ };
+
+ int index = static_cast<int>(battery_percentage_ / 100.0 *
+ nextafter(static_cast<float>(kNumPowerImages), 0));
+ index = std::max(std::min(index, kNumPowerImages - 1), 0);
+ icon_id_ = line_power_on_ ?
+ kChargingImages[index] : kDischargingImages[index];
}
+
SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id_));
+ SetTooltipText(UTF16ToWide(GetLabelAt(0)));
SchedulePaint();
}
diff --git a/chrome/browser/chromeos/status/power_menu_button.h b/chrome/browser/chromeos/status/power_menu_button.h
index 413b744..7f27333 100644
--- a/chrome/browser/chromeos/status/power_menu_button.h
+++ b/chrome/browser/chromeos/status/power_menu_button.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_POWER_MENU_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_POWER_MENU_BUTTON_H_
+#pragma once
#include "app/menus/menu_model.h"
#include "chrome/browser/chromeos/cros/power_library.h"
@@ -11,6 +12,10 @@
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/view_menu_delegate.h"
+namespace base {
+class TimeDelta;
+}
+
class SkBitmap;
namespace chromeos {
@@ -63,18 +68,27 @@ class PowerMenuButton : public StatusAreaButton,
// This method will draw the |icon| in the appropriate place on the |canvas|.
void DrawPowerIcon(gfx::Canvas* canvas, SkBitmap icon);
- // Update the power icon depending on the power status.
- void UpdateIcon();
+ // Update the power icon and menu label info depending on the power status.
+ void UpdateIconAndLabelInfo();
// The number of power images.
static const int kNumPowerImages;
- // The power menu.
- views::Menu2 power_menu_;
+ // Stored data gathered from CrosLibrary::PowerLibrary.
+ bool battery_is_present_;
+ bool line_power_on_;
+ bool battery_fully_charged_;
+ double battery_percentage_;
+ base::TimeDelta battery_time_to_full_;
+ base::TimeDelta battery_time_to_empty_;
// The currently showing icon bitmap id.
int icon_id_;
+ // The power menu. This needs to be initialized last since it calls into
+ // GetLabelAt() during construction.
+ views::Menu2 power_menu_;
+
DISALLOW_COPY_AND_ASSIGN(PowerMenuButton);
};
diff --git a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc
index 62ffab6..66042fd 100644
--- a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc
+++ b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc
@@ -22,11 +22,16 @@ using ::testing::_;
class PowerMenuButtonTest : public CrosInProcessBrowserTest {
protected:
- PowerMenuButtonTest() : CrosInProcessBrowserTest() {}
+ MockPowerLibrary *mock_power_library_;
+
+ PowerMenuButtonTest() : CrosInProcessBrowserTest(),
+ mock_power_library_(NULL) {
+ }
virtual void SetUpInProcessBrowserTestFixture() {
- InitStatusAreaMocks();
- SetStatusAreaMocksExpectations();
+ cros_mock_->InitStatusAreaMocks();
+ cros_mock_->SetStatusAreaMocksExpectations();
+ mock_power_library_ = cros_mock_->mock_power_library();
}
PowerMenuButton* GetPowerMenuButton() {
@@ -45,27 +50,70 @@ class PowerMenuButtonTest : public CrosInProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) {
EXPECT_CALL(*mock_power_library_, battery_is_present())
- .WillRepeatedly((Return(false)));
+ .WillOnce((Return(false))) // no battery
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_percentage())
+ .WillOnce((Return(42.0)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_fully_charged())
+ .WillOnce((Return(false)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, line_power_on())
+ .WillOnce((Return(false)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_empty())
+ .WillOnce((Return(base::TimeDelta::FromMinutes(42))))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_full())
+ .WillOnce((Return(base::TimeDelta::FromMinutes(24))))
+ .RetiresOnSaturation();
EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId());
}
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) {
EXPECT_CALL(*mock_power_library_, battery_is_present())
- .WillRepeatedly((Return(true)));
+ .WillOnce((Return(true)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_percentage())
+ .WillOnce((Return(42.0)))
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, battery_fully_charged())
- .WillRepeatedly((Return(true)));
+ .WillOnce((Return(true))) // fully charged
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, line_power_on())
- .WillRepeatedly((Return(true)));
+ .WillOnce((Return(true))) // plugged in
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_empty())
+ .WillOnce((Return(base::TimeDelta::FromMinutes(42))))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_full())
+ .WillOnce((Return(base::TimeDelta::FromMinutes(0))))
+ .RetiresOnSaturation();
EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId());
}
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) {
+ const int NUM_TIMES = 12; // 6 + 8*12 = 102
EXPECT_CALL(*mock_power_library_, battery_is_present())
- .WillRepeatedly((Return(true)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(true)))
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, battery_fully_charged())
- .WillRepeatedly((Return(false)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(false)))
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, line_power_on())
- .WillRepeatedly((Return(true)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(true))) // plugged in
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_empty())
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(base::TimeDelta::FromMinutes(42))))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_full())
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(base::TimeDelta::FromMinutes(24))))
+ .RetiresOnSaturation();
// Test the 12 battery charging states.
// NOTE: Use an array rather than just calculating a resource number to avoid
@@ -87,7 +135,8 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) {
size_t id = 0;
for (float percent = 6.0; percent < 100.0; percent += 8.0) {
EXPECT_CALL(*mock_power_library_, battery_percentage())
- .WillRepeatedly((Return(percent)));
+ .WillOnce((Return(percent)))
+ .RetiresOnSaturation();
ASSERT_LT(id, arraysize(kChargingImages));
EXPECT_EQ(kChargingImages[id], CallPowerChangedAndGetIconId());
id++;
@@ -95,12 +144,27 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) {
}
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryDischargingTest) {
+ const int NUM_TIMES = 12; // 6 + 8*12 = 102
EXPECT_CALL(*mock_power_library_, battery_is_present())
- .WillRepeatedly((Return(true)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(true)))
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, battery_fully_charged())
- .WillRepeatedly((Return(false)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(false)))
+ .RetiresOnSaturation();
EXPECT_CALL(*mock_power_library_, line_power_on())
- .WillRepeatedly((Return(false)));
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(false)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_empty())
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(base::TimeDelta::FromMinutes(42))))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*mock_power_library_, battery_time_to_full())
+ .Times(NUM_TIMES)
+ .WillRepeatedly((Return(base::TimeDelta::FromMinutes(24))))
+ .RetiresOnSaturation();
// Test the 12 battery discharing states.
// NOTE: Use an array rather than just calculating a resource number to avoid
@@ -122,7 +186,8 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryDischargingTest) {
size_t id = 0;
for (float percent = 6.0; percent < 100.0; percent += 8.0) {
EXPECT_CALL(*mock_power_library_, battery_percentage())
- .WillRepeatedly((Return(percent)));
+ .WillOnce((Return(percent)))
+ .RetiresOnSaturation();
ASSERT_LT(id, arraysize(kDischargingImages));
EXPECT_EQ(kDischargingImages[id], CallPowerChangedAndGetIconId());
id++;
diff --git a/chrome/browser/chromeos/status/status_area_button.cc b/chrome/browser/chromeos/status/status_area_button.cc
index 13aaad2..d2c34e6 100644
--- a/chrome/browser/chromeos/status/status_area_button.cc
+++ b/chrome/browser/chromeos/status/status_area_button.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/chromeos/status/status_area_button.h"
-#include "app/resource_bundle.h"
#include "gfx/canvas.h"
#include "gfx/skbitmap_operations.h"
#include "grit/theme_resources.h"
@@ -17,29 +16,70 @@ namespace chromeos {
// StatusAreaButton
StatusAreaButton::StatusAreaButton(views::ViewMenuDelegate* menu_delegate)
- : MenuButton(NULL, std::wstring(), menu_delegate, false) {
+ : MenuButton(NULL, std::wstring(), menu_delegate, false),
+ use_menu_button_paint_(false) {
set_border(NULL);
- SetShowHighlighted(true);
+
+ // Use an offset that is top aligned with toolbar.
+ set_menu_offset(0, 2);
}
void StatusAreaButton::Paint(gfx::Canvas* canvas, bool for_drag) {
if (state() == BS_PUSHED) {
- DrawPressed(canvas);
+ // Apply 10% white when pushed down.
+ canvas->FillRectInt(SkColorSetARGB(0x19, 0xFF, 0xFF, 0xFF),
+ 0, 0, width(), height());
+ }
+
+ if (use_menu_button_paint_) {
+ views::MenuButton::Paint(canvas, for_drag);
+ } else {
+ if (state() == BS_PUSHED)
+ DrawPressed(canvas);
+
+ DrawIcon(canvas);
+ PaintFocusBorder(canvas);
}
- DrawIcon(canvas);
- PaintFocusBorder(canvas);
}
gfx::Size StatusAreaButton::GetPreferredSize() {
// icons are 24x24
static const int kIconWidth = 24;
static const int kIconHeight = 24;
- gfx::Insets insets = GetInsets();
+ gfx::Insets insets = views::MenuButton::GetInsets();
gfx::Size prefsize(kIconWidth + insets.width(),
kIconHeight + insets.height());
+
+ // Adjusts size when use menu button paint.
+ if (use_menu_button_paint_) {
+ gfx::Size menu_button_size = views::MenuButton::GetPreferredSize();
+ prefsize.SetSize(
+ std::max(prefsize.width(), menu_button_size.width()),
+ std::max(prefsize.height(), menu_button_size.height())
+ );
+
+ // Shift 1-pixel down for odd number of pixels in vertical space.
+ if ((prefsize.height() - menu_button_size.height()) % 2) {
+ insets_.Set(insets.top() + 1, insets.left(),
+ insets.bottom(), insets.right());
+ }
+ }
+
return prefsize;
}
+gfx::Insets StatusAreaButton::GetInsets() const {
+ return insets_;
+}
+
+void StatusAreaButton::SetText(const std::wstring& text) {
+ // TextButtons normally remember the max text size, so the button's preferred
+ // size will always be as large as the largest text ever put in it.
+ // We clear that max text size, so we can adjust the size to fit the text.
+ ClearMaxTextSize();
+ views::MenuButton::SetText(text);
+}
+
void StatusAreaButton::DrawIcon(gfx::Canvas* canvas) {
canvas->DrawBitmapInt(icon(), 0, 0);
}
diff --git a/chrome/browser/chromeos/status/status_area_button.h b/chrome/browser/chromeos/status/status_area_button.h
index b751653..6d57178 100644
--- a/chrome/browser/chromeos/status/status_area_button.h
+++ b/chrome/browser/chromeos/status/status_area_button.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_BUTTON_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_BUTTON_H_
+#pragma once
#include "views/controls/button/menu_button.h"
#include "views/controls/menu/view_menu_delegate.h"
@@ -18,6 +19,15 @@ class StatusAreaButton : public views::MenuButton {
virtual ~StatusAreaButton() {}
virtual void Paint(gfx::Canvas* canvas, bool for_drag);
virtual gfx::Size GetPreferredSize();
+ virtual gfx::Insets GetInsets() const;
+
+ // Overrides TextButton's SetText to clear max text size before seting new
+ // text content so that the button size would fit the new text size.
+ virtual void SetText(const std::wstring& text);
+
+ void set_use_menu_button_paint(bool use_menu_button_paint) {
+ use_menu_button_paint_ = use_menu_button_paint;
+ }
protected:
// Draws the pressed icon. This is called before DrawIcon if the state is
@@ -30,6 +40,12 @@ class StatusAreaButton : public views::MenuButton {
// Otherwise, just call SetIcon() and the it will be handled for you.
virtual void DrawIcon(gfx::Canvas* canvas);
+ // True if the button wants to use views::MenuButton drawings.
+ bool use_menu_button_paint_;
+
+ // Insets to use for this button.
+ gfx::Insets insets_;
+
DISALLOW_COPY_AND_ASSIGN(StatusAreaButton);
};
diff --git a/chrome/browser/chromeos/status/status_area_host.h b/chrome/browser/chromeos/status/status_area_host.h
index e61cf7c..7e86e67 100644
--- a/chrome/browser/chromeos/status/status_area_host.h
+++ b/chrome/browser/chromeos/status/status_area_host.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_HOST_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_HOST_H_
+#pragma once
#include "gfx/native_widget_types.h"
diff --git a/chrome/browser/chromeos/status/status_area_view.cc b/chrome/browser/chromeos/status/status_area_view.cc
index 4f08452..27a3a54 100644
--- a/chrome/browser/chromeos/status/status_area_view.cc
+++ b/chrome/browser/chromeos/status/status_area_view.cc
@@ -19,9 +19,6 @@ namespace chromeos {
// Number of pixels to separate each icon.
const int kSeparation = 6;
-// BrowserWindowGtk tiles its image with this offset
-const int kCustomFrameBackgroundVerticalOffset = 15;
-
StatusAreaView::StatusAreaView(StatusAreaHost* host)
: host_(host),
clock_view_(NULL),
diff --git a/chrome/browser/chromeos/status/status_area_view.h b/chrome/browser/chromeos/status/status_area_view.h
index d30378b..0e4ecc3 100644
--- a/chrome/browser/chromeos/status/status_area_view.h
+++ b/chrome/browser/chromeos/status/status_area_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_STATUS_STATUS_AREA_VIEW_H_
+#pragma once
#include "base/basictypes.h"
#include "chrome/browser/views/accessible_toolbar_view.h"
diff --git a/chrome/browser/chromeos/system_key_event_listener.h b/chrome/browser/chromeos/system_key_event_listener.h
index 117a3a8..b731b94 100644
--- a/chrome/browser/chromeos/system_key_event_listener.h
+++ b/chrome/browser/chromeos/system_key_event_listener.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_KEY_EVENT_LISTENER_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_KEY_EVENT_LISTENER_H_
+#pragma once
#include "base/singleton.h"
#include "chrome/browser/chromeos/wm_message_listener.h"
diff --git a/chrome/browser/chromeos/tab_closeable_state_watcher.cc b/chrome/browser/chromeos/tab_closeable_state_watcher.cc
index d5a01b0..7b7f2cb 100644
--- a/chrome/browser/chromeos/tab_closeable_state_watcher.cc
+++ b/chrome/browser/chromeos/tab_closeable_state_watcher.cc
@@ -4,10 +4,14 @@
#include "chrome/browser/chromeos/tab_closeable_state_watcher.h"
+#include "base/command_line.h"
+#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
@@ -63,7 +67,9 @@ void TabCloseableStateWatcher::TabStripWatcher::TabChangedAt(
TabCloseableStateWatcher::TabCloseableStateWatcher()
: can_close_tab_(true),
- signing_off_(false) {
+ signing_off_(false),
+ bwsi_session_(
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kBWSI)) {
BrowserList::AddObserver(this);
notification_registrar_.Add(this, NotificationType::APP_EXITING,
NotificationService::AllSources());
@@ -71,7 +77,8 @@ TabCloseableStateWatcher::TabCloseableStateWatcher()
TabCloseableStateWatcher::~TabCloseableStateWatcher() {
BrowserList::RemoveObserver(this);
- DCHECK(tabstrip_watchers_.empty());
+ if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
+ DCHECK(tabstrip_watchers_.empty());
}
bool TabCloseableStateWatcher::CanCloseTab(const Browser* browser) const {
@@ -183,7 +190,7 @@ void TabCloseableStateWatcher::CheckAndUpdateState(
} else { // There's only 1 normal browser.
if (!browser_to_check)
browser_to_check = tabstrip_watchers_[0]->browser();
- if (browser_to_check->profile()->IsOffTheRecord()) {
+ if (browser_to_check->profile()->IsOffTheRecord() && !bwsi_session_) {
new_can_close = true;
} else {
TabStripModel* tabstrip_model = browser_to_check->tabstrip_model();
@@ -232,8 +239,8 @@ bool TabCloseableStateWatcher::CanCloseBrowserImpl(const Browser* browser,
return true;
// If last normal browser is incognito, open a non-incognito window,
- // and allow closing of incognito one.
- if (browser->profile()->IsOffTheRecord()) {
+ // and allow closing of incognito one (if not BWSI).
+ if (browser->profile()->IsOffTheRecord() && !bwsi_session_) {
*action_type = OPEN_WINDOW;
return true;
}
diff --git a/chrome/browser/chromeos/tab_closeable_state_watcher.h b/chrome/browser/chromeos/tab_closeable_state_watcher.h
index 5b786f2..9da71f2 100644
--- a/chrome/browser/chromeos/tab_closeable_state_watcher.h
+++ b/chrome/browser/chromeos/tab_closeable_state_watcher.h
@@ -4,12 +4,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_
#define CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_
+#pragma once
#include <vector>
#include "chrome/browser/browser_list.h"
#include "chrome/browser/tab_closeable_state_watcher.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/tabs/tab_strip_model_observer.h"
#include "chrome/common/notification_registrar.h"
namespace chromeos {
@@ -17,6 +18,8 @@ namespace chromeos {
// This class overrides ::TabCloseableStateWatcher to allow or disallow tabs or
// browsers to be closed based on increase or decrease in number of tabs or
// browsers. We only do this on Chromeos and only for non-tests.
+//
+// Normal session:
// 1) A tab, and hence its containing browser, is not closeable if the tab is
// the last NewTabPage in the last normal non-incognito browser and user is not
// signing off.
@@ -26,6 +29,15 @@ namespace chromeos {
// 3) Or, if user closes a normal incognito browser or the last tab in it, the
// browser closes, a new non-incognito normal browser is opened with a
// NewTabPage (which, by rule 1, will not be closeable).
+//
+// BWSI session (all browsers are incognito):
+// Almost the same as in the normal session, but
+// 1) A tab, and hence its containing browser, is not closeable if the tab is
+// the last NewTabPage in the last browser (again, all browsers are incognito
+// browsers).
+// 2-3) Otherwise, if user closes a normal incognito browser or the last tab in
+// it, the browser stays open, the existing tabs are closed, and a new
+// NewTabPage is open.
class TabCloseableStateWatcher : public ::TabCloseableStateWatcher,
public BrowserList::Observer,
@@ -86,6 +98,9 @@ class TabCloseableStateWatcher : public ::TabCloseableStateWatcher,
// allow closing of all tabs and browsers in this situation.
bool signing_off_;
+ // In BWSI session?
+ bool bwsi_session_;
+
NotificationRegistrar notification_registrar_;
// TabStripWatcher is a TabStripModelObserver that funnels all interesting
diff --git a/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc b/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc
index 3d01ab1..ea49119 100644
--- a/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc
+++ b/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc
@@ -1,16 +1,18 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/chromeos/tab_closeable_state_watcher.h"
#include "base/file_path.h"
-#include "base/logging.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
+#include "chrome/browser/native_app_modal_dialog.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
@@ -36,7 +38,8 @@ class TabCloseableStateWatcherTest : public InProcessBrowserTest {
// Wrapper for Browser::AddTabWithURL
void AddTabWithURL(Browser* browser, const GURL& url) {
browser->AddTabWithURL(url, GURL(), PageTransition::TYPED, 0,
- TabStripModel::ADD_SELECTED, NULL, std::string());
+ TabStripModel::ADD_SELECTED, NULL, std::string(),
+ &browser);
// Wait for page to finish loading.
ui_test_utils::WaitForNavigation(
&browser->GetSelectedTabContents()->controller());
@@ -280,7 +283,7 @@ IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
TabContents* tab_contents = browser()->GetSelectedTabContents();
browser()->CloseWindow();
AppModalDialog* confirm = ui_test_utils::WaitForAppModalDialog();
- confirm->CancelWindow();
+ confirm->native_dialog()->CancelAppModalDialog();
ui_test_utils::RunAllPendingInMessageLoop();
EXPECT_EQ(1u, BrowserList::size());
EXPECT_EQ(browser(), *(BrowserList::begin()));
@@ -290,7 +293,7 @@ IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
// Close the browser.
browser()->CloseWindow();
confirm = ui_test_utils::WaitForAppModalDialog();
- confirm->AcceptWindow();
+ confirm->native_dialog()->AcceptAppModalDialog();
ui_test_utils::RunAllPendingInMessageLoop();
}
@@ -306,7 +309,7 @@ IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
// Close browser, click OK in BeforeUnload confirm dialog.
browser()->CloseWindow();
AppModalDialog* confirm = ui_test_utils::WaitForAppModalDialog();
- confirm->AcceptWindow();
+ confirm->native_dialog()->AcceptAppModalDialog();
NewTabObserver new_tab_observer(browser());
EXPECT_EQ(1u, BrowserList::size());
EXPECT_EQ(browser(), *(BrowserList::begin()));
@@ -315,4 +318,3 @@ IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
}
} // namespace chromeos
-
diff --git a/chrome/browser/chromeos/testdata/services_manifest.json b/chrome/browser/chromeos/testdata/services_manifest.json
deleted file mode 100644
index 5efb835..0000000
--- a/chrome/browser/chromeos/testdata/services_manifest.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- // Required.
- "version": "1.0",
- "app_menu" : {
- "section_title" : "A partner application menu section title.",
- "web_apps" : [
- "http://localhost/a/1",
- "http://localhost/a/2",
- ],
- "support_page": "http://localhost/h",
- "extensions": [
- "http://localhost/e/1",
- "http://localhost/e/2",
- ],
- },
-
- // Optional.
- "initial_start_page": "http://localhost",
-}
diff --git a/chrome/browser/chromeos/testdata/startup_manifest.json b/chrome/browser/chromeos/testdata/startup_manifest.json
deleted file mode 100644
index 25521a2..0000000
--- a/chrome/browser/chromeos/testdata/startup_manifest.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- // Required.
- "version": "1.0",
- "product_sku" : "SKU",
-
- // Optional.
- "initial_locale" : "ru",
- "initial_timezone" : "Asia/Tokyo",
- "background_color" : "#880088",
- "registration_url" : "http://www.google.com",
- "setup_content" : [
- {
- "content_locale" : "en_US",
- "help_page" : "setup_content/en_US/help.html",
- "eula_page" : "setup_content/en_US/eula.html",
- },
- {
- "content_locale" : "ru",
- "help_page" : "setup_content/ru/help.html",
- "eula_page" : "setup_content/ru/eula.html",
- },
- ]
-}
diff --git a/chrome/browser/chromeos/update_browsertest.cc b/chrome/browser/chromeos/update_browsertest.cc
index 9dca0bb..bbb67c3 100644
--- a/chrome/browser/chromeos/update_browsertest.cc
+++ b/chrome/browser/chromeos/update_browsertest.cc
@@ -4,13 +4,13 @@
#include "base/ref_counted.h"
#include "base/utf_string_conversions.h"
-#include "chrome/test/automation/dom_element_proxy.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
-#include "chrome/browser/chromeos/update_observer.h"
#include "chrome/browser/chromeos/cros/mock_update_library.h"
+#include "chrome/browser/chromeos/update_observer.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
+#include "chrome/test/automation/dom_element_proxy.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
@@ -34,7 +34,7 @@ void CallObservers(chromeos::MockUpdateLibrary* lib,
.WillRepeatedly((ReturnRef(x)))
.RetiresOnSaturation();
FOR_EACH_OBSERVER(chromeos::UpdateLibrary::Observer, *observers,
- Changed(lib));
+ UpdateStatusChanged(lib));
}
void FireSuccessSequence(chromeos::MockUpdateLibrary* lib,
diff --git a/chrome/browser/chromeos/update_observer.cc b/chrome/browser/chromeos/update_observer.cc
index ac1af56..60bd1e8 100644
--- a/chrome/browser/chromeos/update_observer.cc
+++ b/chrome/browser/chromeos/update_observer.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/chromeos/update_observer.h"
#include "app/l10n_util.h"
-#include "base/string_util.h"
+#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/time_format.h"
#include "grit/generated_resources.h"
@@ -15,52 +15,22 @@ namespace chromeos {
UpdateObserver::UpdateObserver(Profile* profile)
: notification_(profile, "update.chromeos", IDR_NOTIFICATION_UPDATE,
- l10n_util::GetStringUTF16(IDS_UPDATE_TITLE)),
- progress_(-1) {}
+ l10n_util::GetStringUTF16(IDS_UPDATE_TITLE)) {}
UpdateObserver::~UpdateObserver() {
notification_.Hide();
}
-void UpdateObserver::Changed(UpdateLibrary* object) {
- switch (object->status().status) {
- case UPDATE_STATUS_ERROR:
- notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_ERROR), true);
- break;
- case UPDATE_STATUS_IDLE:
- case UPDATE_STATUS_CHECKING_FOR_UPDATE:
- // Do nothing in these cases, we don't want to notify the user of the
- // check unless there is an update. We don't hide here because
- // we want the final state to be sticky.
- break;
- case UPDATE_STATUS_UPDATE_AVAILABLE:
- notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE),
- false);
- break;
- case UPDATE_STATUS_DOWNLOADING:
- {
- int progress = static_cast<int>(object->status().download_progress *
- 100.0);
- if (progress != progress_) {
- progress_ = progress;
- notification_.Show(l10n_util::GetStringFUTF16(IDS_UPDATE_DOWNLOADING,
- IntToString16(progress_)), false);
- }
- }
- break;
- case UPDATE_STATUS_VERIFYING:
- notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING),
- false);
- break;
- case UPDATE_STATUS_FINALIZING:
- notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING),
- false);
- break;
- case UPDATE_STATUS_UPDATED_NEED_REBOOT:
- notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED), true);
- break;
+void UpdateObserver::UpdateStatusChanged(UpdateLibrary* library) {
+#if 0
+ // TODO seanparent@chromium.org : This update should only be shown when an
+ // update is critical and should include a restart button using the
+ // update_engine restart API. Currently removed entirely per Kan's request.
+
+ if (library->status().status == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+ notification_.Show(l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED), true);
}
+#endif
}
} // namespace chromeos
-
diff --git a/chrome/browser/chromeos/update_observer.h b/chrome/browser/chromeos/update_observer.h
index e199958..3ec372b 100644
--- a/chrome/browser/chromeos/update_observer.h
+++ b/chrome/browser/chromeos/update_observer.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_UPDATE_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_UPDATE_OBSERVER_H_
+#pragma once
#include "base/basictypes.h"
#include "base/time.h"
@@ -23,10 +24,9 @@ class UpdateObserver : public UpdateLibrary::Observer {
virtual ~UpdateObserver();
private:
- virtual void Changed(UpdateLibrary* object);
+ virtual void UpdateStatusChanged(UpdateLibrary* library);
SystemNotification notification_;
- int progress_; // Last displayed remaining time in minutes
DISALLOW_COPY_AND_ASSIGN(UpdateObserver);
};
diff --git a/chrome/browser/chromeos/usb_mount_observer.cc b/chrome/browser/chromeos/usb_mount_observer.cc
index d0e329f..fbfb501 100644
--- a/chrome/browser/chromeos/usb_mount_observer.cc
+++ b/chrome/browser/chromeos/usb_mount_observer.cc
@@ -8,8 +8,10 @@
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/dom_ui/filebrowse_ui.h"
-#include "chrome/browser/pref_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
namespace chromeos {
@@ -52,7 +54,11 @@ void USBMountObserver::OpenFileBrowse(const std::string& url,
bool small) {
Browser* browser;
Profile* profile;
- profile = BrowserList::GetLastActive()->profile();
+ browser = BrowserList::GetLastActive();
+ if (browser == NULL) {
+ return;
+ }
+ profile = browser->profile();
PrefService* pref_service = profile->GetPrefs();
if (!pref_service->GetBoolean(prefs::kLabsAdvancedFilesystemEnabled)) {
return;
diff --git a/chrome/browser/chromeos/usb_mount_observer.h b/chrome/browser/chromeos/usb_mount_observer.h
index 1dd78d3..5f30b31 100644
--- a/chrome/browser/chromeos/usb_mount_observer.h
+++ b/chrome/browser/chromeos/usb_mount_observer.h
@@ -4,15 +4,16 @@
#ifndef CHROME_BROWSER_CHROMEOS_USB_MOUNT_OBSERVER_H_
#define CHROME_BROWSER_CHROMEOS_USB_MOUNT_OBSERVER_H_
+#pragma once
#include <string>
#include <vector>
#include "chrome/browser/chromeos/cros/mount_library.h"
#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
-#include "chrome/common/notification_registrar.h"
class Browser;
class Profile;
diff --git a/chrome/browser/chromeos/usb_mount_observer_browsertest.cc b/chrome/browser/chromeos/usb_mount_observer_browsertest.cc
index 3621067..e6a5c99 100644
--- a/chrome/browser/chromeos/usb_mount_observer_browsertest.cc
+++ b/chrome/browser/chromeos/usb_mount_observer_browsertest.cc
@@ -4,7 +4,6 @@
#include "base/ref_counted.h"
#include "base/utf_string_conversions.h"
-#include "chrome/test/automation/dom_element_proxy.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chromeos/cros/mock_mount_library.h"
@@ -12,6 +11,7 @@
#include "chrome/browser/dom_ui/mediaplayer_ui.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
+#include "chrome/test/automation/dom_element_proxy.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
diff --git a/chrome/browser/chromeos/version_loader.cc b/chrome/browser/chromeos/version_loader.cc
index 9475205..e24b357 100644
--- a/chrome/browser/chromeos/version_loader.cc
+++ b/chrome/browser/chromeos/version_loader.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -9,6 +9,7 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
+#include "base/string_split.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/chromeos/version_loader.h b/chrome/browser/chromeos/version_loader.h
index c7072b5..0e5acb5 100644
--- a/chrome/browser/chromeos/version_loader.h
+++ b/chrome/browser/chromeos/version_loader.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_VERSION_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_VERSION_LOADER_H_
+#pragma once
#include <string>
diff --git a/chrome/browser/chromeos/view_ids.h b/chrome/browser/chromeos/view_ids.h
index 8f0e016..f8b2794 100644
--- a/chrome/browser/chromeos/view_ids.h
+++ b/chrome/browser/chromeos/view_ids.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_VIEW_IDS_H_
#define CHROME_BROWSER_CHROMEOS_VIEW_IDS_H_
+#pragma once
#include "chrome/browser/view_ids.h"
@@ -12,7 +13,6 @@ enum ChromeOSViewIds {
// Start with the offset that is big enough to avoid possible
// collison.
VIEW_ID_STATUS_AREA = VIEW_ID_PREDEFINED_COUNT + 10000,
- VIEW_ID_OTR_AVATAR,
};
#endif // CHROME_BROWSER_CHROMEOS_VIEW_IDS_H_
diff --git a/chrome/browser/chromeos/volume_bubble.cc b/chrome/browser/chromeos/volume_bubble.cc
index 9b7543a..6c71fb3 100644
--- a/chrome/browser/chromeos/volume_bubble.cc
+++ b/chrome/browser/chromeos/volume_bubble.cc
@@ -17,7 +17,7 @@ const int kBubbleShowTimeoutSec = 2;
const int kAnimationDurationMs = 200;
// Horizontal relative position: 0 - leftmost, 0.5 - center, 1 - rightmost.
-const double kVolumeBubbleXRatio = 0.18;
+const double kVolumeBubbleXRatio = 0.5;
// Vertical gap from the bottom of the screen in pixels.
const int kVolumeBubbleBottomGap = 30;
diff --git a/chrome/browser/chromeos/volume_bubble.h b/chrome/browser/chromeos/volume_bubble.h
index 90bb034..c2da38e 100644
--- a/chrome/browser/chromeos/volume_bubble.h
+++ b/chrome/browser/chromeos/volume_bubble.h
@@ -4,8 +4,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_H_
#define CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_H_
+#pragma once
-#include "app/active_window_watcher_x.h"
#include "app/slide_animation.h"
#include "base/singleton.h"
#include "chrome/browser/views/info_bubble.h"
diff --git a/chrome/browser/chromeos/volume_bubble_view.cc b/chrome/browser/chromeos/volume_bubble_view.cc
index 5aa99c1..7bb500f 100644
--- a/chrome/browser/chromeos/volume_bubble_view.cc
+++ b/chrome/browser/chromeos/volume_bubble_view.cc
@@ -6,8 +6,8 @@
#include <string>
-#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/logging.h"
#include "gfx/canvas.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
diff --git a/chrome/browser/chromeos/volume_bubble_view.h b/chrome/browser/chromeos/volume_bubble_view.h
index fbf77d2..f9ec0b0 100644
--- a/chrome/browser/chromeos/volume_bubble_view.h
+++ b/chrome/browser/chromeos/volume_bubble_view.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_VIEW_H_
+#pragma once
#include "views/view.h"
diff --git a/chrome/browser/chromeos/wm_ipc.cc b/chrome/browser/chromeos/wm_ipc.cc
index 1bb9a52..1dd0af5 100644
--- a/chrome/browser/chromeos/wm_ipc.cc
+++ b/chrome/browser/chromeos/wm_ipc.cc
@@ -11,8 +11,8 @@ extern "C" {
#include "app/x11_util.h"
#include "base/logging.h"
-#include "base/singleton.h"
#include "base/scoped_ptr.h"
+#include "base/singleton.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/wm_ipc.h b/chrome/browser/chromeos/wm_ipc.h
index 6161749..92fef71 100644
--- a/chrome/browser/chromeos/wm_ipc.h
+++ b/chrome/browser/chromeos/wm_ipc.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_IPC_H_
#define CHROME_BROWSER_CHROMEOS_WM_IPC_H_
+#pragma once
#include <gtk/gtk.h>
#include <map>
diff --git a/chrome/browser/chromeos/wm_message_listener.h b/chrome/browser/chromeos/wm_message_listener.h
index 5972889..f389c4c 100644
--- a/chrome/browser/chromeos/wm_message_listener.h
+++ b/chrome/browser/chromeos/wm_message_listener.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_MESSAGE_LISTENER_H_
#define CHROME_BROWSER_CHROMEOS_WM_MESSAGE_LISTENER_H_
+#pragma once
#include <gtk/gtk.h>
diff --git a/chrome/browser/chromeos/wm_overview_controller.cc b/chrome/browser/chromeos/wm_overview_controller.cc
index 5e40520..8fbd74f 100644
--- a/chrome/browser/chromeos/wm_overview_controller.cc
+++ b/chrome/browser/chromeos/wm_overview_controller.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/tab_contents/thumbnail_generator.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/common/notification_service.h"
#include "views/widget/root_view.h"
diff --git a/chrome/browser/chromeos/wm_overview_controller.h b/chrome/browser/chromeos/wm_overview_controller.h
index 19a4ed0..c007b72 100644
--- a/chrome/browser/chromeos/wm_overview_controller.h
+++ b/chrome/browser/chromeos/wm_overview_controller.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_CONTROLLER_H_
+#pragma once
#include <vector>
diff --git a/chrome/browser/chromeos/wm_overview_fav_icon.cc b/chrome/browser/chromeos/wm_overview_fav_icon.cc
index 0568932..dea1b0e 100644
--- a/chrome/browser/chromeos/wm_overview_fav_icon.cc
+++ b/chrome/browser/chromeos/wm_overview_fav_icon.cc
@@ -9,8 +9,8 @@
#include "app/x11_util.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/chromeos/wm_overview_snapshot.h"
-#include "skia/ext/image_operations.h"
#include "cros/chromeos_wm_ipc_enums.h"
+#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
diff --git a/chrome/browser/chromeos/wm_overview_fav_icon.h b/chrome/browser/chromeos/wm_overview_fav_icon.h
index 0d22498..d4b4427 100644
--- a/chrome/browser/chromeos/wm_overview_fav_icon.h
+++ b/chrome/browser/chromeos/wm_overview_fav_icon.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_FAV_ICON_H_
#define CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_FAV_ICON_H_
+#pragma once
#include "views/widget/widget_gtk.h"
diff --git a/chrome/browser/chromeos/wm_overview_snapshot.h b/chrome/browser/chromeos/wm_overview_snapshot.h
index 1257866..d6eeee0 100644
--- a/chrome/browser/chromeos/wm_overview_snapshot.h
+++ b/chrome/browser/chromeos/wm_overview_snapshot.h
@@ -4,11 +4,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_SNAPSHOT_H_
#define CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_SNAPSHOT_H_
+#pragma once
#include "third_party/skia/include/core/SkBitmap.h"
+#include "views/controls/image_view.h"
#include "views/view.h"
#include "views/widget/widget_gtk.h"
-#include "views/controls/image_view.h"
class Browser;
diff --git a/chrome/browser/chromeos/wm_overview_title.cc b/chrome/browser/chromeos/wm_overview_title.cc
index 2c21bc6..0325065 100644
--- a/chrome/browser/chromeos/wm_overview_title.cc
+++ b/chrome/browser/chromeos/wm_overview_title.cc
@@ -8,6 +8,7 @@
#include "app/x11_util.h"
#include "base/string16.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/drop_shadow_label.h"
@@ -42,9 +43,9 @@ namespace {
// given value (well, unless the font at size 1 is taller than the
// given value).
Font FindFontThisHigh(int pixels, Font base) {
- Font font = Font::CreateFont(base.FontName(), 1);
+ Font font(base.GetFontName(), 1);
Font last_font = font;
- while (font.height() < pixels) {
+ while (font.GetHeight() < pixels) {
last_font = font;
font = font.DeriveFont(1, Font::BOLD);
}
diff --git a/chrome/browser/chromeos/wm_overview_title.h b/chrome/browser/chromeos/wm_overview_title.h
index 90e4bd5..b145432 100644
--- a/chrome/browser/chromeos/wm_overview_title.h
+++ b/chrome/browser/chromeos/wm_overview_title.h
@@ -4,6 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_TITLE_H_
#define CHROME_BROWSER_CHROMEOS_WM_OVERVIEW_TITLE_H_
+#pragma once
#include "base/string16.h"
#include "views/widget/widget_gtk.h"