From 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 25 Nov 2010 19:40:10 +0000 Subject: Merge Chromium at r66597: Initial merge by git. Change-Id: I9639f8a997f90ec219573aa22a49f5dbde78cc7b --- AUTHORS | 3 + base/base.gyp | 3 + base/base.gypi | 17 +- base/base_paths_mac.mm | 5 +- base/command_line.cc | 21 +- base/command_line_unittest.cc | 27 +- base/crypto/encryptor.h | 7 +- base/crypto/encryptor_nss.cc | 3 - base/crypto/encryptor_openssl.cc | 108 +- base/crypto/encryptor_unittest.cc | 122 + base/crypto/encryptor_win.cc | 2 + base/crypto/rsa_private_key.h | 11 +- base/crypto/rsa_private_key_openssl.cc | 111 +- base/crypto/symmetric_key.h | 18 +- base/crypto/symmetric_key_openssl.cc | 59 +- base/crypto/symmetric_key_unittest.cc | 149 +- base/file_path.cc | 2 +- base/file_util_mac.mm | 2 +- base/file_util_posix.cc | 4 +- base/i18n/rtl.cc | 16 - base/i18n/rtl.h | 7 +- base/logging.cc | 11 + base/mac_util.h | 1 + base/mac_util.mm | 25 +- base/message_loop.cc | 12 +- base/message_pump_glib_x.cc | 143 +- base/message_pump_glib_x.h | 22 + base/native_library.h | 4 +- base/native_library_linux.cc | 4 + base/native_library_mac.mm | 3 +- base/native_library_win.cc | 4 + base/openssl_util.cc | 88 + base/openssl_util.h | 33 +- base/path_service.cc | 8 + base/path_service.h | 5 + base/pickle.cc | 16 +- base/pickle.h | 4 +- base/pickle_unittest.cc | 33 + base/platform_thread_posix.cc | 8 +- base/process_util.h | 8 - base/safe_strerror_posix.cc | 9 +- base/scoped_native_library.cc | 44 + base/scoped_native_library.h | 36 +- base/scoped_ptr.h | 4 +- base/scoped_vector.h | 1 + base/shared_memory.h | 8 +- base/shared_memory_win.cc | 9 +- base/singleton.h | 8 +- base/string16_unittest.cc | 2 +- base/string_split.cc | 57 + base/string_split.h | 15 + base/string_split_unittest.cc | 32 + base/string_util.cc | 57 - base/string_util.h | 30 +- base/string_util_unittest.cc | 32 - base/stringize_macros.h | 57 + base/stringize_macros_unittest.cc | 59 + base/stringprintf.h | 2 - base/thread_local.h | 15 +- base/thread_local_posix.cc | 4 + base/thread_local_win.cc | 4 + base/time_mac.cc | 4 +- base/time_unittest.cc | 13 + base/tuple.h | 7 + base/version.cc | 4 +- base/win/i18n.cc | 169 ++ base/win/i18n.h | 32 + base/win/i18n_unittest.cc | 42 + build/all.gyp | 1 + build/build_config.h | 6 + build/common.gypi | 34 +- build/linux/pkg-config-wrapper | 4 +- build/linux/system.gyp | 32 +- chrome/browser/DEPS | 1 + chrome/browser/about_flags.cc | 90 +- chrome/browser/about_flags_unittest.cc | 5 + .../accessibility/accessibility_win_browsertest.cc | 2 +- .../accessibility/browser_accessibility_win.cc | 6 +- .../accessibility/browser_accessibility_win.h | 2 +- .../browser_views_accessibility_browsertest.cc | 2 +- chrome/browser/aeropeek_manager.cc | 5 +- chrome/browser/app_controller_mac.mm | 2 +- chrome/browser/autocomplete/autocomplete.cc | 6 +- chrome/browser/autocomplete/autocomplete.h | 26 +- .../autocomplete/autocomplete_browsertest.cc | 4 +- .../autocomplete/autocomplete_classifier.cc | 4 +- .../browser/autocomplete/autocomplete_classifier.h | 16 +- chrome/browser/autocomplete/autocomplete_edit.cc | 19 +- chrome/browser/autocomplete/autocomplete_edit.h | 9 +- .../autocomplete/autocomplete_edit_unittest.cc | 2 + .../browser/autocomplete/autocomplete_edit_view.h | 4 + .../autocomplete_edit_view_browsertest.cc | 28 +- .../autocomplete/autocomplete_edit_view_gtk.cc | 26 +- .../autocomplete/autocomplete_edit_view_gtk.h | 5 +- .../autocomplete/autocomplete_edit_view_mac.h | 2 + .../autocomplete/autocomplete_edit_view_mac.mm | 4 + .../autocomplete/autocomplete_edit_view_win.cc | 17 + .../autocomplete/autocomplete_edit_view_win.h | 4 +- .../autocomplete/autocomplete_popup_model.cc | 2 +- .../browser/autocomplete/autocomplete_unittest.cc | 108 +- .../history_contents_provider_unittest.cc | 15 +- .../history_quick_provider_unittest.cc | 2 +- .../autocomplete/history_url_provider_unittest.cc | 4 +- chrome/browser/autocomplete/keyword_provider.cc | 21 +- chrome/browser/autocomplete/keyword_provider.h | 5 +- .../autocomplete/keyword_provider_unittest.cc | 2 +- chrome/browser/autocomplete/search_provider.cc | 25 +- .../autocomplete/search_provider_unittest.cc | 23 +- chrome/browser/autocomplete_history_manager.cc | 24 +- chrome/browser/autocomplete_history_manager.h | 4 +- chrome/browser/autofill/autofill_browsertest.cc | 4 +- .../autofill_dialog_controller_mac_unittest.mm | 2 +- chrome/browser/autofill/autofill_dialog_gtk.cc | 4 +- chrome/browser/autofill/autofill_download.cc | 4 +- .../autofill/autofill_ie_toolbar_import_win.cc | 9 +- .../autofill_ie_toolbar_import_win_unittest.cc | 12 +- chrome/browser/autofill/autofill_manager.cc | 65 +- chrome/browser/autofill/autofill_manager.h | 3 +- .../browser/autofill/autofill_manager_unittest.cc | 273 ++- chrome/browser/autofill/autofill_profile.cc | 5 + chrome/browser/autofill/autofill_profile.h | 5 + chrome/browser/autofill/credit_card.cc | 25 +- chrome/browser/autofill/credit_card.h | 6 +- chrome/browser/autofill/form_group.cc | 10 + chrome/browser/autofill/form_group.h | 3 + chrome/browser/autofill/form_structure.cc | 55 +- chrome/browser/autofill/form_structure.h | 19 +- chrome/browser/autofill/form_structure_unittest.cc | 48 +- chrome/browser/autofill/personal_data_manager.cc | 87 +- chrome/browser/autofill/personal_data_manager.h | 3 +- .../autofill/personal_data_manager_unittest.cc | 704 +++++- .../automation/automation_browser_tracker.h | 2 +- chrome/browser/automation/automation_provider.cc | 4 +- chrome/browser/automation/automation_provider.h | 10 +- .../browser/automation/automation_provider_gtk.cc | 2 +- .../browser/automation/automation_provider_json.cc | 2 +- .../browser/automation/automation_provider_mac.mm | 2 +- .../automation/automation_provider_observers.cc | 104 +- .../automation/automation_provider_observers.h | 61 +- .../browser/automation/automation_provider_win.cc | 2 +- .../automation_resource_message_filter.cc | 2 +- .../automation/automation_resource_tracker.cc | 2 +- .../automation/chrome_frame_automation_provider.cc | 2 +- .../browser/automation/extension_port_container.cc | 2 +- .../automation/testing_automation_provider.cc | 54 +- .../automation/testing_automation_provider.h | 9 +- .../testing_automation_provider_views.cc | 2 +- chrome/browser/automation/ui_controls_linux.cc | 2 +- .../automation/url_request_automation_job.cc | 2 +- chrome/browser/back_forward_menu_model.cc | 11 +- chrome/browser/back_forward_menu_model.h | 6 +- chrome/browser/background_contents_service.cc | 102 +- chrome/browser/background_contents_service.h | 44 +- .../background_contents_service_unittest.cc | 21 +- chrome/browser/background_mode_manager.cc | 2 +- chrome/browser/blocked_plugin_manager.cc | 91 - chrome/browser/blocked_plugin_manager.h | 40 - .../bookmarks/bookmark_context_menu_controller.cc | 2 +- chrome/browser/bookmarks/bookmark_model.cc | 4 +- .../browser/bookmarks/bookmark_model_unittest.cc | 3 +- chrome/browser/bookmarks/bookmark_utils.cc | 30 +- chrome/browser/bookmarks/bookmark_utils.h | 13 +- chrome/browser/browser_about_handler.cc | 37 +- chrome/browser/browser_browsertest.cc | 10 +- chrome/browser/browser_commands_unittest.cc | 4 +- chrome/browser/browser_focus_uitest.cc | 24 +- chrome/browser/browser_init.cc | 1035 -------- chrome/browser/browser_init.h | 13 - chrome/browser/browser_keyevents_browsertest.cc | 2 +- chrome/browser/browser_main.cc | 121 +- chrome/browser/browser_main_gtk.cc | 62 +- chrome/browser/browser_main_gtk.h | 14 + chrome/browser/browser_main_posix.cc | 9 - chrome/browser/browser_main_win.cc | 21 +- chrome/browser/browser_navigator.cc | 382 --- chrome/browser/browser_navigator.h | 13 - chrome/browser/browser_process.h | 3 + chrome/browser/browser_process_impl.cc | 22 +- chrome/browser/browser_process_impl.h | 5 + chrome/browser/browser_resources.grd | 1 + chrome/browser/browser_uitest.cc | 4 +- chrome/browser/browsing_data_remover.cc | 5 +- chrome/browser/bug_report_data.cc | 2 +- .../child_process_security_policy_browsertest.cc | 4 +- chrome/browser/chrome_browser_application_mac.mm | 43 +- chrome/browser/chromeos/browser_main_chromeos.h | 6 +- chrome/browser/chromeos/cros/cros_mock.cc | 16 +- chrome/browser/chromeos/cros/cryptohome_library.cc | 10 + chrome/browser/chromeos/cros/network_library.cc | 256 +- chrome/browser/chromeos/cros/network_library.h | 36 +- chrome/browser/chromeos/cros_settings.cc | 42 +- .../chromeos/cros_settings_provider_proxy.cc | 328 --- .../chromeos/cros_settings_provider_proxy.h | 50 - .../chromeos/cros_settings_provider_stats.cc | 66 - .../chromeos/cros_settings_provider_stats.h | 41 - .../chromeos/cros_settings_provider_user.cc | 298 --- .../browser/chromeos/cros_settings_provider_user.h | 76 - .../chromeos/dom_ui/accounts_options_handler.cc | 2 +- .../chromeos/dom_ui/internet_options_handler.cc | 129 +- .../chromeos/dom_ui/internet_options_handler.h | 9 +- chrome/browser/chromeos/dom_ui/labs_handler.cc | 38 - chrome/browser/chromeos/dom_ui/labs_handler.h | 24 - .../chromeos/dom_ui/language_options_handler.cc | 21 +- chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc | 297 ++- chrome/browser/chromeos/dom_ui/network_menu_ui.cc | 15 +- chrome/browser/chromeos/dom_ui/proxy_handler.cc | 4 +- .../chromeos/dom_ui/stats_options_handler.cc | 2 +- .../chromeos/dom_ui/system_settings_provider.cc | 216 +- chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc | 2 +- chrome/browser/chromeos/frame/browser_view.cc | 26 +- chrome/browser/chromeos/frame/browser_view.h | 16 + chrome/browser/chromeos/frame/bubble_frame_view.cc | 79 +- chrome/browser/chromeos/frame/bubble_frame_view.h | 6 + chrome/browser/chromeos/frame/bubble_window.cc | 14 + chrome/browser/chromeos/frame/bubble_window.h | 6 +- chrome/browser/chromeos/frame/panel_controller.cc | 2 +- .../chromeos/input_method/candidate_window.cc | 155 +- .../chromeos/input_method/candidate_window.gyp | 2 + .../chromeos/input_method/candidate_window.h | 37 + .../chromeos/input_method/candidate_window_main.cc | 80 + .../chromeos/input_method/input_method_util.cc | 2 +- .../chromeos/login/account_creation_view.cc | 4 +- .../browser/chromeos/login/auth_attempt_state.cc | 26 +- chrome/browser/chromeos/login/auth_attempt_state.h | 14 +- chrome/browser/chromeos/login/background_view.cc | 4 + chrome/browser/chromeos/login/background_view.h | 3 + chrome/browser/chromeos/login/cryptohome_op.cc | 1 + .../chromeos/login/cryptohome_op_unittest.cc | 2 +- chrome/browser/chromeos/login/eula_view.cc | 19 +- .../chromeos/login/existing_user_controller.cc | 17 +- .../chromeos/login/existing_user_controller.h | 1 + .../browser/chromeos/login/google_authenticator.cc | 18 +- .../browser/chromeos/login/google_authenticator.h | 10 +- .../login/google_authenticator_unittest.cc | 47 +- chrome/browser/chromeos/login/guest_user_view.cc | 15 +- chrome/browser/chromeos/login/helper.cc | 20 + chrome/browser/chromeos/login/helper.h | 28 +- .../browser/chromeos/login/language_switch_menu.cc | 5 +- chrome/browser/chromeos/login/login_browsertest.cc | 2 +- chrome/browser/chromeos/login/login_html_dialog.cc | 43 +- chrome/browser/chromeos/login/login_html_dialog.h | 14 +- chrome/browser/chromeos/login/login_performer.cc | 2 +- chrome/browser/chromeos/login/login_utils.cc | 68 +- .../chromeos/login/network_screen_browsertest.cc | 14 +- .../chromeos/login/network_selection_view.cc | 11 +- .../chromeos/login/network_selection_view.h | 6 +- chrome/browser/chromeos/login/new_user_view.cc | 34 +- chrome/browser/chromeos/login/new_user_view.h | 1 + chrome/browser/chromeos/login/online_attempt.cc | 40 +- chrome/browser/chromeos/login/online_attempt.h | 6 +- .../chromeos/login/online_attempt_unittest.cc | 64 +- chrome/browser/chromeos/login/owner_manager.cc | 9 + .../chromeos/login/parallel_authenticator.cc | 18 +- .../chromeos/login/parallel_authenticator.h | 8 +- .../login/parallel_authenticator_unittest.cc | 10 +- .../chromeos/login/password_changed_view.cc | 33 +- .../browser/chromeos/login/password_changed_view.h | 9 +- chrome/browser/chromeos/login/screen_lock_view.cc | 13 +- chrome/browser/chromeos/login/screen_lock_view.h | 2 +- chrome/browser/chromeos/login/screen_locker.cc | 48 +- chrome/browser/chromeos/login/screen_locker.h | 2 +- .../chromeos/login/screen_locker_browsertest.cc | 31 +- .../browser/chromeos/login/test_attempt_state.cc | 10 +- chrome/browser/chromeos/login/test_attempt_state.h | 23 +- chrome/browser/chromeos/login/update_screen.cc | 74 +- chrome/browser/chromeos/login/update_screen.h | 14 + .../chromeos/login/update_screen_browsertest.cc | 1 + chrome/browser/chromeos/login/user_controller.cc | 78 +- chrome/browser/chromeos/login/user_controller.h | 4 + .../chromeos/login/user_controller_unittest.cc | 30 + chrome/browser/chromeos/login/user_image_screen.cc | 16 +- chrome/browser/chromeos/login/user_image_screen.h | 4 + chrome/browser/chromeos/login/user_image_view.cc | 132 +- chrome/browser/chromeos/login/user_image_view.h | 12 +- chrome/browser/chromeos/login/user_manager.cc | 11 +- chrome/browser/chromeos/login/user_manager.h | 9 + chrome/browser/chromeos/login/username_view.cc | 108 +- chrome/browser/chromeos/login/username_view.h | 43 +- chrome/browser/chromeos/login/wizard_controller.cc | 6 + .../login/wizard_controller_browsertest.cc | 4 +- .../login/wizard_in_process_browser_test.cc | 2 +- .../chromeos/metrics_cros_settings_provider.cc | 66 + .../chromeos/metrics_cros_settings_provider.h | 41 + .../browser/chromeos/network_message_observer.cc | 101 +- chrome/browser/chromeos/network_message_observer.h | 3 +- .../notifications/notification_browsertest.cc | 2 +- .../browser/chromeos/offline/offline_load_page.cc | 2 +- .../options/wifi_config_view_browsertest.cc | 2 +- .../browser/chromeos/panels/panel_browsertest.cc | 2 +- chrome/browser/chromeos/panels/panel_scroller.h | 1 + chrome/browser/chromeos/pipe_reader_unittest.cc | 9 +- .../browser/chromeos/proxy_config_service_impl.cc | 4 +- .../chromeos/proxy_config_service_impl_unittest.cc | 6 +- .../chromeos/proxy_cros_settings_provider.cc | 334 +++ .../chromeos/proxy_cros_settings_provider.h | 50 + .../status/clock_menu_button_browsertest.cc | 4 +- .../status/input_method_menu_button_browsertest.cc | 4 +- .../chromeos/status/network_dropdown_button.cc | 24 +- .../chromeos/status/network_dropdown_button.h | 5 +- chrome/browser/chromeos/status/network_menu.cc | 174 +- chrome/browser/chromeos/status/network_menu.h | 10 +- .../browser/chromeos/status/network_menu_button.cc | 48 +- .../browser/chromeos/status/network_menu_button.h | 4 + .../status/power_menu_button_browsertest.cc | 4 +- .../browser/chromeos/status/status_area_button.cc | 10 +- .../browser/chromeos/status/status_area_button.h | 7 + chrome/browser/chromeos/status/status_area_view.cc | 8 + chrome/browser/chromeos/status/status_area_view.h | 1 + .../browser/chromeos/system_key_event_listener.cc | 27 +- .../tab_closeable_state_watcher_browsertest.cc | 2 +- chrome/browser/chromeos/update_browsertest.cc | 2 +- chrome/browser/chromeos/usb_mount_observer.cc | 14 +- .../chromeos/usb_mount_observer_browsertest.cc | 2 +- .../chromeos/user_cros_settings_provider.cc | 300 +++ .../browser/chromeos/user_cros_settings_provider.h | 76 + chrome/browser/chromeos/views/copy_background.cc | 34 + chrome/browser/chromeos/views/copy_background.h | 35 + chrome/browser/chromeos/views/dropdown_button.cc | 73 + chrome/browser/chromeos/views/dropdown_button.h | 33 + chrome/browser/chromeos/views/native_menu_domui.cc | 6 +- chrome/browser/chromeos/volume_bubble.cc | 2 +- chrome/browser/chromeos/volume_bubble.h | 1 + chrome/browser/chromeos/wm_overview_controller.cc | 2 +- chrome/browser/chromeos/wm_overview_snapshot.cc | 2 +- chrome/browser/chromeos/wm_overview_title.cc | 2 +- .../cocoa/applescript/window_applescript.mm | 2 +- chrome/browser/cocoa/browser_test_helper.h | 2 +- chrome/browser/cocoa/browser_window_cocoa.h | 2 +- chrome/browser/cocoa/browser_window_cocoa.mm | 9 +- chrome/browser/cocoa/browser_window_controller.h | 6 +- chrome/browser/cocoa/browser_window_controller.mm | 79 +- .../cocoa/content_exceptions_window_controller.h | 5 +- .../cocoa/content_exceptions_window_controller.mm | 74 +- .../browser/cocoa/content_setting_bubble_cocoa.mm | 37 +- .../cocoa/content_settings_dialog_controller.h | 1 + .../cocoa/content_settings_dialog_controller.mm | 30 +- .../content_settings_dialog_controller_unittest.mm | 30 +- chrome/browser/cocoa/dev_tools_controller.h | 10 +- chrome/browser/cocoa/dev_tools_controller.mm | 43 +- .../cocoa/extension_installed_bubble_controller.h | 10 +- .../cocoa/extension_installed_bubble_controller.mm | 61 +- ...tension_installed_bubble_controller_unittest.mm | 4 +- .../cocoa/location_bar/location_bar_view_mac.h | 1 + .../cocoa/location_bar/location_bar_view_mac.mm | 4 + .../browser/cocoa/page_info_bubble_controller.mm | 5 +- .../browser/cocoa/preferences_window_controller.mm | 7 +- .../cocoa/previewable_contents_controller.h | 6 - .../cocoa/previewable_contents_controller.mm | 41 +- .../previewable_contents_controller_unittest.mm | 15 - chrome/browser/cocoa/reload_button.h | 5 + chrome/browser/cocoa/reload_button.mm | 27 +- chrome/browser/cocoa/reload_button_unittest.mm | 61 +- chrome/browser/cocoa/shell_dialogs_mac.mm | 14 + chrome/browser/cocoa/sidebar_controller.h | 11 +- chrome/browser/cocoa/sidebar_controller.mm | 33 +- chrome/browser/cocoa/tab_contents_controller.h | 44 +- chrome/browser/cocoa/tab_contents_controller.mm | 152 +- chrome/browser/cocoa/tab_strip_controller.h | 14 +- chrome/browser/cocoa/tab_strip_controller.mm | 17 +- chrome/browser/content_setting_bubble_model.cc | 9 +- .../content_setting_bubble_model_unittest.cc | 1 + chrome/browser/content_setting_combo_model.cc | 6 +- chrome/browser/crash_handler_host_linux.cc | 26 +- chrome/browser/crash_handler_host_linux.h | 6 + chrome/browser/crash_recovery_browsertest.cc | 2 +- chrome/browser/custom_home_pages_table_model.cc | 2 +- .../debugger/devtools_http_protocol_handler.cc | 2 +- .../browser/debugger/devtools_netlog_observer.cc | 8 +- .../browser/debugger/devtools_sanity_unittest.cc | 2 +- chrome/browser/debugger/devtools_window.cc | 2 +- chrome/browser/debugger/inspectable_tab_proxy.cc | 2 +- chrome/browser/defaults.cc | 4 + chrome/browser/defaults.h | 6 + .../device_orientation_browsertest.cc | 2 +- chrome/browser/dock_info_win.cc | 2 +- chrome/browser/dom_ui/app_launcher_handler.cc | 158 +- chrome/browser/dom_ui/app_launcher_handler.h | 24 +- chrome/browser/dom_ui/bug_report_ui.cc | 6 +- chrome/browser/dom_ui/conflicts_ui.cc | 2 +- chrome/browser/dom_ui/dom_ui_factory.cc | 14 + chrome/browser/dom_ui/dom_ui_factory.h | 7 +- chrome/browser/dom_ui/filebrowse_ui.cc | 36 +- chrome/browser/dom_ui/foreign_session_handler.cc | 2 +- chrome/browser/dom_ui/history2_ui.cc | 4 +- chrome/browser/dom_ui/history_ui.cc | 6 +- .../dom_ui/html_dialog_tab_contents_delegate.cc | 4 +- .../html_dialog_tab_contents_delegate_unittest.cc | 4 +- chrome/browser/dom_ui/mediaplayer_browsertest.cc | 18 +- chrome/browser/dom_ui/mediaplayer_ui.cc | 17 +- chrome/browser/dom_ui/new_tab_ui.cc | 6 +- chrome/browser/dom_ui/new_tab_ui_uitest.cc | 25 + chrome/browser/dom_ui/ntp_resource_cache.cc | 28 +- .../browser/dom_ui/options/about_page_handler.cc | 1 + .../dom_ui/options/advanced_options_handler.cc | 13 +- .../dom_ui/options/content_settings_handler.cc | 1 + chrome/browser/dom_ui/options/options_ui.cc | 4 +- .../dom_ui/options/personal_options_handler.cc | 30 +- .../dom_ui/options/personal_options_handler.h | 2 - chrome/browser/dom_ui/plugins_ui.cc | 4 +- chrome/browser/dom_ui/shown_sections_handler.cc | 38 +- chrome/browser/dom_ui/shown_sections_handler.h | 6 +- chrome/browser/download/download_item.cc | 31 + chrome/browser/download/download_item.h | 9 + chrome/browser/download/download_manager.cc | 31 +- chrome/browser/download/download_manager.h | 18 +- chrome/browser/download/download_shelf.cc | 2 +- chrome/browser/download/download_uitest.cc | 30 +- chrome/browser/download/download_util.cc | 117 +- chrome/browser/download/download_util.h | 4 + chrome/browser/download/save_page_browsertest.cc | 2 +- chrome/browser/enumerate_modules_model_win.cc | 19 +- chrome/browser/enumerate_modules_model_win.h | 2 +- chrome/browser/extensions/alert_apitest.cc | 2 +- chrome/browser/extensions/all_urls_apitest.cc | 4 +- .../extensions/app_background_page_apitest.cc | 2 +- chrome/browser/extensions/app_process_apitest.cc | 2 +- .../browser/extensions/browser_action_apitest.cc | 2 +- .../extensions/browser_action_test_util_gtk.cc | 2 +- .../extensions/browser_action_test_util_views.cc | 4 +- .../content_script_extension_process_apitest.cc | 2 +- chrome/browser/extensions/convert_user_script.h | 2 + chrome/browser/extensions/convert_web_app.cc | 172 ++ chrome/browser/extensions/convert_web_app.h | 43 + .../browser/extensions/convert_web_app_unittest.cc | 174 ++ chrome/browser/extensions/crx_installer.cc | 35 +- chrome/browser/extensions/crx_installer.h | 3 + .../extensions/crx_installer_browsertest.cc | 5 +- chrome/browser/extensions/default_apps.cc | 14 +- chrome/browser/extensions/default_apps_unittest.cc | 6 +- .../extensions/execute_code_in_tab_function.cc | 2 +- .../extensions/extension_accessibility_api.cc | 2 +- chrome/browser/extensions/extension_apitest.cc | 2 +- .../extensions/extension_browser_actions_api.cc | 2 +- .../extensions/extension_browser_event_router.cc | 8 +- chrome/browser/extensions/extension_browsertest.cc | 6 +- .../extensions/extension_browsertests_misc.cc | 4 +- .../extension_context_menu_browsertest.cc | 2 +- .../extensions/extension_context_menu_model.cc | 6 +- .../extensions/extension_cookies_helpers.cc | 2 +- .../extension_crash_recovery_browsertest.cc | 2 +- .../extensions/extension_devtools_browsertests.cc | 6 +- .../extension_disabled_infobar_delegate.cc | 5 +- chrome/browser/extensions/extension_dom_ui.cc | 17 +- .../extensions/extension_function_dispatcher.cc | 7 +- .../extension_gallery_install_apitest.cc | 32 +- chrome/browser/extensions/extension_host.cc | 10 +- chrome/browser/extensions/extension_host.h | 4 - chrome/browser/extensions/extension_idle_api.cc | 2 +- .../extensions/extension_incognito_apitest.cc | 14 +- .../extensions/extension_infobar_delegate.cc | 4 +- .../extensions/extension_infobar_delegate.h | 2 +- .../browser/extensions/extension_infobar_module.cc | 2 +- chrome/browser/extensions/extension_input_api.cc | 2 +- chrome/browser/extensions/extension_install_ui.cc | 1 + .../extensions/extension_install_ui_browsertest.cc | 4 +- .../browser/extensions/extension_management_api.cc | 6 +- .../extensions/extension_management_apitest.cc | 2 +- .../extensions/extension_management_browsertest.cc | 4 +- chrome/browser/extensions/extension_module.cc | 23 + chrome/browser/extensions/extension_module.h | 20 + .../browser/extensions/extension_module_apitest.cc | 12 + chrome/browser/extensions/extension_omnibox_api.cc | 99 +- chrome/browser/extensions/extension_omnibox_api.h | 6 +- .../extensions/extension_omnibox_apitest.cc | 26 +- .../extensions/extension_omnibox_unittest.cc | 133 ++ .../extensions/extension_override_apitest.cc | 2 +- .../extensions/extension_page_actions_module.cc | 4 +- chrome/browser/extensions/extension_popup_api.cc | 4 +- .../extensions/extension_pref_store_unittest.cc | 2 +- chrome/browser/extensions/extension_prefs.cc | 25 + chrome/browser/extensions/extension_prefs.h | 7 + .../extensions/extension_process_manager.cc | 2 +- .../extensions/extension_processes_apitest.cc | 2 +- chrome/browser/extensions/extension_protocols.cc | 11 +- .../browser/extensions/extension_proxy_apitest.cc | 2 +- .../extensions/extension_startup_browsertest.cc | 2 +- .../browser/extensions/extension_tabs_apitest.cc | 2 +- chrome/browser/extensions/extension_tabs_module.cc | 4 +- chrome/browser/extensions/extension_test_api.cc | 4 +- .../extension_toolbar_model_browsertest.cc | 4 +- chrome/browser/extensions/extension_uitest.cc | 2 +- chrome/browser/extensions/extension_updater.cc | 69 +- chrome/browser/extensions/extension_updater.h | 15 +- .../extensions/extension_updater_unittest.cc | 145 +- .../extensions/extension_webstore_private_api.cc | 63 +- .../extensions/extension_webstore_private_api.h | 17 +- chrome/browser/extensions/extensions_service.cc | 200 +- .../extensions/extensions_service_unittest.cc | 13 +- chrome/browser/extensions/extensions_ui.cc | 2 +- chrome/browser/extensions/notifications_apitest.cc | 2 +- chrome/browser/extensions/page_action_apitest.cc | 8 +- .../extensions/sandboxed_extension_unpacker.cc | 4 + .../extensions/theme_installed_infobar_delegate.cc | 39 +- chrome/browser/extensions/window_open_apitest.cc | 4 +- chrome/browser/external_protocol_handler.cc | 2 +- chrome/browser/external_tab_container_win.cc | 9 +- chrome/browser/external_tab_container_win.h | 2 +- .../browser_file_system_callback_dispatcher.cc | 7 +- .../file_system/browser_file_system_context.cc | 34 + .../file_system/browser_file_system_context.h | 35 + .../file_system/file_system_dispatcher_host.cc | 157 +- .../file_system/file_system_dispatcher_host.h | 53 +- .../file_system/file_system_host_context.cc | 50 - .../browser/file_system/file_system_host_context.h | 44 - chrome/browser/find_bar_host_browsertest.cc | 6 +- chrome/browser/gears_integration.cc | 8 +- chrome/browser/gears_integration.h | 13 +- .../browser/geolocation/geolocation_browsertest.cc | 2 +- .../geolocation/geolocation_permission_context.cc | 21 +- chrome/browser/global_keyboard_shortcuts_mac.mm | 68 +- .../global_keyboard_shortcuts_mac_unittest.mm | 95 +- chrome/browser/google/google_url_tracker.cc | 247 +- chrome/browser/google/google_url_tracker.h | 57 +- .../browser/google/google_url_tracker_unittest.cc | 612 +++-- chrome/browser/gpu_process_host.cc | 72 +- chrome/browser/gpu_process_host.h | 26 +- chrome/browser/gpu_process_host_ui_shim.cc | 40 +- chrome/browser/gpu_process_host_ui_shim.h | 15 +- chrome/browser/gtk/back_forward_button_gtk.cc | 2 +- chrome/browser/gtk/bookmark_bar_gtk.cc | 3 +- chrome/browser/gtk/bookmark_bar_gtk.h | 3 +- .../gtk/bookmark_bar_gtk_interactive_uitest.cc | 8 +- chrome/browser/gtk/bookmark_bar_gtk_unittest.cc | 6 +- chrome/browser/gtk/bookmark_editor_gtk.cc | 168 ++ chrome/browser/gtk/bookmark_editor_gtk.h | 40 +- chrome/browser/gtk/bookmark_menu_controller_gtk.cc | 26 +- chrome/browser/gtk/bookmark_menu_controller_gtk.h | 3 + chrome/browser/gtk/browser_actions_toolbar_gtk.cc | 2 +- chrome/browser/gtk/browser_actions_toolbar_gtk.h | 1 + chrome/browser/gtk/browser_titlebar.cc | 13 +- chrome/browser/gtk/browser_titlebar.h | 4 + chrome/browser/gtk/browser_toolbar_gtk.cc | 2 +- chrome/browser/gtk/browser_toolbar_gtk.h | 1 + chrome/browser/gtk/browser_window_factory_gtk.cc | 2 +- chrome/browser/gtk/browser_window_gtk.cc | 45 +- chrome/browser/gtk/browser_window_gtk.h | 2 +- chrome/browser/gtk/chrome_gtk_frame.cc | 155 ++ chrome/browser/gtk/chrome_gtk_frame.h | 56 + .../browser/gtk/clear_browsing_data_dialog_gtk.cc | 2 +- chrome/browser/gtk/constrained_window_gtk.cc | 6 +- chrome/browser/gtk/custom_button.h | 1 + chrome/browser/gtk/dialogs_gtk.cc | 1 + .../browser/gtk/download_in_progress_dialog_gtk.cc | 4 +- chrome/browser/gtk/download_item_gtk.cc | 2 +- chrome/browser/gtk/download_item_gtk.h | 2 +- chrome/browser/gtk/download_shelf_gtk.cc | 2 +- chrome/browser/gtk/extension_infobar_gtk.cc | 8 +- chrome/browser/gtk/extension_infobar_gtk.h | 2 - .../browser/gtk/extension_install_prompt2_gtk.cc | 5 +- .../browser/gtk/extension_installed_bubble_gtk.cc | 93 +- .../browser/gtk/extension_installed_bubble_gtk.h | 2 + chrome/browser/gtk/extension_popup_gtk.cc | 2 +- chrome/browser/gtk/find_bar_gtk.cc | 2 +- chrome/browser/gtk/first_run_bubble.cc | 2 +- chrome/browser/gtk/gconf_titlebar_listener.cc | 10 +- chrome/browser/gtk/gtk_theme_provider.cc | 259 +- chrome/browser/gtk/gtk_theme_provider.h | 35 +- chrome/browser/gtk/gtk_util.cc | 97 +- chrome/browser/gtk/gtk_util.h | 6 + chrome/browser/gtk/hover_controller_gtk.h | 1 + chrome/browser/gtk/html_dialog_gtk.cc | 2 +- chrome/browser/gtk/hung_renderer_dialog_gtk.cc | 14 +- chrome/browser/gtk/infobar_arrow_model.h | 1 + chrome/browser/gtk/infobar_gtk.h | 1 - chrome/browser/gtk/instant_confirm_dialog_gtk.cc | 12 +- chrome/browser/gtk/location_bar_view_gtk.cc | 6 +- chrome/browser/gtk/location_bar_view_gtk.h | 4 + chrome/browser/gtk/menu_gtk.cc | 12 +- chrome/browser/gtk/meta_frames.cc | 25 - chrome/browser/gtk/meta_frames.h | 39 - .../browser/gtk/notifications/balloon_view_gtk.h | 2 +- .../browser/gtk/options/advanced_contents_gtk.cc | 8 +- .../browser/gtk/options/content_filter_page_gtk.cc | 135 +- .../browser/gtk/options/content_filter_page_gtk.h | 23 + chrome/browser/gtk/options/content_page_gtk.cc | 6 +- .../gtk/options/content_settings_window_gtk.cc | 4 +- .../browser/gtk/options/cookie_filter_page_gtk.cc | 106 +- .../browser/gtk/options/cookie_filter_page_gtk.h | 17 +- chrome/browser/gtk/options/general_page_gtk.cc | 3 +- chrome/browser/gtk/page_info_bubble_gtk.cc | 5 +- chrome/browser/gtk/reload_button_gtk.cc | 2 +- chrome/browser/gtk/sad_tab_gtk.cc | 7 +- chrome/browser/gtk/slide_animator_gtk.h | 2 +- chrome/browser/gtk/status_bubble_gtk.cc | 1 + chrome/browser/gtk/status_bubble_gtk.h | 3 +- .../browser/gtk/tabs/dragged_tab_controller_gtk.cc | 2 +- chrome/browser/gtk/tabs/dragged_tab_gtk.h | 1 + chrome/browser/gtk/tabs/tab_renderer_gtk.cc | 11 +- chrome/browser/gtk/tabs/tab_renderer_gtk.h | 4 +- chrome/browser/gtk/tabs/tab_strip_gtk.cc | 38 +- chrome/browser/gtk/task_manager_gtk.cc | 7 + .../gtk/translate/translate_infobar_base_gtk.h | 1 + chrome/browser/gtk/view_id_util_browsertest.cc | 2 +- chrome/browser/history/history.h | 2 +- chrome/browser/history/history_browsertest.cc | 2 +- chrome/browser/history/redirect_uitest.cc | 3 +- chrome/browser/history/text_database.cc | 4 +- chrome/browser/history/top_sites_database.cc | 5 +- chrome/browser/host_content_settings_map.cc | 158 +- chrome/browser/host_content_settings_map.h | 17 + .../browser/host_content_settings_map_unittest.cc | 283 ++- chrome/browser/host_zoom_map.h | 12 +- chrome/browser/idbbindingutilities_browsertest.cc | 4 +- chrome/browser/importer/importer.cc | 2 +- .../in_process_webkit/browser_webkitclient_impl.cc | 21 +- .../in_process_webkit/browser_webkitclient_impl.h | 6 + .../in_process_webkit/dom_storage_context.cc | 13 +- .../in_process_webkit/indexed_db_browsertest.cc | 2 +- .../indexed_db_key_utility_client.cc | 6 +- chrome/browser/instant/instant_browsertest.cc | 5 +- chrome/browser/instant/instant_confirm_dialog.cc | 8 +- chrome/browser/instant/instant_confirm_dialog.h | 5 +- chrome/browser/instant/instant_controller.cc | 167 +- chrome/browser/instant/instant_controller.h | 19 +- chrome/browser/instant/instant_delegate.h | 5 + chrome/browser/instant/instant_loader.cc | 51 +- chrome/browser/instant/instant_loader.h | 13 +- chrome/browser/instant/instant_opt_in.cc | 33 - chrome/browser/instant/instant_opt_in.h | 25 - chrome/browser/instant/promo_counter.cc | 115 + chrome/browser/instant/promo_counter.h | 78 + chrome/browser/instant/promo_counter_unittest.cc | 81 + chrome/browser/io_thread.cc | 66 +- chrome/browser/io_thread.h | 14 +- chrome/browser/media_uitest.cc | 55 +- chrome/browser/metrics/histogram_synchronizer.cc | 37 +- chrome/browser/metrics/histogram_synchronizer.h | 13 +- chrome/browser/metrics/metrics_log.cc | 6 +- chrome/browser/metrics/metrics_log_unittest.cc | 4 +- chrome/browser/mime_registry_dispatcher.cc | 96 + chrome/browser/mime_registry_dispatcher.h | 37 + chrome/browser/nacl_host/nacl_process_host.cc | 24 + chrome/browser/net/chrome_url_request_context.cc | 6 +- chrome/browser/net/chrome_url_request_context.h | 14 +- .../net/chrome_url_request_context_unittest.cc | 1 + chrome/browser/net/connection_tester_unittest.cc | 6 +- chrome/browser/net/cookie_policy_browsertest.cc | 2 +- chrome/browser/net/gaia/token_service.cc | 4 +- chrome/browser/net/gaia/token_service.h | 4 +- chrome/browser/net/gaia/token_service_unittest.cc | 2 +- chrome/browser/net/passive_log_collector.cc | 20 +- chrome/browser/net/passive_log_collector.h | 3 + .../browser/net/passive_log_collector_unittest.cc | 54 + chrome/browser/net/predictor.cc | 16 +- chrome/browser/net/predictor_api.cc | 2 +- chrome/browser/net/url_info.cc | 29 +- chrome/browser/options_util.cc | 11 + chrome/browser/page_info_model.cc | 14 +- .../password_store_default_unittest.cc | 8 +- .../password_manager/password_store_x_unittest.cc | 8 +- chrome/browser/platform_util_linux.cc | 19 +- chrome/browser/plugin_service.cc | 8 - chrome/browser/plugin_service_browsertest.cc | 107 + chrome/browser/plugin_service_unittest.cc | 63 + .../policy/configuration_policy_pref_store.cc | 99 +- .../policy/configuration_policy_pref_store.h | 13 +- .../configuration_policy_pref_store_unittest.cc | 20 +- .../policy/configuration_policy_provider.cc | 15 + .../browser/policy/configuration_policy_provider.h | 3 + .../policy/configuration_policy_store_interface.h | 11 + .../device_management_backend_impl_browsertest.cc | 55 +- .../policy/device_management_policy_cache.cc | 42 +- .../policy/device_management_policy_cache.h | 9 + .../device_management_policy_cache_unittest.cc | 39 +- .../policy/device_management_policy_provider.cc | 190 ++ .../policy/device_management_policy_provider.h | 116 + .../device_management_policy_provider_unittest.cc | 147 ++ chrome/browser/policy/device_token_fetcher.cc | 196 +- chrome/browser/policy/device_token_fetcher.h | 101 +- .../policy/device_token_fetcher_unittest.cc | 159 +- .../browser/policy/file_based_policy_provider.cc | 15 - chrome/browser/policy/file_based_policy_provider.h | 4 - .../policy/mock_configuration_policy_store.cc | 33 + .../policy/mock_configuration_policy_store.h | 23 +- .../policy/mock_device_management_backend.cc | 122 +- .../policy/mock_device_management_backend.h | 56 +- .../policy/proto/device_management_backend.proto | 4 +- .../policy/proto/device_management_local.proto | 26 + .../policy/proto/device_management_proto.gyp | 80 + chrome/browser/popup_blocker_browsertest.cc | 2 +- chrome/browser/ppapi_plugin_process_host.cc | 104 + chrome/browser/ppapi_plugin_process_host.h | 57 + chrome/browser/prefs/browser_prefs.cc | 4 +- chrome/browser/prefs/command_line_pref_store.cc | 9 + chrome/browser/prefs/pref_notifier.h | 9 +- chrome/browser/prefs/pref_notifier_unittest.cc | 3 +- chrome/browser/prefs/pref_service.cc | 6 +- chrome/browser/prefs/pref_service_unittest.cc | 18 +- chrome/browser/prefs/pref_value_store.cc | 137 +- chrome/browser/prefs/pref_value_store.h | 34 +- chrome/browser/prefs/pref_value_store_unittest.cc | 228 +- .../printing/cloud_print/cloud_print_setup_flow.cc | 10 +- .../printing/cloud_print/cloud_print_setup_flow.h | 6 +- .../printing/print_preview_tab_controller.cc | 194 ++ .../printing/print_preview_tab_controller.h | 87 + .../print_preview_tab_controller_unittest.cc | 114 + chrome/browser/process_singleton_linux.cc | 2 +- chrome/browser/process_singleton_linux_uitest.cc | 4 +- chrome/browser/process_singleton_win.cc | 2 +- chrome/browser/profile.cc | 28 +- chrome/browser/profile.h | 14 +- chrome/browser/profile_impl.cc | 62 +- chrome/browser/profile_impl.h | 12 +- chrome/browser/profile_manager.cc | 6 +- chrome/browser/remoting/remoting_setup_flow.cc | 12 +- chrome/browser/remoting/remoting_setup_flow.h | 6 +- .../browser/renderer_host/audio_renderer_host.cc | 27 +- .../renderer_host/audio_renderer_host_unittest.cc | 4 +- .../renderer_host/browser_render_process_host.cc | 35 +- .../renderer_host/browser_render_process_host.h | 4 + .../file_utilities_dispatcher_host.cc | 10 +- .../renderer_host/file_utilities_dispatcher_host.h | 2 +- .../renderer_host/render_sandbox_host_linux.cc | 8 +- .../renderer_host/render_sandbox_host_linux.h | 8 +- chrome/browser/renderer_host/render_view_host.cc | 105 +- chrome/browser/renderer_host/render_view_host.h | 29 +- .../renderer_host/render_view_host_delegate.cc | 13 +- .../renderer_host/render_view_host_delegate.h | 41 +- chrome/browser/renderer_host/render_widget_host.cc | 52 +- chrome/browser/renderer_host/render_widget_host.h | 15 +- .../renderer_host/render_widget_host_unittest.cc | 11 +- .../renderer_host/render_widget_host_view.h | 12 + .../renderer_host/render_widget_host_view_mac.mm | 14 +- .../renderer_host/render_widget_host_view_win.cc | 76 +- .../renderer_host/render_widget_host_view_win.h | 4 - .../renderer_host/resource_dispatcher_host.cc | 3 +- .../resource_dispatcher_host_uitest.cc | 5 +- .../renderer_host/resource_message_filter.cc | 48 +- .../renderer_host/resource_message_filter.h | 17 +- .../test/render_process_host_browsertest.cc | 10 +- .../test/render_view_host_browsertest.cc | 2 +- .../test/render_view_host_manager_browsertest.cc | 44 +- .../test/renderer_accessibility_browsertest.cc | 2 +- .../test/web_cache_manager_browsertest.cc | 2 +- chrome/browser/renderer_preferences_util.cc | 1 + chrome/browser/resources/filebrowse.html | 2 +- chrome/browser/resources/guest_session_tab.html | 25 + chrome/browser/resources/incognito_tab.css | 35 + chrome/browser/resources/incognito_tab.html | 38 +- chrome/browser/resources/mobile_setup.html | 70 +- chrome/browser/resources/mobile_setup.js | 17 +- chrome/browser/resources/network_menu.js | 48 +- chrome/browser/resources/new_new_tab.css | 21 +- chrome/browser/resources/new_new_tab.html | 8 +- chrome/browser/resources/new_new_tab.js | 5 +- chrome/browser/resources/ntp/apps.js | 18 +- chrome/browser/resources/options.html | 117 +- chrome/browser/resources/options/about_page.html | 1 + .../resources/options/advanced_options.html | 8 +- .../browser/resources/options/advanced_options.js | 2 +- .../resources/options/autofill_options.html | 14 +- .../resources/options/certificate_manager.html | 38 +- .../options/chromeos_internet_detail.html | 43 +- .../options/chromeos_internet_network_element.js | 23 +- .../resources/options/chromeos_internet_options.js | 60 +- .../options/chromeos_internet_options_page.css | 4 +- .../browser/resources/options/chromeos_labs.html | 47 - .../resources/options/chromeos_language_options.js | 19 +- .../resources/options/content_settings.html | 58 +- .../options/content_settings_exceptions_area.js | 23 +- chrome/browser/resources/options/options_page.css | 128 +- chrome/browser/resources/options/options_page.js | 106 +- .../resources/options/passwords_exceptions.html | 23 +- .../resources/options/personal_options.html | 12 +- .../browser/resources/options/personal_options.js | 28 +- .../resources/options/search_engine_manager.html | 6 +- .../resources/options/subpages_tab_controls.css | 48 +- .../shared/images/guest_icon_standalone.png | Bin 0 -> 2556 bytes chrome/browser/rlz/rlz.cc | 8 +- chrome/browser/safe_browsing/bloom_filter.cc | 5 +- .../safe_browsing/client_side_detection_service.cc | 321 +++ .../safe_browsing/client_side_detection_service.h | 200 ++ .../client_side_detection_service_unittest.cc | 198 ++ chrome/browser/safe_browsing/csd.proto | 34 + chrome/browser/safe_browsing/protocol_manager.cc | 2 +- .../safe_browsing/safe_browsing_blocking_page.cc | 2 +- .../safe_browsing/safe_browsing_store_file.cc | 31 + .../safe_browsing/safe_browsing_store_file.h | 12 + chrome/browser/safe_browsing/safe_browsing_test.cc | 36 +- .../browser/search_engines/template_url_model.cc | 1 + .../template_url_prepopulate_data.cc | 3 +- .../template_url_scraper_unittest.cc | 2 +- .../service/service_process_control_browsertest.cc | 2 +- chrome/browser/sessions/session_restore.cc | 14 +- .../sessions/session_restore_browsertest.cc | 4 +- chrome/browser/sessions/session_service.cc | 2 +- chrome/browser/sessions/session_service.h | 4 +- chrome/browser/sessions/session_types.cc | 2 +- chrome/browser/shell_dialogs.h | 1 + chrome/browser/show_options_url.cc | 4 +- chrome/browser/sidebar/sidebar_test.cc | 2 +- chrome/browser/speech/speech_input_browsertest.cc | 2 +- .../speech/speech_input_bubble_browsertest.cc | 2 +- chrome/browser/speech/speech_input_bubble_views.cc | 2 +- chrome/browser/speech/speech_recognizer.cc | 6 +- chrome/browser/spellcheck_host.cc | 11 + chrome/browser/ssl/ssl_blocking_page.cc | 2 +- chrome/browser/ssl/ssl_browser_tests.cc | 148 +- chrome/browser/ssl/ssl_manager.cc | 3 +- .../sync/engine/download_updates_command.cc | 3 +- .../sync/engine/net/server_connection_manager.cc | 17 +- .../sync/engine/net/server_connection_manager.h | 42 +- chrome/browser/sync/engine/syncapi.cc | 141 +- chrome/browser/sync/engine/syncapi.h | 9 +- chrome/browser/sync/engine/syncer.cc | 11 +- chrome/browser/sync/engine/syncer.h | 16 +- chrome/browser/sync/engine/syncer_thread.cc | 134 +- chrome/browser/sync/engine/syncer_thread.h | 34 +- .../browser/sync/engine/syncer_thread_unittest.cc | 49 +- .../browser/sync/glue/bookmark_change_processor.cc | 17 +- .../browser/sync/glue/bookmark_change_processor.h | 8 + chrome/browser/sync/glue/sync_backend_host.cc | 20 +- chrome/browser/sync/glue/sync_backend_host.h | 11 +- .../sync/notifier/server_notifier_thread.cc | 11 +- chrome/browser/sync/profile_sync_service.cc | 52 +- chrome/browser/sync/profile_sync_service.h | 29 +- .../browser/sync/profile_sync_service_harness.cc | 26 +- chrome/browser/sync/profile_sync_service_harness.h | 18 +- .../sync/profile_sync_service_password_unittest.cc | 2 +- .../browser/sync/protocol/autofill_specifics.proto | 3 + .../browser/sync/protocol/nigori_specifics.proto | 3 + chrome/browser/sync/resources/passphrase.html | 7 +- chrome/browser/sync/sessions/sync_session.cc | 12 +- chrome/browser/sync/sessions/sync_session.h | 13 +- chrome/browser/sync/signin_manager.cc | 16 +- chrome/browser/sync/signin_manager.h | 4 +- chrome/browser/sync/signin_manager_unittest.cc | 4 +- chrome/browser/sync/sync_setup_flow.cc | 30 +- chrome/browser/sync/sync_setup_flow.h | 3 +- chrome/browser/sync/sync_setup_wizard_unittest.cc | 12 +- chrome/browser/sync/syncable/model_type.cc | 71 + chrome/browser/sync/syncable/model_type.h | 11 + chrome/browser/tab_contents/background_contents.cc | 12 + chrome/browser/tab_contents/background_contents.h | 8 + chrome/browser/tab_contents/interstitial_page.cc | 2 +- .../browser/tab_contents/navigation_controller.cc | 5 +- .../tab_contents/navigation_controller_unittest.cc | 8 +- chrome/browser/tab_contents/navigation_entry.h | 10 +- .../tab_contents/navigation_entry_unittest.cc | 8 +- .../tab_contents/render_view_context_menu.cc | 2 +- .../render_view_host_delegate_helper.cc | 14 +- .../tab_contents/render_view_host_manager.cc | 12 +- chrome/browser/tab_contents/security_style.h | 35 - chrome/browser/tab_contents/tab_contents.cc | 67 +- chrome/browser/tab_contents/tab_contents.h | 18 +- .../browser/tab_contents/tab_contents_delegate.cc | 11 - .../browser/tab_contents/tab_contents_delegate.h | 15 +- chrome/browser/tab_contents/thumbnail_generator.cc | 33 +- chrome/browser/tab_menu_model.cc | 3 +- chrome/browser/tabs/default_tab_handler.cc | 2 +- chrome/browser/tabs/pinned_tab_codec.cc | 2 +- chrome/browser/tabs/pinned_tab_codec.h | 2 +- chrome/browser/tabs/pinned_tab_service.cc | 2 +- chrome/browser/tabs/tab_strip_model.cc | 23 +- chrome/browser/tabs/tab_strip_model_unittest.cc | 47 + chrome/browser/task_manager/task_manager.cc | 54 +- chrome/browser/task_manager/task_manager.h | 18 + .../task_manager/task_manager_browsertest.cc | 36 +- .../task_manager_resource_providers.cc | 368 ++- .../task_manager/task_manager_resource_providers.h | 113 +- chrome/browser/themes/browser_theme_provider.cc | 5 +- chrome/browser/themes/browser_theme_provider.h | 6 +- chrome/browser/toolbar_model.cc | 2 +- chrome/browser/translate/languages_menu_model.cc | 3 +- chrome/browser/translate/options_menu_model.cc | 20 +- chrome/browser/translate/translate_manager.cc | 4 +- chrome/browser/translate/translate_manager.h | 3 +- chrome/browser/ui/browser.cc | 117 +- chrome/browser/ui/browser.h | 7 +- chrome/browser/ui/browser_init.cc | 6 +- chrome/browser/ui/browser_init_browsertest.cc | 4 +- chrome/browser/ui/browser_list.cc | 18 +- chrome/browser/ui/browser_list.h | 16 +- chrome/browser/ui/browser_navigator.cc | 108 +- chrome/browser/ui/browser_navigator.h | 11 +- chrome/browser/ui/browser_navigator_browsertest.cc | 108 +- chrome/browser/ui/browser_window.h | 9 +- chrome/browser/ui/views/PRESUBMIT.py | 13 + chrome/browser/ui/views/about_chrome_view.cc | 819 +++++++ chrome/browser/ui/views/about_chrome_view.h | 173 ++ chrome/browser/ui/views/about_ipc_dialog.cc | 460 ++++ chrome/browser/ui/views/about_ipc_dialog.h | 79 + chrome/browser/ui/views/accelerator_table_gtk.cc | 159 ++ chrome/browser/ui/views/accelerator_table_gtk.h | 32 + .../ui/views/accessibility_event_router_views.cc | 305 +++ .../ui/views/accessibility_event_router_views.h | 154 ++ .../accessibility_event_router_views_unittest.cc | 174 ++ chrome/browser/ui/views/accessible_pane_view.cc | 251 ++ chrome/browser/ui/views/accessible_pane_view.h | 100 + chrome/browser/ui/views/accessible_view_helper.cc | 89 + chrome/browser/ui/views/accessible_view_helper.h | 83 + .../browser/ui/views/app_launched_animation_win.cc | 136 ++ chrome/browser/ui/views/appcache_info_view.cc | 40 + chrome/browser/ui/views/appcache_info_view.h | 24 + .../autocomplete_popup_contents_view.cc | 1211 ++++++++++ .../autocomplete_popup_contents_view.h | 178 ++ .../views/autocomplete/autocomplete_popup_gtk.cc | 37 + .../ui/views/autocomplete/autocomplete_popup_gtk.h | 28 + .../views/autocomplete/autocomplete_popup_win.cc | 46 + .../ui/views/autocomplete/autocomplete_popup_win.h | 33 + .../browser/ui/views/autofill_profiles_view_win.cc | 1319 ++++++++++ .../browser/ui/views/autofill_profiles_view_win.h | 440 ++++ .../ui/views/bookmark_bar_instructions_view.cc | 108 + .../ui/views/bookmark_bar_instructions_view.h | 68 + chrome/browser/ui/views/bookmark_bar_view.cc | 1743 ++++++++++++++ chrome/browser/ui/views/bookmark_bar_view.h | 507 ++++ chrome/browser/ui/views/bookmark_bar_view_test.cc | 1358 +++++++++++ .../browser/ui/views/bookmark_bar_view_unittest.cc | 47 + chrome/browser/ui/views/bookmark_bubble_view.cc | 413 ++++ chrome/browser/ui/views/bookmark_bubble_view.h | 162 ++ chrome/browser/ui/views/bookmark_context_menu.cc | 100 + chrome/browser/ui/views/bookmark_context_menu.h | 76 + .../bookmark_context_menu_controller_views.cc | 292 +++ .../views/bookmark_context_menu_controller_views.h | 93 + .../browser/ui/views/bookmark_context_menu_test.cc | 311 +++ chrome/browser/ui/views/bookmark_editor_view.cc | 585 +++++ chrome/browser/ui/views/bookmark_editor_view.h | 266 +++ .../ui/views/bookmark_editor_view_unittest.cc | 366 +++ .../ui/views/bookmark_menu_controller_views.cc | 415 ++++ .../ui/views/bookmark_menu_controller_views.h | 200 ++ .../browser/ui/views/browser_actions_container.cc | 1100 +++++++++ .../browser/ui/views/browser_actions_container.h | 511 ++++ .../views/browser_actions_container_browsertest.cc | 200 ++ chrome/browser/ui/views/browser_bubble.cc | 126 + chrome/browser/ui/views/browser_bubble.h | 131 + chrome/browser/ui/views/browser_bubble_gtk.cc | 120 + chrome/browser/ui/views/browser_bubble_win.cc | 132 + chrome/browser/ui/views/browser_dialogs.h | 130 + .../browser_keyboard_accessibility_test_win.cc | 210 ++ chrome/browser/ui/views/bubble_border.cc | 443 ++++ chrome/browser/ui/views/bubble_border.h | 172 ++ chrome/browser/ui/views/certificate_viewer_win.cc | 32 + chrome/browser/ui/views/chrome_views_delegate.cc | 102 + chrome/browser/ui/views/chrome_views_delegate.h | 39 + chrome/browser/ui/views/clear_browsing_data.cc | 472 ++++ chrome/browser/ui/views/clear_browsing_data.h | 128 + .../browser/ui/views/clear_browsing_data_view.cc | 371 +++ chrome/browser/ui/views/clear_browsing_data_view.h | 121 + chrome/browser/ui/views/clear_data_view.cc | 174 ++ chrome/browser/ui/views/clear_data_view.h | 99 + chrome/browser/ui/views/clear_server_data.cc | 344 +++ chrome/browser/ui/views/clear_server_data.h | 118 + chrome/browser/ui/views/collected_cookies_win.cc | 391 +++ chrome/browser/ui/views/collected_cookies_win.h | 96 + .../browser/ui/views/confirm_message_box_dialog.cc | 104 + .../browser/ui/views/confirm_message_box_dialog.h | 100 + .../ui/views/constrained_html_delegate_gtk.cc | 118 + .../ui/views/constrained_html_delegate_win.cc | 113 + chrome/browser/ui/views/constrained_window_win.cc | 673 ++++++ chrome/browser/ui/views/constrained_window_win.h | 77 + .../ui/views/content_setting_bubble_contents.cc | 379 +++ .../ui/views/content_setting_bubble_contents.h | 104 + chrome/browser/ui/views/cookie_info_view.cc | 278 +++ chrome/browser/ui/views/cookie_info_view.h | 123 + .../ui/views/create_application_shortcut_view.cc | 457 ++++ .../ui/views/create_application_shortcut_view.h | 93 + chrome/browser/ui/views/database_info_view.cc | 144 ++ chrome/browser/ui/views/database_info_view.h | 56 + chrome/browser/ui/views/database_open_info_view.cc | 40 + chrome/browser/ui/views/database_open_info_view.h | 33 + chrome/browser/ui/views/default_search_view.cc | 103 + chrome/browser/ui/views/default_search_view.h | 65 + chrome/browser/ui/views/detachable_toolbar_view.cc | 119 + chrome/browser/ui/views/detachable_toolbar_view.h | 91 + chrome/browser/ui/views/dialog_stubs_gtk.cc | 79 + chrome/browser/ui/views/dom_view.cc | 62 + chrome/browser/ui/views/dom_view.h | 59 + chrome/browser/ui/views/dom_view_browsertest.cc | 93 + chrome/browser/ui/views/download_item_view.cc | 1078 +++++++++ chrome/browser/ui/views/download_item_view.h | 277 +++ chrome/browser/ui/views/download_shelf_view.cc | 440 ++++ chrome/browser/ui/views/download_shelf_view.h | 155 ++ .../ui/views/download_started_animation_win.cc | 180 ++ chrome/browser/ui/views/dropdown_bar_host.cc | 310 +++ chrome/browser/ui/views/dropdown_bar_host.h | 188 ++ chrome/browser/ui/views/dropdown_bar_host_gtk.cc | 31 + chrome/browser/ui/views/dropdown_bar_host_win.cc | 48 + chrome/browser/ui/views/dropdown_bar_view.h | 54 + .../browser/ui/views/edit_search_engine_dialog.cc | 266 +++ .../browser/ui/views/edit_search_engine_dialog.h | 105 + chrome/browser/ui/views/event_utils.cc | 31 + chrome/browser/ui/views/event_utils.h | 28 + .../views/extensions/browser_action_drag_data.cc | 89 + .../ui/views/extensions/browser_action_drag_data.h | 64 + .../browser_action_drag_data_unittest.cc | 56 + .../browser_action_overflow_menu_controller.cc | 209 ++ .../browser_action_overflow_menu_controller.h | 117 + .../views/extensions/extension_install_prompt.cc | 166 ++ .../views/extensions/extension_install_prompt2.cc | 318 +++ .../views/extensions/extension_installed_bubble.cc | 353 +++ .../views/extensions/extension_installed_bubble.h | 86 + .../browser/ui/views/extensions/extension_popup.cc | 423 ++++ .../browser/ui/views/extensions/extension_popup.h | 224 ++ .../browser/ui/views/extensions/extension_view.cc | 207 ++ .../browser/ui/views/extensions/extension_view.h | 112 + .../browser/ui/views/external_protocol_dialog.cc | 181 ++ chrome/browser/ui/views/external_protocol_dialog.h | 59 + chrome/browser/ui/views/find_bar_host.cc | 297 +++ chrome/browser/ui/views/find_bar_host.h | 130 + chrome/browser/ui/views/find_bar_host_gtk.cc | 30 + .../ui/views/find_bar_host_interactive_uitest.cc | 177 ++ chrome/browser/ui/views/find_bar_host_uitest.cc | 88 + chrome/browser/ui/views/find_bar_host_win.cc | 33 + chrome/browser/ui/views/find_bar_view.cc | 545 +++++ chrome/browser/ui/views/find_bar_view.h | 126 + chrome/browser/ui/views/first_run_bubble.cc | 537 +++++ chrome/browser/ui/views/first_run_bubble.h | 56 + .../ui/views/first_run_search_engine_view.cc | 430 ++++ .../ui/views/first_run_search_engine_view.h | 144 ++ .../ui/views/frame/app_panel_browser_frame_view.cc | 505 ++++ .../ui/views/frame/app_panel_browser_frame_view.h | 130 + .../browser/ui/views/frame/browser_bubble_host.cc | 43 + .../browser/ui/views/frame/browser_bubble_host.h | 43 + chrome/browser/ui/views/frame/browser_frame.h | 80 + chrome/browser/ui/views/frame/browser_frame_gtk.cc | 154 ++ chrome/browser/ui/views/frame/browser_frame_gtk.h | 85 + chrome/browser/ui/views/frame/browser_frame_win.cc | 324 +++ chrome/browser/ui/views/frame/browser_frame_win.h | 101 + .../ui/views/frame/browser_non_client_frame_view.h | 33 + chrome/browser/ui/views/frame/browser_root_view.cc | 155 ++ chrome/browser/ui/views/frame/browser_root_view.h | 63 + chrome/browser/ui/views/frame/browser_view.cc | 2516 ++++++++++++++++++++ chrome/browser/ui/views/frame/browser_view.h | 658 +++++ .../browser/ui/views/frame/browser_view_layout.cc | 414 ++++ .../browser/ui/views/frame/browser_view_layout.h | 112 + .../browser/ui/views/frame/contents_container.cc | 128 + chrome/browser/ui/views/frame/contents_container.h | 78 + .../ui/views/frame/glass_browser_frame_view.cc | 511 ++++ .../ui/views/frame/glass_browser_frame_view.h | 103 + .../ui/views/frame/opaque_browser_frame_view.cc | 1052 ++++++++ .../ui/views/frame/opaque_browser_frame_view.h | 148 ++ .../ui/views/frame/popup_non_client_frame_view.cc | 58 + .../ui/views/frame/popup_non_client_frame_view.h | 40 + chrome/browser/ui/views/fullscreen_exit_bubble.cc | 289 +++ chrome/browser/ui/views/fullscreen_exit_bubble.h | 109 + chrome/browser/ui/views/generic_info_view.cc | 105 + chrome/browser/ui/views/generic_info_view.h | 67 + .../browser/ui/views/generic_info_view_unittest.cc | 65 + chrome/browser/ui/views/html_dialog_view.cc | 219 ++ chrome/browser/ui/views/html_dialog_view.h | 88 + .../ui/views/html_dialog_view_browsertest.cc | 205 ++ chrome/browser/ui/views/hung_renderer_view.cc | 464 ++++ chrome/browser/ui/views/importer_lock_view.cc | 78 + chrome/browser/ui/views/importer_lock_view.h | 48 + chrome/browser/ui/views/importer_view.cc | 287 +++ chrome/browser/ui/views/importer_view.h | 109 + chrome/browser/ui/views/importing_progress_view.cc | 312 +++ chrome/browser/ui/views/importing_progress_view.h | 95 + chrome/browser/ui/views/indexed_db_info_view.cc | 131 + chrome/browser/ui/views/indexed_db_info_view.h | 55 + chrome/browser/ui/views/info_bubble.cc | 550 +++++ chrome/browser/ui/views/info_bubble.h | 310 +++ chrome/browser/ui/views/info_bubble_unittest.cc | 237 ++ .../ui/views/infobars/after_translate_infobar.cc | 169 ++ .../ui/views/infobars/after_translate_infobar.h | 79 + .../ui/views/infobars/before_translate_infobar.cc | 173 ++ .../ui/views/infobars/before_translate_infobar.h | 76 + .../browser/ui/views/infobars/extension_infobar.cc | 183 ++ .../browser/ui/views/infobars/extension_infobar.h | 72 + .../ui/views/infobars/infobar_button_border.cc | 141 ++ .../ui/views/infobars/infobar_button_border.h | 53 + .../browser/ui/views/infobars/infobar_container.cc | 164 ++ .../browser/ui/views/infobars/infobar_container.h | 94 + .../ui/views/infobars/infobar_text_button.cc | 57 + .../ui/views/infobars/infobar_text_button.h | 38 + chrome/browser/ui/views/infobars/infobars.cc | 615 +++++ chrome/browser/ui/views/infobars/infobars.h | 251 ++ .../ui/views/infobars/translate_infobar_base.cc | 178 ++ .../ui/views/infobars/translate_infobar_base.h | 75 + .../ui/views/infobars/translate_message_infobar.cc | 57 + .../ui/views/infobars/translate_message_infobar.h | 29 + chrome/browser/ui/views/instant_confirm_view.cc | 94 + chrome/browser/ui/views/instant_confirm_view.h | 41 + chrome/browser/ui/views/js_modal_dialog_views.cc | 155 ++ chrome/browser/ui/views/js_modal_dialog_views.h | 60 + chrome/browser/ui/views/keyword_editor_view.cc | 306 +++ chrome/browser/ui/views/keyword_editor_view.h | 117 + chrome/browser/ui/views/list_background.h | 37 + chrome/browser/ui/views/local_storage_info_view.cc | 133 ++ chrome/browser/ui/views/local_storage_info_view.h | 57 + .../ui/views/local_storage_set_item_info_view.cc | 127 + .../ui/views/local_storage_set_item_info_view.h | 60 + .../browser/ui/views/location_bar/click_handler.cc | 36 + .../browser/ui/views/location_bar/click_handler.h | 34 + .../location_bar/content_setting_image_view.cc | 92 + .../location_bar/content_setting_image_view.h | 61 + .../ui/views/location_bar/ev_bubble_view.cc | 29 + .../browser/ui/views/location_bar/ev_bubble_view.h | 38 + .../views/location_bar/icon_label_bubble_view.cc | 79 + .../ui/views/location_bar/icon_label_bubble_view.h | 64 + .../ui/views/location_bar/keyword_hint_view.cc | 127 + .../ui/views/location_bar/keyword_hint_view.h | 62 + .../ui/views/location_bar/location_bar_view.cc | 1232 ++++++++++ .../ui/views/location_bar/location_bar_view.h | 413 ++++ .../ui/views/location_bar/location_icon_view.cc | 23 + .../ui/views/location_bar/location_icon_view.h | 35 + .../views/location_bar/page_action_image_view.cc | 243 ++ .../ui/views/location_bar/page_action_image_view.h | 113 + .../location_bar/page_action_with_badge_view.cc | 39 + .../location_bar/page_action_with_badge_view.h | 37 + .../ui/views/location_bar/selected_keyword_view.cc | 71 + .../ui/views/location_bar/selected_keyword_view.h | 59 + chrome/browser/ui/views/location_bar/star_view.cc | 75 + chrome/browser/ui/views/location_bar/star_view.h | 48 + .../ui/views/location_bar/suggested_text_view.cc | 106 + .../ui/views/location_bar/suggested_text_view.h | 56 + chrome/browser/ui/views/login_view.cc | 152 ++ chrome/browser/ui/views/login_view.h | 82 + chrome/browser/ui/views/modal_dialog_delegate.cc | 40 + chrome/browser/ui/views/modal_dialog_delegate.h | 31 + .../browser/ui/views/notifications/balloon_view.cc | 503 ++++ .../browser/ui/views/notifications/balloon_view.h | 172 ++ .../ui/views/notifications/balloon_view_host.cc | 92 + .../ui/views/notifications/balloon_view_host.h | 59 + .../ui/views/options/advanced_contents_view.cc | 1727 ++++++++++++++ .../ui/views/options/advanced_contents_view.h | 39 + .../browser/ui/views/options/advanced_page_view.cc | 145 ++ .../browser/ui/views/options/advanced_page_view.h | 46 + .../views/options/content_exceptions_table_view.cc | 33 + .../views/options/content_exceptions_table_view.h | 31 + .../ui/views/options/content_filter_page_view.cc | 231 ++ .../ui/views/options/content_filter_page_view.h | 49 + .../browser/ui/views/options/content_page_view.cc | 496 ++++ .../browser/ui/views/options/content_page_view.h | 117 + .../views/options/content_settings_window_view.cc | 210 ++ .../views/options/content_settings_window_view.h | 92 + .../ui/views/options/cookie_filter_page_view.cc | 116 + .../ui/views/options/cookie_filter_page_view.h | 52 + chrome/browser/ui/views/options/cookies_view.cc | 397 +++ chrome/browser/ui/views/options/cookies_view.h | 159 ++ .../ui/views/options/exception_editor_view.cc | 175 ++ .../ui/views/options/exception_editor_view.h | 114 + .../ui/views/options/exceptions_page_view.cc | 193 ++ .../ui/views/options/exceptions_page_view.h | 75 + chrome/browser/ui/views/options/exceptions_view.cc | 275 +++ chrome/browser/ui/views/options/exceptions_view.h | 117 + .../views/options/fonts_languages_window_view.cc | 134 ++ .../ui/views/options/fonts_languages_window_view.h | 74 + chrome/browser/ui/views/options/fonts_page_view.cc | 435 ++++ chrome/browser/ui/views/options/fonts_page_view.h | 130 + .../browser/ui/views/options/general_page_view.cc | 902 +++++++ .../browser/ui/views/options/general_page_view.h | 173 ++ .../ui/views/options/languages_page_view.cc | 579 +++++ .../browser/ui/views/options/languages_page_view.h | 119 + .../ui/views/options/managed_prefs_banner_view.cc | 71 + .../ui/views/options/managed_prefs_banner_view.h | 52 + .../browser/ui/views/options/options_group_view.cc | 141 ++ .../browser/ui/views/options/options_group_view.h | 63 + .../browser/ui/views/options/options_page_view.cc | 42 + .../browser/ui/views/options/options_page_view.h | 52 + .../ui/views/options/options_window_view.cc | 244 ++ .../options/passwords_exceptions_window_view.cc | 111 + .../options/passwords_exceptions_window_view.h | 67 + .../ui/views/options/passwords_page_view.cc | 367 +++ .../browser/ui/views/options/passwords_page_view.h | 200 ++ .../ui/views/options/plugin_filter_page_view.cc | 49 + .../ui/views/options/plugin_filter_page_view.h | 32 + .../options/simple_content_exceptions_view.cc | 185 ++ .../views/options/simple_content_exceptions_view.h | 95 + chrome/browser/ui/views/page_info_bubble_view.cc | 355 +++ chrome/browser/ui/views/page_info_bubble_view.h | 85 + .../ui/views/pinned_contents_info_bubble.cc | 53 + .../browser/ui/views/pinned_contents_info_bubble.h | 68 + chrome/browser/ui/views/reload_button.cc | 137 ++ chrome/browser/ui/views/reload_button.h | 82 + chrome/browser/ui/views/reload_button_unittest.cc | 150 ++ .../browser/ui/views/repost_form_warning_view.cc | 82 + chrome/browser/ui/views/repost_form_warning_view.h | 57 + chrome/browser/ui/views/restart_message_box.cc | 64 + chrome/browser/ui/views/restart_message_box.h | 43 + chrome/browser/ui/views/sad_tab_view.cc | 147 ++ chrome/browser/ui/views/sad_tab_view.h | 62 + chrome/browser/ui/views/select_file_dialog.cc | 484 ++++ chrome/browser/ui/views/shell_dialogs_win.cc | 1130 +++++++++ .../browser/ui/views/shell_dialogs_win_unittest.cc | 44 + .../views/ssl_client_certificate_selector_win.cc | 73 + chrome/browser/ui/views/status_bubble_views.cc | 836 +++++++ chrome/browser/ui/views/status_bubble_views.h | 136 ++ .../ui/views/status_icons/status_icon_win.cc | 89 + .../ui/views/status_icons/status_icon_win.h | 65 + .../ui/views/status_icons/status_tray_gtk.cc | 10 + .../ui/views/status_icons/status_tray_win.cc | 81 + .../ui/views/status_icons/status_tray_win.h | 43 + .../views/status_icons/status_tray_win_unittest.cc | 55 + .../tab_contents/native_tab_contents_container.h | 48 + .../native_tab_contents_container_gtk.cc | 152 ++ .../native_tab_contents_container_gtk.h | 46 + .../native_tab_contents_container_win.cc | 143 ++ .../native_tab_contents_container_win.h | 41 + .../tab_contents/render_view_context_menu_views.cc | 98 + .../tab_contents/render_view_context_menu_views.h | 47 + .../views/tab_contents/tab_contents_container.cc | 145 ++ .../ui/views/tab_contents/tab_contents_container.h | 106 + .../ui/views/tab_contents/tab_contents_drag_win.cc | 367 +++ .../ui/views/tab_contents/tab_contents_drag_win.h | 100 + .../ui/views/tab_contents/tab_contents_view_gtk.cc | 515 ++++ .../ui/views/tab_contents/tab_contents_view_gtk.h | 141 ++ .../ui/views/tab_contents/tab_contents_view_win.cc | 577 +++++ .../ui/views/tab_contents/tab_contents_view_win.h | 152 ++ chrome/browser/ui/views/tab_icon_view.cc | 156 ++ chrome/browser/ui/views/tab_icon_view.h | 73 + chrome/browser/ui/views/tabs/base_tab.cc | 480 ++++ chrome/browser/ui/views/tabs/base_tab.h | 205 ++ chrome/browser/ui/views/tabs/base_tab_strip.cc | 473 ++++ chrome/browser/ui/views/tabs/base_tab_strip.h | 266 +++ .../ui/views/tabs/browser_tab_strip_controller.cc | 428 ++++ .../ui/views/tabs/browser_tab_strip_controller.h | 121 + .../ui/views/tabs/dragged_tab_controller.cc | 1342 +++++++++++ .../browser/ui/views/tabs/dragged_tab_controller.h | 339 +++ chrome/browser/ui/views/tabs/dragged_tab_view.cc | 222 ++ chrome/browser/ui/views/tabs/dragged_tab_view.h | 103 + .../browser/ui/views/tabs/native_view_photobooth.h | 44 + .../ui/views/tabs/native_view_photobooth_gtk.cc | 34 + .../ui/views/tabs/native_view_photobooth_gtk.h | 30 + .../ui/views/tabs/native_view_photobooth_win.cc | 165 ++ .../ui/views/tabs/native_view_photobooth_win.h | 58 + chrome/browser/ui/views/tabs/side_tab.cc | 114 + chrome/browser/ui/views/tabs/side_tab.h | 44 + chrome/browser/ui/views/tabs/side_tab_strip.cc | 260 ++ chrome/browser/ui/views/tabs/side_tab_strip.h | 67 + chrome/browser/ui/views/tabs/tab.cc | 610 +++++ chrome/browser/ui/views/tabs/tab.h | 141 ++ chrome/browser/ui/views/tabs/tab_controller.h | 59 + chrome/browser/ui/views/tabs/tab_dragging_test.cc | 515 ++++ chrome/browser/ui/views/tabs/tab_renderer_data.h | 46 + chrome/browser/ui/views/tabs/tab_strip.cc | 982 ++++++++ chrome/browser/ui/views/tabs/tab_strip.h | 287 +++ .../browser/ui/views/tabs/tab_strip_controller.h | 73 + chrome/browser/ui/views/task_manager_view.cc | 744 ++++++ chrome/browser/ui/views/textfield_views.cc | 34 + chrome/browser/ui/views/textfield_views.h | 27 + chrome/browser/ui/views/theme_background.cc | 60 + chrome/browser/ui/views/theme_background.h | 41 + chrome/browser/ui/views/theme_helpers.cc | 92 + chrome/browser/ui/views/theme_helpers.h | 30 + .../browser/ui/views/theme_install_bubble_view.cc | 165 ++ .../browser/ui/views/theme_install_bubble_view.h | 79 + chrome/browser/ui/views/toolbar_view.cc | 688 ++++++ chrome/browser/ui/views/toolbar_view.h | 221 ++ .../ui/views/unhandled_keyboard_event_handler.cc | 75 + .../ui/views/unhandled_keyboard_event_handler.h | 40 + chrome/browser/ui/views/uninstall_view.cc | 152 ++ chrome/browser/ui/views/uninstall_view.h | 62 + .../ui/views/update_recommended_message_box.cc | 99 + .../ui/views/update_recommended_message_box.h | 46 + chrome/browser/ui/views/url_picker.cc | 249 ++ chrome/browser/ui/views/url_picker.h | 110 + chrome/browser/ui/views/user_data_dir_dialog.cc | 99 + chrome/browser/ui/views/user_data_dir_dialog.h | 72 + chrome/browser/ui/views/window.cc | 29 + chrome/browser/ui/views/window.h | 29 + chrome/browser/ui/views/wrench_menu.cc | 737 ++++++ chrome/browser/ui/views/wrench_menu.h | 92 + chrome/browser/views/PRESUBMIT.py | 13 - chrome/browser/views/about_chrome_view.cc | 819 ------- chrome/browser/views/about_chrome_view.h | 168 +- chrome/browser/views/about_ipc_dialog.cc | 460 ---- chrome/browser/views/about_ipc_dialog.h | 74 +- chrome/browser/views/accelerator_table_gtk.cc | 159 -- chrome/browser/views/accelerator_table_gtk.h | 27 +- .../views/accessibility_event_router_views.cc | 305 --- .../views/accessibility_event_router_views.h | 147 +- .../accessibility_event_router_views_unittest.cc | 174 -- chrome/browser/views/accessible_pane_view.cc | 251 -- chrome/browser/views/accessible_pane_view.h | 93 +- chrome/browser/views/accessible_view_helper.cc | 89 - chrome/browser/views/accessible_view_helper.h | 76 +- chrome/browser/views/app_launched_animation_win.cc | 135 -- chrome/browser/views/appcache_info_view.cc | 40 - chrome/browser/views/appcache_info_view.h | 15 +- .../autocomplete_popup_contents_view.cc | 1191 --------- .../autocomplete_popup_contents_view.h | 170 +- .../views/autocomplete/autocomplete_popup_gtk.cc | 37 - .../views/autocomplete/autocomplete_popup_gtk.h | 21 +- .../views/autocomplete/autocomplete_popup_win.cc | 46 - .../views/autocomplete/autocomplete_popup_win.h | 26 +- chrome/browser/views/autofill_profiles_view_win.cc | 1327 ----------- chrome/browser/views/autofill_profiles_view_win.h | 433 +--- .../views/bookmark_bar_instructions_view.cc | 108 - .../browser/views/bookmark_bar_instructions_view.h | 61 +- chrome/browser/views/bookmark_bar_view.cc | 1734 -------------- chrome/browser/views/bookmark_bar_view.h | 501 +--- chrome/browser/views/bookmark_bar_view_test.cc | 1358 ----------- chrome/browser/views/bookmark_bar_view_unittest.cc | 47 - chrome/browser/views/bookmark_bubble_view.cc | 413 ---- chrome/browser/views/bookmark_bubble_view.h | 155 +- chrome/browser/views/bookmark_context_menu.cc | 100 - chrome/browser/views/bookmark_context_menu.h | 69 +- .../bookmark_context_menu_controller_views.cc | 292 --- .../views/bookmark_context_menu_controller_views.h | 86 +- chrome/browser/views/bookmark_context_menu_test.cc | 311 --- chrome/browser/views/bookmark_editor_view.cc | 581 ----- chrome/browser/views/bookmark_editor_view.h | 258 +- .../browser/views/bookmark_editor_view_unittest.cc | 366 --- chrome/browser/views/bookmark_editor_viw.h | 0 .../views/bookmark_menu_controller_views.cc | 415 ---- .../browser/views/bookmark_menu_controller_views.h | 193 +- chrome/browser/views/browser_actions_container.cc | 1100 --------- chrome/browser/views/browser_actions_container.h | 502 +--- .../views/browser_actions_container_browsertest.cc | 200 -- chrome/browser/views/browser_bubble.cc | 126 - chrome/browser/views/browser_bubble.h | 124 +- chrome/browser/views/browser_bubble_gtk.cc | 120 - chrome/browser/views/browser_bubble_win.cc | 132 - chrome/browser/views/browser_dialogs.h | 123 +- .../browser_keyboard_accessibility_test_win.cc | 210 -- chrome/browser/views/bubble_border.cc | 443 ---- chrome/browser/views/bubble_border.h | 165 +- chrome/browser/views/certificate_viewer_win.cc | 32 - chrome/browser/views/chrome_views_delegate.cc | 102 - chrome/browser/views/chrome_views_delegate.h | 32 +- chrome/browser/views/clear_browsing_data.cc | 472 ---- chrome/browser/views/clear_browsing_data.h | 123 +- chrome/browser/views/clear_browsing_data_view.cc | 371 --- chrome/browser/views/clear_browsing_data_view.h | 116 +- chrome/browser/views/clear_data_view.cc | 174 -- chrome/browser/views/clear_data_view.h | 92 +- chrome/browser/views/clear_server_data.cc | 344 --- chrome/browser/views/clear_server_data.h | 111 +- chrome/browser/views/collected_cookies_win.cc | 391 --- chrome/browser/views/collected_cookies_win.h | 89 +- chrome/browser/views/confirm_message_box_dialog.cc | 104 - chrome/browser/views/confirm_message_box_dialog.h | 95 +- .../browser/views/constrained_html_delegate_win.cc | 113 - chrome/browser/views/constrained_window_win.cc | 673 ------ chrome/browser/views/constrained_window_win.h | 72 +- .../views/content_setting_bubble_contents.cc | 379 --- .../views/content_setting_bubble_contents.h | 97 +- chrome/browser/views/cookie_info_view.cc | 278 --- chrome/browser/views/cookie_info_view.h | 114 +- .../views/create_application_shortcut_view.cc | 458 ---- .../views/create_application_shortcut_view.h | 86 +- chrome/browser/views/database_info_view.cc | 144 -- chrome/browser/views/database_info_view.h | 49 +- chrome/browser/views/database_open_info_view.cc | 40 - chrome/browser/views/database_open_info_view.h | 24 +- chrome/browser/views/default_search_view.cc | 103 - chrome/browser/views/default_search_view.h | 58 +- chrome/browser/views/detachable_toolbar_view.cc | 119 - chrome/browser/views/detachable_toolbar_view.h | 84 +- chrome/browser/views/dialog_stubs_gtk.cc | 79 - chrome/browser/views/dom_view.cc | 62 - chrome/browser/views/dom_view.h | 54 +- chrome/browser/views/dom_view_browsertest.cc | 93 - chrome/browser/views/download_item_view.cc | 1077 --------- chrome/browser/views/download_item_view.h | 273 +-- chrome/browser/views/download_shelf_view.cc | 439 ---- chrome/browser/views/download_shelf_view.h | 152 +- .../views/download_started_animation_win.cc | 180 -- chrome/browser/views/dropdown_bar_host.cc | 310 --- chrome/browser/views/dropdown_bar_host.h | 181 +- chrome/browser/views/dropdown_bar_host_gtk.cc | 31 - chrome/browser/views/dropdown_bar_host_win.cc | 48 - chrome/browser/views/dropdown_bar_view.h | 47 +- chrome/browser/views/edit_search_engine_dialog.cc | 266 --- chrome/browser/views/edit_search_engine_dialog.h | 100 +- chrome/browser/views/event_utils.cc | 31 - chrome/browser/views/event_utils.h | 27 +- .../views/extensions/browser_action_drag_data.cc | 89 - .../views/extensions/browser_action_drag_data.h | 57 +- .../browser_action_drag_data_unittest.cc | 56 - .../browser_action_overflow_menu_controller.cc | 209 -- .../browser_action_overflow_menu_controller.h | 110 +- .../views/extensions/extension_install_prompt.cc | 167 -- .../views/extensions/extension_install_prompt2.cc | 320 --- .../views/extensions/extension_installed_bubble.cc | 389 --- .../views/extensions/extension_installed_bubble.h | 78 +- chrome/browser/views/extensions/extension_popup.cc | 423 ---- chrome/browser/views/extensions/extension_popup.h | 219 +- chrome/browser/views/extensions/extension_view.cc | 207 -- chrome/browser/views/extensions/extension_view.h | 105 +- chrome/browser/views/external_protocol_dialog.cc | 181 -- chrome/browser/views/external_protocol_dialog.h | 54 +- chrome/browser/views/find_bar_host.cc | 297 --- chrome/browser/views/find_bar_host.h | 123 +- chrome/browser/views/find_bar_host_gtk.cc | 30 - .../views/find_bar_host_interactive_uitest.cc | 176 -- chrome/browser/views/find_bar_host_uitest.cc | 88 - chrome/browser/views/find_bar_host_win.cc | 33 - chrome/browser/views/find_bar_view.cc | 526 ---- chrome/browser/views/find_bar_view.h | 119 +- chrome/browser/views/first_run_bubble.cc | 537 ----- chrome/browser/views/first_run_bubble.h | 49 +- .../browser/views/first_run_search_engine_view.cc | 430 ---- .../browser/views/first_run_search_engine_view.h | 135 +- .../views/frame/app_panel_browser_frame_view.cc | 505 ---- .../views/frame/app_panel_browser_frame_view.h | 123 +- chrome/browser/views/frame/browser_bubble_host.cc | 43 - chrome/browser/views/frame/browser_bubble_host.h | 36 +- chrome/browser/views/frame/browser_frame.h | 73 +- chrome/browser/views/frame/browser_frame_gtk.cc | 154 -- chrome/browser/views/frame/browser_frame_gtk.h | 78 +- chrome/browser/views/frame/browser_frame_win.cc | 324 --- chrome/browser/views/frame/browser_frame_win.h | 94 +- .../views/frame/browser_non_client_frame_view.h | 26 +- chrome/browser/views/frame/browser_root_view.cc | 155 -- chrome/browser/views/frame/browser_root_view.h | 62 +- chrome/browser/views/frame/browser_view.cc | 2472 ------------------- chrome/browser/views/frame/browser_view.h | 651 +---- chrome/browser/views/frame/browser_view_layout.cc | 414 ---- chrome/browser/views/frame/browser_view_layout.h | 103 +- chrome/browser/views/frame/contents_container.cc | 200 -- chrome/browser/views/frame/contents_container.h | 79 +- .../views/frame/glass_browser_frame_view.cc | 511 ---- .../browser/views/frame/glass_browser_frame_view.h | 96 +- .../views/frame/opaque_browser_frame_view.cc | 1031 -------- .../views/frame/opaque_browser_frame_view.h | 141 +- .../views/frame/popup_non_client_frame_view.cc | 58 - .../views/frame/popup_non_client_frame_view.h | 33 +- chrome/browser/views/fullscreen_exit_bubble.cc | 288 --- chrome/browser/views/fullscreen_exit_bubble.h | 106 +- chrome/browser/views/generic_info_view.cc | 105 - chrome/browser/views/generic_info_view.h | 58 +- chrome/browser/views/generic_info_view_unittest.cc | 65 - chrome/browser/views/html_dialog_view.cc | 219 -- chrome/browser/views/html_dialog_view.h | 83 +- .../browser/views/html_dialog_view_browsertest.cc | 205 -- chrome/browser/views/hung_renderer_view.cc | 464 ---- chrome/browser/views/importer_lock_view.cc | 78 - chrome/browser/views/importer_lock_view.h | 45 +- chrome/browser/views/importer_view.cc | 287 --- chrome/browser/views/importer_view.h | 102 +- chrome/browser/views/importing_progress_view.cc | 312 --- chrome/browser/views/importing_progress_view.h | 88 +- chrome/browser/views/indexed_db_info_view.cc | 131 - chrome/browser/views/indexed_db_info_view.h | 48 +- chrome/browser/views/info_bubble.cc | 542 ----- chrome/browser/views/info_bubble.h | 300 +-- chrome/browser/views/info_bubble_unittest.cc | 237 -- .../views/infobars/after_translate_infobar.cc | 169 -- .../views/infobars/after_translate_infobar.h | 72 +- .../views/infobars/before_translate_infobar.cc | 173 -- .../views/infobars/before_translate_infobar.h | 69 +- chrome/browser/views/infobars/extension_infobar.cc | 183 -- chrome/browser/views/infobars/extension_infobar.h | 65 +- .../views/infobars/infobar_button_border.cc | 141 -- .../browser/views/infobars/infobar_button_border.h | 46 +- chrome/browser/views/infobars/infobar_container.cc | 164 -- chrome/browser/views/infobars/infobar_container.h | 87 +- .../browser/views/infobars/infobar_text_button.cc | 57 - .../browser/views/infobars/infobar_text_button.h | 31 +- chrome/browser/views/infobars/infobars.cc | 614 ----- chrome/browser/views/infobars/infobars.h | 244 +- .../views/infobars/translate_infobar_base.cc | 178 -- .../views/infobars/translate_infobar_base.h | 68 +- .../views/infobars/translate_message_infobar.cc | 57 - .../views/infobars/translate_message_infobar.h | 22 +- chrome/browser/views/instant_confirm_view.cc | 97 - chrome/browser/views/instant_confirm_view.h | 34 +- chrome/browser/views/js_modal_dialog_views.cc | 155 -- chrome/browser/views/js_modal_dialog_views.h | 53 +- chrome/browser/views/keyword_editor_view.cc | 306 --- chrome/browser/views/keyword_editor_view.h | 110 +- chrome/browser/views/list_background.h | 28 +- chrome/browser/views/local_storage_info_view.cc | 133 -- chrome/browser/views/local_storage_info_view.h | 48 +- .../views/local_storage_set_item_info_view.cc | 127 - .../views/local_storage_set_item_info_view.h | 51 +- chrome/browser/views/location_bar/click_handler.cc | 36 - chrome/browser/views/location_bar/click_handler.h | 25 +- .../location_bar/content_setting_image_view.cc | 92 - .../location_bar/content_setting_image_view.h | 54 +- .../browser/views/location_bar/ev_bubble_view.cc | 29 - chrome/browser/views/location_bar/ev_bubble_view.h | 29 +- .../views/location_bar/icon_label_bubble_view.cc | 79 - .../views/location_bar/icon_label_bubble_view.h | 57 +- .../views/location_bar/keyword_hint_view.cc | 127 - .../browser/views/location_bar/keyword_hint_view.h | 55 +- .../views/location_bar/location_bar_view.cc | 1195 ---------- .../browser/views/location_bar/location_bar_view.h | 397 +-- .../views/location_bar/location_icon_view.cc | 23 - .../views/location_bar/location_icon_view.h | 28 +- .../views/location_bar/page_action_image_view.cc | 243 -- .../views/location_bar/page_action_image_view.h | 106 +- .../location_bar/page_action_with_badge_view.cc | 39 - .../location_bar/page_action_with_badge_view.h | 30 +- .../views/location_bar/selected_keyword_view.cc | 71 - .../views/location_bar/selected_keyword_view.h | 52 +- chrome/browser/views/location_bar/star_view.cc | 75 - chrome/browser/views/location_bar/star_view.h | 41 +- chrome/browser/views/login_view.cc | 152 -- chrome/browser/views/login_view.h | 77 +- chrome/browser/views/modal_dialog_delegate.cc | 40 - chrome/browser/views/modal_dialog_delegate.h | 22 +- chrome/browser/views/notifications/balloon_view.cc | 502 ---- chrome/browser/views/notifications/balloon_view.h | 164 +- .../views/notifications/balloon_view_host.cc | 92 - .../views/notifications/balloon_view_host.h | 52 +- .../views/options/advanced_contents_view.cc | 1725 -------------- .../browser/views/options/advanced_contents_view.h | 36 +- chrome/browser/views/options/advanced_page_view.cc | 145 -- chrome/browser/views/options/advanced_page_view.h | 39 +- .../views/options/content_exceptions_table_view.cc | 33 - .../views/options/content_exceptions_table_view.h | 24 +- .../views/options/content_filter_page_view.cc | 227 -- .../views/options/content_filter_page_view.h | 42 +- chrome/browser/views/options/content_page_view.cc | 496 ---- chrome/browser/views/options/content_page_view.h | 110 +- .../views/options/content_settings_window_view.cc | 210 -- .../views/options/content_settings_window_view.h | 83 +- .../views/options/cookie_filter_page_view.cc | 116 - .../views/options/cookie_filter_page_view.h | 43 +- chrome/browser/views/options/cookies_view.cc | 397 --- chrome/browser/views/options/cookies_view.h | 152 +- .../browser/views/options/exception_editor_view.cc | 175 -- .../browser/views/options/exception_editor_view.h | 107 +- .../browser/views/options/exceptions_page_view.cc | 193 -- .../browser/views/options/exceptions_page_view.h | 70 +- chrome/browser/views/options/exceptions_view.cc | 275 --- chrome/browser/views/options/exceptions_view.h | 108 +- .../views/options/fonts_languages_window_view.cc | 134 -- .../views/options/fonts_languages_window_view.h | 69 +- chrome/browser/views/options/fonts_page_view.cc | 435 ---- chrome/browser/views/options/fonts_page_view.h | 125 +- chrome/browser/views/options/general_page_view.cc | 883 ------- chrome/browser/views/options/general_page_view.h | 165 +- .../browser/views/options/languages_page_view.cc | 579 ----- chrome/browser/views/options/languages_page_view.h | 116 +- .../views/options/managed_prefs_banner_view.cc | 71 - .../views/options/managed_prefs_banner_view.h | 45 +- chrome/browser/views/options/options_group_view.cc | 141 -- chrome/browser/views/options/options_group_view.h | 60 +- chrome/browser/views/options/options_page_view.cc | 42 - chrome/browser/views/options/options_page_view.h | 49 +- .../browser/views/options/options_window_view.cc | 244 -- .../options/passwords_exceptions_window_view.cc | 111 - .../options/passwords_exceptions_window_view.h | 62 +- .../browser/views/options/passwords_page_view.cc | 367 --- chrome/browser/views/options/passwords_page_view.h | 195 +- .../views/options/plugin_filter_page_view.cc | 49 - .../views/options/plugin_filter_page_view.h | 23 +- .../options/simple_content_exceptions_view.cc | 185 -- .../views/options/simple_content_exceptions_view.h | 86 +- chrome/browser/views/page_info_bubble_view.cc | 352 --- chrome/browser/views/page_info_bubble_view.h | 76 +- .../browser/views/pinned_contents_info_bubble.cc | 53 - chrome/browser/views/pinned_contents_info_bubble.h | 61 +- chrome/browser/views/reload_button.cc | 137 -- chrome/browser/views/reload_button.h | 79 +- chrome/browser/views/reload_button_unittest.cc | 150 -- chrome/browser/views/repost_form_warning_view.cc | 82 - chrome/browser/views/repost_form_warning_view.h | 52 +- chrome/browser/views/restart_message_box.cc | 64 - chrome/browser/views/restart_message_box.h | 36 +- chrome/browser/views/sad_tab_view.cc | 145 -- chrome/browser/views/sad_tab_view.h | 57 +- chrome/browser/views/select_file_dialog.cc | 483 ---- chrome/browser/views/shell_dialogs_win.cc | 1130 --------- chrome/browser/views/shell_dialogs_win_unittest.cc | 44 - .../views/ssl_client_certificate_selector_win.cc | 73 - chrome/browser/views/status_bubble_views.cc | 835 ------- chrome/browser/views/status_bubble_views.h | 129 +- .../browser/views/status_icons/status_icon_win.cc | 89 - .../browser/views/status_icons/status_icon_win.h | 58 +- .../browser/views/status_icons/status_tray_gtk.cc | 10 - .../browser/views/status_icons/status_tray_win.cc | 81 - .../browser/views/status_icons/status_tray_win.h | 34 +- .../views/status_icons/status_tray_win_unittest.cc | 55 - .../tab_contents/native_tab_contents_container.h | 43 +- .../native_tab_contents_container_gtk.cc | 152 -- .../native_tab_contents_container_gtk.h | 41 +- .../native_tab_contents_container_win.cc | 143 -- .../native_tab_contents_container_win.h | 36 +- .../tab_contents/render_view_context_menu_views.cc | 98 - .../tab_contents/render_view_context_menu_views.h | 40 +- .../views/tab_contents/tab_contents_container.cc | 121 - .../views/tab_contents/tab_contents_container.h | 74 +- .../views/tab_contents/tab_contents_drag_win.cc | 367 --- .../views/tab_contents/tab_contents_drag_win.h | 95 +- .../views/tab_contents/tab_contents_view_gtk.cc | 515 ---- .../views/tab_contents/tab_contents_view_gtk.h | 134 +- .../views/tab_contents/tab_contents_view_win.cc | 577 ----- .../views/tab_contents/tab_contents_view_win.h | 147 +- chrome/browser/views/tab_icon_view.cc | 156 -- chrome/browser/views/tab_icon_view.h | 68 +- chrome/browser/views/tabs/base_tab.cc | 480 ---- chrome/browser/views/tabs/base_tab.h | 197 +- chrome/browser/views/tabs/base_tab_strip.cc | 473 ---- chrome/browser/views/tabs/base_tab_strip.h | 259 +- .../views/tabs/browser_tab_strip_controller.cc | 428 ---- .../views/tabs/browser_tab_strip_controller.h | 112 +- .../browser/views/tabs/dragged_tab_controller.cc | 1341 ----------- chrome/browser/views/tabs/dragged_tab_controller.h | 332 +-- chrome/browser/views/tabs/dragged_tab_view.cc | 222 -- chrome/browser/views/tabs/dragged_tab_view.h | 96 +- chrome/browser/views/tabs/native_view_photobooth.h | 39 +- .../views/tabs/native_view_photobooth_gtk.cc | 34 - .../views/tabs/native_view_photobooth_gtk.h | 25 +- .../views/tabs/native_view_photobooth_win.cc | 165 -- .../views/tabs/native_view_photobooth_win.h | 53 +- chrome/browser/views/tabs/side_tab.cc | 114 - chrome/browser/views/tabs/side_tab.h | 37 +- chrome/browser/views/tabs/side_tab_strip.cc | 260 -- chrome/browser/views/tabs/side_tab_strip.h | 60 +- chrome/browser/views/tabs/tab.cc | 610 ----- chrome/browser/views/tabs/tab.h | 134 +- chrome/browser/views/tabs/tab_controller.h | 52 +- chrome/browser/views/tabs/tab_dragging_test.cc | 515 ---- chrome/browser/views/tabs/tab_renderer_data.h | 39 +- chrome/browser/views/tabs/tab_strip.cc | 982 -------- chrome/browser/views/tabs/tab_strip.h | 280 +-- chrome/browser/views/tabs/tab_strip_controller.h | 66 +- chrome/browser/views/task_manager_view.cc | 691 ------ chrome/browser/views/textfield_views.cc | 34 - chrome/browser/views/textfield_views.h | 20 +- chrome/browser/views/theme_background.cc | 60 - chrome/browser/views/theme_background.h | 34 +- chrome/browser/views/theme_helpers.cc | 92 - chrome/browser/views/theme_helpers.h | 29 +- chrome/browser/views/theme_install_bubble_view.cc | 165 -- chrome/browser/views/theme_install_bubble_view.h | 72 +- chrome/browser/views/toolbar_view.cc | 741 ------ chrome/browser/views/toolbar_view.h | 229 +- .../views/unhandled_keyboard_event_handler.cc | 75 - .../views/unhandled_keyboard_event_handler.h | 35 +- chrome/browser/views/uninstall_view.cc | 152 -- chrome/browser/views/uninstall_view.h | 55 +- .../views/update_recommended_message_box.cc | 99 - .../browser/views/update_recommended_message_box.h | 43 +- chrome/browser/views/url_picker.cc | 249 -- chrome/browser/views/url_picker.h | 103 +- chrome/browser/views/user_data_dir_dialog.cc | 99 - chrome/browser/views/user_data_dir_dialog.h | 67 +- chrome/browser/views/window.cc | 29 - chrome/browser/views/window.h | 22 +- chrome/browser/views/wrench_menu.cc | 737 ------ chrome/browser/views/wrench_menu.h | 85 +- chrome/browser/web_applications/web_app.cc | 12 +- chrome/browser/web_applications/web_app.h | 6 +- .../browser/web_applications/web_app_unittest.cc | 2 +- chrome/browser/window_sizer.cc | 2 +- chrome/browser/window_sizer_linux.cc | 2 +- chrome/browser/window_sizer_win.cc | 2 +- chrome/browser/worker_host/worker_process_host.cc | 34 +- chrome/browser/worker_host/worker_process_host.h | 9 +- chrome/browser/wrench_menu_model.cc | 8 +- chrome/common/automation_constants.h | 36 + chrome/common/automation_messages.cc | 9 + chrome/common/automation_messages.h | 645 +++++ chrome/common/automation_messages_internal.h | 1460 ++++++++++++ chrome/common/child_process_info.cc | 3 + chrome/common/child_process_info.h | 3 +- chrome/common/child_process_logging.h | 2 +- chrome/common/child_process_logging_mac.mm | 22 +- chrome/common/chrome_switches.cc | 60 +- chrome/common/chrome_switches.h | 17 +- chrome/common/common_param_traits.cc | 14 +- chrome/common/common_param_traits.h | 6 +- chrome/common/common_param_traits_unittest.cc | 24 +- chrome/common/common_resources.grd | 1 + chrome/common/extensions/api/extension_api.json | 86 +- chrome/common/extensions/docs/a11y.html | 10 +- chrome/common/extensions/docs/api_index.html | 12 +- chrome/common/extensions/docs/api_other.html | 10 +- chrome/common/extensions/docs/autoupdate.html | 10 +- .../common/extensions/docs/background_pages.html | 10 +- chrome/common/extensions/docs/bookmarks.html | 10 +- chrome/common/extensions/docs/browserAction.html | 10 +- chrome/common/extensions/docs/build/build.py | 9 +- chrome/common/extensions/docs/build/directory.py | 169 +- chrome/common/extensions/docs/content_scripts.html | 10 +- chrome/common/extensions/docs/contextMenus.html | 10 +- chrome/common/extensions/docs/cookies.html | 10 +- chrome/common/extensions/docs/crx.html | 10 +- chrome/common/extensions/docs/css/ApiRefStyles.css | 7 + chrome/common/extensions/docs/devguide.html | 10 +- chrome/common/extensions/docs/docs.html | 10 +- chrome/common/extensions/docs/events.html | 10 +- .../docs/examples/api/bookmarks/basic.zip | Bin 5647 -> 5687 bytes .../examples/api/browserAction/make_page_red.zip | Bin 3930 -> 3970 bytes .../docs/examples/api/browserAction/print.zip | Bin 1614 -> 1654 bytes .../examples/api/browserAction/set_icon_path.zip | Bin 15530 -> 15570 bytes .../examples/api/browserAction/set_page_color.zip | Bin 5245 -> 5285 bytes .../docs/examples/api/contextMenus/basic.zip | Bin 3512 -> 3552 bytes .../extensions/docs/examples/api/cookies.zip | Bin 9255 -> 9295 bytes .../docs/examples/api/history/showHistory.zip | Bin 9608 -> 9648 bytes .../extensions/docs/examples/api/i18n/cld.zip | Bin 1310 -> 1350 bytes .../docs/examples/api/i18n/getMessage.zip | Bin 6739 -> 6779 bytes .../docs/examples/api/idle/idle_simple.zip | Bin 11992 -> 12032 bytes .../docs/examples/api/infobars/sandwichbar.zip | Bin 16055 -> 16095 bytes .../docs/examples/api/messaging/timer.zip | Bin 3558 -> 3598 bytes .../extensions/docs/examples/api/notifications.zip | Bin 49949 -> 49989 bytes .../docs/examples/api/omnibox/extension-docs.zip | Bin 74406 -> 74348 bytes .../api/omnibox/extension-docs/background.html | 12 +- .../api/omnibox/extension-docs/manifest.json | 3 +- .../docs/examples/api/omnibox/simple-example.zip | Bin 1208 -> 1185 bytes .../api/omnibox/simple-example/background.html | 4 +- .../api/omnibox/simple-example/manifest.json | 3 +- .../docs/examples/api/override/blank_ntp.zip | Bin 699 -> 739 bytes .../examples/api/override/override_igoogle.zip | Bin 496 -> 536 bytes .../api/pageAction/pageaction_by_content.zip | Bin 14181 -> 14221 bytes .../examples/api/pageAction/pageaction_by_url.zip | Bin 15175 -> 15215 bytes .../docs/examples/api/pageAction/set_icon.zip | Bin 8421 -> 8461 bytes .../examples/api/processes/process_monitor.zip | Bin 5226 -> 5266 bytes .../docs/examples/api/processes/show_tabs.zip | Bin 6112 -> 6152 bytes .../docs/examples/api/tabs/inspector.zip | Bin 46521 -> 46561 bytes .../docs/examples/api/tabs/screenshot.zip | Bin 6202 -> 6242 bytes .../docs/examples/api/windows/merge_windows.zip | Bin 12134 -> 12174 bytes .../docs/examples/extensions/benchmark.zip | Bin 316130 -> 258748 bytes .../docs/examples/extensions/buildbot.zip | Bin 28059 -> 28099 bytes .../docs/examples/extensions/calendar.zip | Bin 0 -> 40571 bytes .../extensions/calendar/_locales/en/messages.json | 38 + .../extensions/calendar/images/calendar_logo.gif | Bin 0 -> 3828 bytes .../extensions/calendar/images/icon-128.gif | Bin 0 -> 5232 bytes .../extensions/calendar/images/icon-16.gif | Bin 0 -> 413 bytes .../extensions/calendar/images/icon-16_bw.gif | Bin 0 -> 1019 bytes .../extensions/calendar/javascript/background.js | 728 ++++++ .../extensions/calendar/javascript/options.js | 73 + .../extensions/calendar/javascript/util.js | 14 + .../examples/extensions/calendar/manifest.json | 18 + .../extensions/calendar/views/background.html | 16 + .../extensions/calendar/views/options.html | 87 + .../docs/examples/extensions/chrome_search.zip | Bin 3885 -> 3734 bytes .../extensions/chrome_search/background.html | 10 +- .../extensions/chrome_search/manifest.json | 18 +- .../docs/examples/extensions/email_this_page.zip | Bin 11437 -> 11477 bytes .../extensions/docs/examples/extensions/fx.zip | Bin 37859 -> 37899 bytes .../extensions/docs/examples/extensions/gdocs.zip | Bin 164256 -> 164296 bytes .../extensions/docs/examples/extensions/gmail.zip | Bin 57647 -> 57687 bytes .../docs/examples/extensions/imageinfo.zip | Bin 45525 -> 46603 bytes .../extensions/docs/examples/extensions/mappy.zip | Bin 21151 -> 21191 bytes .../extensions/docs/examples/extensions/news.zip | Bin 22018 -> 65941 bytes .../extensions/news/_locales/en/messages.json | 102 + .../docs/examples/extensions/news/css/feed.css | 101 + .../docs/examples/extensions/news/css/options.css | 121 + .../docs/examples/extensions/news/feed.html | 310 --- .../docs/examples/extensions/news/images/buzz.png | Bin 0 -> 892 bytes .../extensions/news/images/delete-icon.png | Bin 0 -> 1030 bytes .../docs/examples/extensions/news/images/fb.png | Bin 0 -> 428 bytes .../docs/examples/extensions/news/images/news.gif | Bin 0 -> 3431 bytes .../extensions/news/images/news_action.png | Bin 0 -> 1109 bytes .../examples/extensions/news/images/news_icon.png | Bin 0 -> 10782 bytes .../extensions/news/images/sprite_arrows.gif | Bin 0 -> 1328 bytes .../examples/extensions/news/images/twitter.png | Bin 0 -> 588 bytes .../examples/extensions/news/javascript/feed.js | 388 +++ .../examples/extensions/news/javascript/options.js | 395 +++ .../examples/extensions/news/javascript/util.js | 29 + .../docs/examples/extensions/news/manifest.json | 19 +- .../docs/examples/extensions/news/news_action.png | Bin 1109 -> 0 bytes .../docs/examples/extensions/news/news_icon.png | Bin 10782 -> 0 bytes .../examples/extensions/news/sprite_arrows.gif | Bin 1328 -> 0 bytes .../examples/extensions/news/views/background.html | 27 + .../docs/examples/extensions/news/views/feed.html | 146 ++ .../examples/extensions/news/views/options.html | 166 ++ .../docs/examples/extensions/news_a11y.zip | Bin 25262 -> 25302 bytes .../docs/examples/extensions/news_i18n.zip | Bin 27689 -> 27729 bytes .../docs/examples/extensions/oauth_contacts.zip | Bin 71913 -> 71953 bytes .../extensions/docs/examples/extensions/wave.zip | Bin 98759 -> 98799 bytes .../docs/examples/howto/contentscript_xhr.zip | Bin 9769 -> 9809 bytes .../docs/examples/tutorials/analytics.zip | Bin 16263 -> 16303 bytes .../docs/examples/tutorials/getstarted.zip | Bin 10844 -> 10884 bytes .../extensions/docs/experimental.clipboard.html | 10 +- .../extensions/docs/experimental.contextMenus.html | 10 +- .../extensions/docs/experimental.cookies.html | 10 +- .../extensions/docs/experimental.history.html | 10 +- chrome/common/extensions/docs/experimental.html | 11 +- .../common/extensions/docs/experimental.idle.html | 10 +- .../extensions/docs/experimental.infobars.html | 10 +- .../extensions/docs/experimental.omnibox.html | 1216 +--------- .../extensions/docs/experimental.processes.html | 10 +- .../common/extensions/docs/experimental.proxy.html | 10 +- .../extensions/docs/experimental.sidebar.html | 10 +- .../docs/experimental.webNavigation.html | 10 +- .../extensions/docs/experimental.webRequest.html | 10 +- chrome/common/extensions/docs/extension.html | 141 +- .../extensions/docs/external_extensions.html | 10 +- chrome/common/extensions/docs/faq.html | 10 +- chrome/common/extensions/docs/getstarted.html | 10 +- chrome/common/extensions/docs/history.html | 10 +- chrome/common/extensions/docs/hosting.html | 10 +- chrome/common/extensions/docs/i18n-messages.html | 10 +- chrome/common/extensions/docs/i18n.html | 10 +- chrome/common/extensions/docs/idle.html | 10 +- chrome/common/extensions/docs/index.html | 10 +- chrome/common/extensions/docs/management.html | 10 +- chrome/common/extensions/docs/manifest.html | 10 +- chrome/common/extensions/docs/match_patterns.html | 10 +- chrome/common/extensions/docs/messaging.html | 10 +- chrome/common/extensions/docs/notifications.html | 10 +- chrome/common/extensions/docs/npapi.html | 10 +- chrome/common/extensions/docs/options.html | 10 +- chrome/common/extensions/docs/override.html | 10 +- chrome/common/extensions/docs/overview.html | 10 +- chrome/common/extensions/docs/packaging.html | 10 +- chrome/common/extensions/docs/pageAction.html | 10 +- .../extensions/docs/permission_warnings.html | 14 +- chrome/common/extensions/docs/samples.html | 194 +- chrome/common/extensions/docs/samples.json | 1631 +++++++------ .../extensions/docs/server/chromeextensionsdocs.py | 2 +- chrome/common/extensions/docs/tabs.html | 10 +- .../extensions/docs/template/api_template.html | 10 +- chrome/common/extensions/docs/themes.html | 10 +- chrome/common/extensions/docs/tut_analytics.html | 10 +- chrome/common/extensions/docs/tut_debugging.html | 10 +- chrome/common/extensions/docs/tut_oauth.html | 10 +- chrome/common/extensions/docs/tutorials.html | 10 +- chrome/common/extensions/docs/whats_new.html | 10 +- chrome/common/extensions/docs/windows.html | 10 +- chrome/common/extensions/docs/xhr.html | 10 +- chrome/common/extensions/extension.cc | 43 +- chrome/common/extensions/extension.h | 4 + chrome/common/extensions/extension_constants.cc | 9 +- chrome/common/extensions/extension_constants.h | 15 +- chrome/common/extensions/extension_l10n_util.cc | 4 + .../extensions/extension_l10n_util_unittest.cc | 33 +- chrome/common/extensions/extension_resource.cc | 34 +- chrome/common/extensions/extension_resource.h | 28 - chrome/common/extensions/url_pattern_unittest.cc | 30 +- chrome/common/extensions/user_script_unittest.cc | 18 +- chrome/common/gpu_info.cc | 14 +- chrome/common/gpu_info.h | 15 +- chrome/common/gpu_messages.cc | 90 +- chrome/common/gpu_messages_unittest.cc | 4 +- chrome/common/json_schema_validator.cc | 503 ++++ chrome/common/json_schema_validator.h | 211 ++ chrome/common/json_schema_validator_unittest.cc | 51 + .../common/json_schema_validator_unittest_base.cc | 628 +++++ .../common/json_schema_validator_unittest_base.h | 59 + chrome/common/metrics_helpers.cc | 90 +- chrome/common/metrics_helpers.h | 71 +- chrome/common/multi_process_lock.h | 39 + chrome/common/multi_process_lock_linux.cc | 108 + chrome/common/multi_process_lock_mac.cc | 54 + chrome/common/multi_process_lock_unittest.cc | 157 ++ chrome/common/multi_process_lock_win.cc | 58 + chrome/common/net/gaia/gaia_auth_consumer.h | 2 +- chrome/common/net/gaia/gaia_auth_fetcher.cc | 437 ++++ chrome/common/net/gaia/gaia_auth_fetcher.h | 203 ++ .../common/net/gaia/gaia_auth_fetcher_unittest.cc | 443 ++++ .../common/net/gaia/gaia_auth_fetcher_unittest.h | 84 + chrome/common/net/gaia/gaia_authenticator2.cc | 437 ---- chrome/common/net/gaia/gaia_authenticator2.h | 204 -- .../net/gaia/gaia_authenticator2_unittest.cc | 443 ---- .../common/net/gaia/gaia_authenticator2_unittest.h | 84 - chrome/common/net/test_url_fetcher_factory.cc | 77 + chrome/common/net/test_url_fetcher_factory.h | 68 +- chrome/common/net/url_fetcher_unittest.cc | 6 +- chrome/common/notification_service.h | 4 +- chrome/common/page_type.h | 17 + chrome/common/pepper_plugin_registry.cc | 29 +- chrome/common/pepper_plugin_registry.h | 17 +- chrome/common/policy_constants.cc | 12 + chrome/common/policy_constants.h | 11 + chrome/common/pref_names.cc | 45 + chrome/common/pref_names.h | 22 + chrome/common/render_messages.cc | 2 +- chrome/common/render_messages_internal.h | 26 +- chrome/common/render_messages_params.cc | 13 +- chrome/common/render_messages_params.h | 16 +- chrome/common/resource_dispatcher_unittest.cc | 8 +- chrome/common/sandbox_mac.mm | 27 +- chrome/common/sandbox_policy.cc | 84 +- chrome/common/security_style.h | 35 + chrome/common/url_constants.cc | 21 + chrome/common/url_constants.h | 9 + chrome/common/web_app_schema.json | 58 + chrome/common/web_apps.cc | 323 +++ chrome/common/web_apps.h | 109 + chrome/common/web_apps_unittest.cc | 190 ++ net/base/cert_test_util.cc | 22 +- net/base/cookie_monster.cc | 23 +- net/base/cookie_monster_unittest.cc | 28 + net/base/cookie_options.h | 4 +- net/base/ev_root_ca_metadata.cc | 2 +- net/base/net_errors.cc | 5 +- net/base/net_test_suite.h | 6 +- net/base/net_util.cc | 4 +- net/base/openssl_util.cc | 86 - net/base/openssl_util.h | 59 - net/base/ssl_config_service.cc | 3 +- net/base/ssl_config_service.h | 19 + net/base/ssl_config_service_mac.cc | 2 + net/base/ssl_config_service_win.cc | 7 + net/base/ssl_false_start_blacklist.txt | 1 + net/base/x509_certificate.cc | 4 + net/base/x509_certificate.h | 10 + net/base/x509_certificate_openssl.cc | 48 +- net/base/x509_openssl_util.cc | 111 +- net/base/x509_openssl_util.h | 10 +- net/base/x509_openssl_util_unittest.cc | 102 + net/data/cache_tests/bad_rankings3/contents.txt | 92 + net/data/cache_tests/bad_rankings3/data_0 | Bin 0 -> 45056 bytes net/data/cache_tests/bad_rankings3/data_1 | Bin 0 -> 270336 bytes net/data/cache_tests/bad_rankings3/data_2 | Bin 0 -> 8192 bytes net/data/cache_tests/bad_rankings3/data_3 | Bin 0 -> 8192 bytes net/data/cache_tests/bad_rankings3/index | Bin 0 -> 262512 bytes net/disk_cache/backend_unittest.cc | 20 + net/disk_cache/file_posix.cc | 233 +- net/disk_cache/rankings.cc | 107 +- net/disk_cache/rankings.h | 12 +- net/http/http_auth_gssapi_posix.cc | 33 +- net/http/http_auth_gssapi_posix.h | 8 +- net/http/http_auth_gssapi_posix_unittest.cc | 12 +- net/http/http_auth_handler_digest.cc | 67 +- net/http/http_auth_handler_digest.h | 76 +- net/http/http_auth_handler_digest_unittest.cc | 189 +- net/http/http_auth_handler_factory.cc | 25 +- net/http/http_auth_handler_factory.h | 8 +- net/http/http_auth_handler_negotiate.cc | 10 +- net/http/http_auth_handler_negotiate.h | 12 +- net/http/http_auth_handler_negotiate_unittest.cc | 9 +- net/http/http_auth_handler_ntlm_win.cc | 2 +- net/http/http_auth_sspi_win.cc | 65 - net/http/http_auth_sspi_win.h | 59 +- net/http/http_basic_stream.cc | 6 +- net/http/http_cache.cc | 8 - net/http/http_cache_unittest.cc | 6 +- net/http/http_net_log_params.h | 4 + net/http/http_network_layer_unittest.cc | 2 +- net/http/http_network_transaction.cc | 24 +- net/http/http_network_transaction_unittest.cc | 218 +- net/http/http_proxy_client_socket.cc | 16 +- net/http/http_proxy_client_socket.h | 3 +- net/http/http_proxy_client_socket_pool.cc | 28 +- net/http/http_proxy_client_socket_pool.h | 5 + net/http/http_proxy_client_socket_pool_unittest.cc | 4 +- net/http/http_request_headers.cc | 10 +- net/http/http_response_headers_unittest.cc | 223 +- net/http/http_response_info.cc | 16 +- net/http/http_stream_parser.cc | 14 +- net/http/http_stream_parser.h | 5 +- net/http/http_stream_request.cc | 14 +- net/http/http_stream_request.h | 4 +- net/http/http_util.cc | 4 +- net/net.gyp | 46 +- net/proxy/proxy_bypass_rules.cc | 4 +- net/proxy/proxy_config_service_linux.cc | 6 + net/proxy/proxy_script_fetcher_impl_unittest.cc | 6 + net/socket/client_socket_factory.cc | 21 +- net/socket/client_socket_factory.h | 15 +- net/socket/client_socket_pool_base_unittest.cc | 2 +- net/socket/dns_cert_provenance_check.cc | 138 +- net/socket/socket_test_util.cc | 10 +- net/socket/socket_test_util.h | 6 +- net/socket/ssl_client_socket_mac.cc | 126 +- net/socket/ssl_client_socket_mac.h | 13 +- net/socket/ssl_client_socket_mac_factory.cc | 4 +- net/socket/ssl_client_socket_mac_factory.h | 2 +- net/socket/ssl_client_socket_nss.cc | 139 +- net/socket/ssl_client_socket_nss.h | 17 +- net/socket/ssl_client_socket_nss_factory.cc | 4 +- net/socket/ssl_client_socket_nss_factory.h | 2 +- net/socket/ssl_client_socket_openssl.cc | 42 +- net/socket/ssl_client_socket_openssl.h | 4 +- net/socket/ssl_client_socket_pool.cc | 31 +- net/socket/ssl_client_socket_pool.h | 7 +- net/socket/ssl_client_socket_pool_unittest.cc | 2 +- net/socket/ssl_client_socket_snapstart_unittest.cc | 366 +++ net/socket/ssl_client_socket_unittest.cc | 222 +- net/socket/ssl_client_socket_win.cc | 11 +- net/socket/ssl_client_socket_win.h | 16 +- net/socket/ssl_error_params.cc | 24 + net/socket/ssl_error_params.h | 28 + net/socket/ssl_host_info.cc | 9 +- net/socket/ssl_host_info.h | 4 +- net/socket/tcp_client_socket_libevent.cc | 15 + net/socket/tcp_client_socket_libevent.h | 9 + net/socket/tcp_client_socket_pool_unittest.cc | 2 +- net/socket/tcp_client_socket_win.cc | 12 + net/socket/tcp_client_socket_win.h | 9 + net/socket_stream/socket_stream.cc | 7 +- net/spdy/spdy_network_transaction_unittest.cc | 45 +- net/spdy/spdy_session.cc | 57 +- net/spdy/spdy_session.h | 22 + net/test/openssl_helper.cc | 264 ++ net/test/python_utils.cc | 30 +- net/test/python_utils.h | 4 +- net/test/test_server.cc | 151 +- net/test/test_server.h | 19 +- net/test/test_server_posix.cc | 47 +- net/test/test_server_win.cc | 26 +- net/third_party/nss/ssl/ssl3con.c | 28 +- net/third_party/nss/ssl/sslplatf.c | 6 +- net/tools/flip_server/balsa_headers.cc | 17 +- net/tools/hresolv/hresolv.cc | 13 +- net/tools/testserver/chromiumsync.py | 14 + net/tools/testserver/device_management.py | 318 +++ net/tools/testserver/run_testserver.cc | 18 +- net/tools/testserver/testserver.py | 304 ++- net/url_request/url_request.cc | 11 + net/url_request/url_request.h | 4 + net/url_request/url_request_file_job.cc | 43 +- net/url_request/url_request_file_job.h | 5 +- net/url_request/url_request_job_manager.cc | 2 +- net/url_request/url_request_job_manager.h | 7 +- net/url_request/url_request_job_metrics.cc | 2 +- net/url_request/url_request_unittest.cc | 4 + net/url_request/view_cache_helper.cc | 4 +- net/websockets/websocket_net_log_params.h | 42 +- .../websocket_net_log_params_unittest.cc | 47 + testing/gtest_mac.mm | 4 +- testing/gtest_mac_unittest.mm | 10 + third_party/libjingle/source/CHANGELOG | 12 + third_party/libjingle/source/talk/base/fileutils.h | 4 + third_party/libjingle/source/talk/base/helpers.cc | 26 +- third_party/libjingle/source/talk/base/helpers.h | 6 + third_party/libjingle/source/talk/base/linux.cc | 15 +- third_party/libjingle/source/talk/base/linux.h | 5 + third_party/libjingle/source/talk/base/macutils.cc | 66 +- third_party/libjingle/source/talk/base/macutils.h | 4 + .../source/talk/examples/call/call_main.cc | 27 +- .../source/talk/examples/call/call_main.cc~ | 348 --- .../source/talk/examples/call/callclient.cc | 153 +- .../source/talk/examples/call/callclient.h | 22 +- third_party/libjingle/source/talk/main.scons | 86 +- .../libjingle/source/talk/p2p/base/constants.cc | 24 +- .../libjingle/source/talk/p2p/base/constants.h | 23 +- .../libjingle/source/talk/p2p/base/parsing.cc | 20 + .../libjingle/source/talk/p2p/base/parsing.h | 6 + .../libjingle/source/talk/p2p/base/session.cc | 142 +- .../libjingle/source/talk/p2p/base/session.h | 12 +- .../source/talk/p2p/base/sessionmessages.cc | 34 +- .../source/talk/p2p/base/sessionmessages.h | 7 + .../libjingle/source/talk/p2p/base/transport.cc | 11 +- .../libjingle/source/talk/session/phone/call.cc | 31 +- .../libjingle/source/talk/session/phone/call.h | 20 +- .../libjingle/source/talk/session/phone/channel.cc | 75 +- .../libjingle/source/talk/session/phone/channel.h | 45 +- .../source/talk/session/phone/filemediaengine.h | 8 +- .../source/talk/session/phone/mediachannel.h | 32 +- .../talk/session/phone/mediasessionclient.cc | 379 ++- .../source/talk/session/phone/mediasessionclient.h | 72 +- .../source/talk/session/phone/mediasink.h | 49 + .../libjingle/source/talk/session/phone/rtpdump.cc | 45 +- .../libjingle/source/talk/session/phone/rtpdump.h | 23 + .../source/talk/session/phone/srtpfilter.cc | 1 + .../source/talk/session/phone/srtpfilter.h | 2 + .../source/talk/session/phone/videocommon.h | 31 +- .../talk/site_scons/site_tools/talk_noops.pyc | Bin 975 -> 0 bytes .../libjingle/source/talk/site_scons/talk.py | 98 +- .../libjingle/source/talk/site_scons/talk.pyc | Bin 15030 -> 0 bytes webkit/glue/cpp_bound_class_unittest.cc | 3 +- webkit/glue/dom_operations.cc | 136 +- webkit/glue/dom_operations.h | 43 - webkit/glue/dom_operations_unittest.cc | 54 - webkit/glue/plugins/pepper_file_chooser.cc | 4 + webkit/glue/plugins/pepper_file_ref.cc | 14 +- webkit/glue/plugins/pepper_graphics_2d.cc | 5 +- webkit/glue/plugins/pepper_graphics_3d_gl.cc | 10 +- webkit/glue/plugins/pepper_plugin_instance.cc | 2 +- webkit/glue/plugins/pepper_plugin_module.cc | 82 +- webkit/glue/plugins/pepper_plugin_module.h | 28 +- webkit/glue/plugins/pepper_url_loader.cc | 38 +- webkit/glue/plugins/pepper_url_loader.h | 21 +- webkit/glue/plugins/pepper_url_request_info.cc | 10 +- webkit/glue/plugins/pepper_url_request_info.h | 8 +- webkit/glue/plugins/pepper_url_response_info.cc | 8 +- webkit/glue/plugins/pepper_url_response_info.h | 6 +- webkit/glue/plugins/plugin_host.cc | 17 + webkit/glue/plugins/plugin_lib.cc | 27 +- webkit/glue/plugins/plugin_list.cc | 10 - webkit/glue/plugins/plugin_list.h | 5 - webkit/glue/plugins/plugin_list_posix.cc | 2 +- webkit/glue/simple_webmimeregistry_impl.h | 3 + webkit/glue/user_agent.cc | 4 +- webkit/glue/webkit_glue.cc | 6 +- webkit/glue/webkit_glue.gypi | 1 + webkit/glue/webmediaplayer_impl.cc | 30 +- webkit/glue/webmediaplayer_impl.h | 5 +- webkit/glue/webpreferences.cc | 2 +- 2060 files changed, 114637 insertions(+), 91931 deletions(-) create mode 100644 base/openssl_util.cc create mode 100644 base/scoped_native_library.cc create mode 100644 base/stringize_macros.h create mode 100644 base/stringize_macros_unittest.cc create mode 100644 base/win/i18n.cc create mode 100644 base/win/i18n.h create mode 100644 base/win/i18n_unittest.cc delete mode 100644 chrome/browser/blocked_plugin_manager.cc delete mode 100644 chrome/browser/blocked_plugin_manager.h delete mode 100644 chrome/browser/browser_init.cc delete mode 100644 chrome/browser/browser_init.h delete mode 100644 chrome/browser/browser_navigator.cc delete mode 100644 chrome/browser/browser_navigator.h delete mode 100644 chrome/browser/chromeos/cros_settings_provider_proxy.cc delete mode 100644 chrome/browser/chromeos/cros_settings_provider_proxy.h delete mode 100644 chrome/browser/chromeos/cros_settings_provider_stats.cc delete mode 100644 chrome/browser/chromeos/cros_settings_provider_stats.h delete mode 100644 chrome/browser/chromeos/cros_settings_provider_user.cc delete mode 100644 chrome/browser/chromeos/cros_settings_provider_user.h delete mode 100644 chrome/browser/chromeos/dom_ui/labs_handler.cc delete mode 100644 chrome/browser/chromeos/dom_ui/labs_handler.h create mode 100644 chrome/browser/chromeos/input_method/candidate_window.h create mode 100644 chrome/browser/chromeos/input_method/candidate_window_main.cc create mode 100644 chrome/browser/chromeos/login/user_controller_unittest.cc create mode 100644 chrome/browser/chromeos/metrics_cros_settings_provider.cc create mode 100644 chrome/browser/chromeos/metrics_cros_settings_provider.h create mode 100644 chrome/browser/chromeos/proxy_cros_settings_provider.cc create mode 100644 chrome/browser/chromeos/proxy_cros_settings_provider.h create mode 100644 chrome/browser/chromeos/user_cros_settings_provider.cc create mode 100644 chrome/browser/chromeos/user_cros_settings_provider.h create mode 100644 chrome/browser/chromeos/views/copy_background.cc create mode 100644 chrome/browser/chromeos/views/copy_background.h create mode 100644 chrome/browser/chromeos/views/dropdown_button.cc create mode 100644 chrome/browser/chromeos/views/dropdown_button.h create mode 100644 chrome/browser/extensions/convert_web_app.cc create mode 100644 chrome/browser/extensions/convert_web_app.h create mode 100644 chrome/browser/extensions/convert_web_app_unittest.cc create mode 100644 chrome/browser/extensions/extension_module.cc create mode 100644 chrome/browser/extensions/extension_module.h create mode 100644 chrome/browser/extensions/extension_module_apitest.cc create mode 100644 chrome/browser/extensions/extension_omnibox_unittest.cc create mode 100644 chrome/browser/file_system/browser_file_system_context.cc create mode 100644 chrome/browser/file_system/browser_file_system_context.h delete mode 100644 chrome/browser/file_system/file_system_host_context.cc delete mode 100644 chrome/browser/file_system/file_system_host_context.h create mode 100644 chrome/browser/gtk/chrome_gtk_frame.cc create mode 100644 chrome/browser/gtk/chrome_gtk_frame.h delete mode 100644 chrome/browser/gtk/meta_frames.cc delete mode 100644 chrome/browser/gtk/meta_frames.h delete mode 100644 chrome/browser/instant/instant_opt_in.cc delete mode 100644 chrome/browser/instant/instant_opt_in.h create mode 100644 chrome/browser/instant/promo_counter.cc create mode 100644 chrome/browser/instant/promo_counter.h create mode 100644 chrome/browser/instant/promo_counter_unittest.cc create mode 100644 chrome/browser/mime_registry_dispatcher.cc create mode 100644 chrome/browser/mime_registry_dispatcher.h create mode 100644 chrome/browser/plugin_service_browsertest.cc create mode 100644 chrome/browser/plugin_service_unittest.cc create mode 100644 chrome/browser/policy/device_management_policy_provider.cc create mode 100644 chrome/browser/policy/device_management_policy_provider.h create mode 100644 chrome/browser/policy/device_management_policy_provider_unittest.cc create mode 100644 chrome/browser/policy/mock_configuration_policy_store.cc create mode 100644 chrome/browser/policy/proto/device_management_local.proto create mode 100644 chrome/browser/policy/proto/device_management_proto.gyp create mode 100644 chrome/browser/ppapi_plugin_process_host.cc create mode 100644 chrome/browser/ppapi_plugin_process_host.h create mode 100644 chrome/browser/printing/print_preview_tab_controller.cc create mode 100644 chrome/browser/printing/print_preview_tab_controller.h create mode 100644 chrome/browser/printing/print_preview_tab_controller_unittest.cc create mode 100644 chrome/browser/resources/guest_session_tab.html create mode 100644 chrome/browser/resources/incognito_tab.css delete mode 100644 chrome/browser/resources/options/chromeos_labs.html create mode 100644 chrome/browser/resources/shared/images/guest_icon_standalone.png create mode 100644 chrome/browser/safe_browsing/client_side_detection_service.cc create mode 100644 chrome/browser/safe_browsing/client_side_detection_service.h create mode 100644 chrome/browser/safe_browsing/client_side_detection_service_unittest.cc create mode 100644 chrome/browser/safe_browsing/csd.proto delete mode 100644 chrome/browser/tab_contents/security_style.h create mode 100755 chrome/browser/ui/views/PRESUBMIT.py create mode 100644 chrome/browser/ui/views/about_chrome_view.cc create mode 100644 chrome/browser/ui/views/about_chrome_view.h create mode 100644 chrome/browser/ui/views/about_ipc_dialog.cc create mode 100644 chrome/browser/ui/views/about_ipc_dialog.h create mode 100644 chrome/browser/ui/views/accelerator_table_gtk.cc create mode 100644 chrome/browser/ui/views/accelerator_table_gtk.h create mode 100644 chrome/browser/ui/views/accessibility_event_router_views.cc create mode 100644 chrome/browser/ui/views/accessibility_event_router_views.h create mode 100644 chrome/browser/ui/views/accessibility_event_router_views_unittest.cc create mode 100644 chrome/browser/ui/views/accessible_pane_view.cc create mode 100644 chrome/browser/ui/views/accessible_pane_view.h create mode 100644 chrome/browser/ui/views/accessible_view_helper.cc create mode 100644 chrome/browser/ui/views/accessible_view_helper.h create mode 100644 chrome/browser/ui/views/app_launched_animation_win.cc create mode 100644 chrome/browser/ui/views/appcache_info_view.cc create mode 100644 chrome/browser/ui/views/appcache_info_view.h create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.cc create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.cc create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_gtk.h create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_win.cc create mode 100644 chrome/browser/ui/views/autocomplete/autocomplete_popup_win.h create mode 100644 chrome/browser/ui/views/autofill_profiles_view_win.cc create mode 100644 chrome/browser/ui/views/autofill_profiles_view_win.h create mode 100644 chrome/browser/ui/views/bookmark_bar_instructions_view.cc create mode 100644 chrome/browser/ui/views/bookmark_bar_instructions_view.h create mode 100644 chrome/browser/ui/views/bookmark_bar_view.cc create mode 100644 chrome/browser/ui/views/bookmark_bar_view.h create mode 100644 chrome/browser/ui/views/bookmark_bar_view_test.cc create mode 100644 chrome/browser/ui/views/bookmark_bar_view_unittest.cc create mode 100644 chrome/browser/ui/views/bookmark_bubble_view.cc create mode 100644 chrome/browser/ui/views/bookmark_bubble_view.h create mode 100644 chrome/browser/ui/views/bookmark_context_menu.cc create mode 100644 chrome/browser/ui/views/bookmark_context_menu.h create mode 100644 chrome/browser/ui/views/bookmark_context_menu_controller_views.cc create mode 100644 chrome/browser/ui/views/bookmark_context_menu_controller_views.h create mode 100644 chrome/browser/ui/views/bookmark_context_menu_test.cc create mode 100644 chrome/browser/ui/views/bookmark_editor_view.cc create mode 100644 chrome/browser/ui/views/bookmark_editor_view.h create mode 100644 chrome/browser/ui/views/bookmark_editor_view_unittest.cc create mode 100644 chrome/browser/ui/views/bookmark_menu_controller_views.cc create mode 100644 chrome/browser/ui/views/bookmark_menu_controller_views.h create mode 100644 chrome/browser/ui/views/browser_actions_container.cc create mode 100644 chrome/browser/ui/views/browser_actions_container.h create mode 100644 chrome/browser/ui/views/browser_actions_container_browsertest.cc create mode 100644 chrome/browser/ui/views/browser_bubble.cc create mode 100644 chrome/browser/ui/views/browser_bubble.h create mode 100644 chrome/browser/ui/views/browser_bubble_gtk.cc create mode 100644 chrome/browser/ui/views/browser_bubble_win.cc create mode 100644 chrome/browser/ui/views/browser_dialogs.h create mode 100644 chrome/browser/ui/views/browser_keyboard_accessibility_test_win.cc create mode 100644 chrome/browser/ui/views/bubble_border.cc create mode 100644 chrome/browser/ui/views/bubble_border.h create mode 100644 chrome/browser/ui/views/certificate_viewer_win.cc create mode 100644 chrome/browser/ui/views/chrome_views_delegate.cc create mode 100644 chrome/browser/ui/views/chrome_views_delegate.h create mode 100644 chrome/browser/ui/views/clear_browsing_data.cc create mode 100644 chrome/browser/ui/views/clear_browsing_data.h create mode 100644 chrome/browser/ui/views/clear_browsing_data_view.cc create mode 100644 chrome/browser/ui/views/clear_browsing_data_view.h create mode 100644 chrome/browser/ui/views/clear_data_view.cc create mode 100644 chrome/browser/ui/views/clear_data_view.h create mode 100644 chrome/browser/ui/views/clear_server_data.cc create mode 100644 chrome/browser/ui/views/clear_server_data.h create mode 100644 chrome/browser/ui/views/collected_cookies_win.cc create mode 100644 chrome/browser/ui/views/collected_cookies_win.h create mode 100644 chrome/browser/ui/views/confirm_message_box_dialog.cc create mode 100644 chrome/browser/ui/views/confirm_message_box_dialog.h create mode 100644 chrome/browser/ui/views/constrained_html_delegate_gtk.cc create mode 100644 chrome/browser/ui/views/constrained_html_delegate_win.cc create mode 100644 chrome/browser/ui/views/constrained_window_win.cc create mode 100644 chrome/browser/ui/views/constrained_window_win.h create mode 100644 chrome/browser/ui/views/content_setting_bubble_contents.cc create mode 100644 chrome/browser/ui/views/content_setting_bubble_contents.h create mode 100644 chrome/browser/ui/views/cookie_info_view.cc create mode 100644 chrome/browser/ui/views/cookie_info_view.h create mode 100644 chrome/browser/ui/views/create_application_shortcut_view.cc create mode 100644 chrome/browser/ui/views/create_application_shortcut_view.h create mode 100644 chrome/browser/ui/views/database_info_view.cc create mode 100644 chrome/browser/ui/views/database_info_view.h create mode 100644 chrome/browser/ui/views/database_open_info_view.cc create mode 100644 chrome/browser/ui/views/database_open_info_view.h create mode 100644 chrome/browser/ui/views/default_search_view.cc create mode 100644 chrome/browser/ui/views/default_search_view.h create mode 100644 chrome/browser/ui/views/detachable_toolbar_view.cc create mode 100644 chrome/browser/ui/views/detachable_toolbar_view.h create mode 100644 chrome/browser/ui/views/dialog_stubs_gtk.cc create mode 100644 chrome/browser/ui/views/dom_view.cc create mode 100644 chrome/browser/ui/views/dom_view.h create mode 100644 chrome/browser/ui/views/dom_view_browsertest.cc create mode 100644 chrome/browser/ui/views/download_item_view.cc create mode 100644 chrome/browser/ui/views/download_item_view.h create mode 100644 chrome/browser/ui/views/download_shelf_view.cc create mode 100644 chrome/browser/ui/views/download_shelf_view.h create mode 100644 chrome/browser/ui/views/download_started_animation_win.cc create mode 100644 chrome/browser/ui/views/dropdown_bar_host.cc create mode 100644 chrome/browser/ui/views/dropdown_bar_host.h create mode 100644 chrome/browser/ui/views/dropdown_bar_host_gtk.cc create mode 100644 chrome/browser/ui/views/dropdown_bar_host_win.cc create mode 100644 chrome/browser/ui/views/dropdown_bar_view.h create mode 100644 chrome/browser/ui/views/edit_search_engine_dialog.cc create mode 100644 chrome/browser/ui/views/edit_search_engine_dialog.h create mode 100644 chrome/browser/ui/views/event_utils.cc create mode 100644 chrome/browser/ui/views/event_utils.h create mode 100644 chrome/browser/ui/views/extensions/browser_action_drag_data.cc create mode 100644 chrome/browser/ui/views/extensions/browser_action_drag_data.h create mode 100644 chrome/browser/ui/views/extensions/browser_action_drag_data_unittest.cc create mode 100644 chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.cc create mode 100644 chrome/browser/ui/views/extensions/browser_action_overflow_menu_controller.h create mode 100644 chrome/browser/ui/views/extensions/extension_install_prompt.cc create mode 100644 chrome/browser/ui/views/extensions/extension_install_prompt2.cc create mode 100644 chrome/browser/ui/views/extensions/extension_installed_bubble.cc create mode 100644 chrome/browser/ui/views/extensions/extension_installed_bubble.h create mode 100644 chrome/browser/ui/views/extensions/extension_popup.cc create mode 100644 chrome/browser/ui/views/extensions/extension_popup.h create mode 100644 chrome/browser/ui/views/extensions/extension_view.cc create mode 100644 chrome/browser/ui/views/extensions/extension_view.h create mode 100644 chrome/browser/ui/views/external_protocol_dialog.cc create mode 100644 chrome/browser/ui/views/external_protocol_dialog.h create mode 100644 chrome/browser/ui/views/find_bar_host.cc create mode 100644 chrome/browser/ui/views/find_bar_host.h create mode 100644 chrome/browser/ui/views/find_bar_host_gtk.cc create mode 100644 chrome/browser/ui/views/find_bar_host_interactive_uitest.cc create mode 100644 chrome/browser/ui/views/find_bar_host_uitest.cc create mode 100644 chrome/browser/ui/views/find_bar_host_win.cc create mode 100644 chrome/browser/ui/views/find_bar_view.cc create mode 100644 chrome/browser/ui/views/find_bar_view.h create mode 100644 chrome/browser/ui/views/first_run_bubble.cc create mode 100644 chrome/browser/ui/views/first_run_bubble.h create mode 100644 chrome/browser/ui/views/first_run_search_engine_view.cc create mode 100644 chrome/browser/ui/views/first_run_search_engine_view.h create mode 100644 chrome/browser/ui/views/frame/app_panel_browser_frame_view.cc create mode 100644 chrome/browser/ui/views/frame/app_panel_browser_frame_view.h create mode 100644 chrome/browser/ui/views/frame/browser_bubble_host.cc create mode 100644 chrome/browser/ui/views/frame/browser_bubble_host.h create mode 100644 chrome/browser/ui/views/frame/browser_frame.h create mode 100644 chrome/browser/ui/views/frame/browser_frame_gtk.cc create mode 100644 chrome/browser/ui/views/frame/browser_frame_gtk.h create mode 100644 chrome/browser/ui/views/frame/browser_frame_win.cc create mode 100644 chrome/browser/ui/views/frame/browser_frame_win.h create mode 100644 chrome/browser/ui/views/frame/browser_non_client_frame_view.h create mode 100644 chrome/browser/ui/views/frame/browser_root_view.cc create mode 100644 chrome/browser/ui/views/frame/browser_root_view.h create mode 100644 chrome/browser/ui/views/frame/browser_view.cc create mode 100644 chrome/browser/ui/views/frame/browser_view.h create mode 100644 chrome/browser/ui/views/frame/browser_view_layout.cc create mode 100644 chrome/browser/ui/views/frame/browser_view_layout.h create mode 100644 chrome/browser/ui/views/frame/contents_container.cc create mode 100644 chrome/browser/ui/views/frame/contents_container.h create mode 100644 chrome/browser/ui/views/frame/glass_browser_frame_view.cc create mode 100644 chrome/browser/ui/views/frame/glass_browser_frame_view.h create mode 100644 chrome/browser/ui/views/frame/opaque_browser_frame_view.cc create mode 100644 chrome/browser/ui/views/frame/opaque_browser_frame_view.h create mode 100644 chrome/browser/ui/views/frame/popup_non_client_frame_view.cc create mode 100644 chrome/browser/ui/views/frame/popup_non_client_frame_view.h create mode 100644 chrome/browser/ui/views/fullscreen_exit_bubble.cc create mode 100644 chrome/browser/ui/views/fullscreen_exit_bubble.h create mode 100644 chrome/browser/ui/views/generic_info_view.cc create mode 100644 chrome/browser/ui/views/generic_info_view.h create mode 100644 chrome/browser/ui/views/generic_info_view_unittest.cc create mode 100644 chrome/browser/ui/views/html_dialog_view.cc create mode 100644 chrome/browser/ui/views/html_dialog_view.h create mode 100644 chrome/browser/ui/views/html_dialog_view_browsertest.cc create mode 100644 chrome/browser/ui/views/hung_renderer_view.cc create mode 100644 chrome/browser/ui/views/importer_lock_view.cc create mode 100644 chrome/browser/ui/views/importer_lock_view.h create mode 100644 chrome/browser/ui/views/importer_view.cc create mode 100644 chrome/browser/ui/views/importer_view.h create mode 100644 chrome/browser/ui/views/importing_progress_view.cc create mode 100644 chrome/browser/ui/views/importing_progress_view.h create mode 100644 chrome/browser/ui/views/indexed_db_info_view.cc create mode 100644 chrome/browser/ui/views/indexed_db_info_view.h create mode 100644 chrome/browser/ui/views/info_bubble.cc create mode 100644 chrome/browser/ui/views/info_bubble.h create mode 100644 chrome/browser/ui/views/info_bubble_unittest.cc create mode 100644 chrome/browser/ui/views/infobars/after_translate_infobar.cc create mode 100644 chrome/browser/ui/views/infobars/after_translate_infobar.h create mode 100644 chrome/browser/ui/views/infobars/before_translate_infobar.cc create mode 100644 chrome/browser/ui/views/infobars/before_translate_infobar.h create mode 100644 chrome/browser/ui/views/infobars/extension_infobar.cc create mode 100644 chrome/browser/ui/views/infobars/extension_infobar.h create mode 100644 chrome/browser/ui/views/infobars/infobar_button_border.cc create mode 100644 chrome/browser/ui/views/infobars/infobar_button_border.h create mode 100644 chrome/browser/ui/views/infobars/infobar_container.cc create mode 100644 chrome/browser/ui/views/infobars/infobar_container.h create mode 100644 chrome/browser/ui/views/infobars/infobar_text_button.cc create mode 100644 chrome/browser/ui/views/infobars/infobar_text_button.h create mode 100644 chrome/browser/ui/views/infobars/infobars.cc create mode 100644 chrome/browser/ui/views/infobars/infobars.h create mode 100644 chrome/browser/ui/views/infobars/translate_infobar_base.cc create mode 100644 chrome/browser/ui/views/infobars/translate_infobar_base.h create mode 100644 chrome/browser/ui/views/infobars/translate_message_infobar.cc create mode 100644 chrome/browser/ui/views/infobars/translate_message_infobar.h create mode 100644 chrome/browser/ui/views/instant_confirm_view.cc create mode 100644 chrome/browser/ui/views/instant_confirm_view.h create mode 100644 chrome/browser/ui/views/js_modal_dialog_views.cc create mode 100644 chrome/browser/ui/views/js_modal_dialog_views.h create mode 100644 chrome/browser/ui/views/keyword_editor_view.cc create mode 100644 chrome/browser/ui/views/keyword_editor_view.h create mode 100644 chrome/browser/ui/views/list_background.h create mode 100644 chrome/browser/ui/views/local_storage_info_view.cc create mode 100644 chrome/browser/ui/views/local_storage_info_view.h create mode 100644 chrome/browser/ui/views/local_storage_set_item_info_view.cc create mode 100644 chrome/browser/ui/views/local_storage_set_item_info_view.h create mode 100644 chrome/browser/ui/views/location_bar/click_handler.cc create mode 100644 chrome/browser/ui/views/location_bar/click_handler.h create mode 100644 chrome/browser/ui/views/location_bar/content_setting_image_view.cc create mode 100644 chrome/browser/ui/views/location_bar/content_setting_image_view.h create mode 100644 chrome/browser/ui/views/location_bar/ev_bubble_view.cc create mode 100644 chrome/browser/ui/views/location_bar/ev_bubble_view.h create mode 100644 chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc create mode 100644 chrome/browser/ui/views/location_bar/icon_label_bubble_view.h create mode 100644 chrome/browser/ui/views/location_bar/keyword_hint_view.cc create mode 100644 chrome/browser/ui/views/location_bar/keyword_hint_view.h create mode 100644 chrome/browser/ui/views/location_bar/location_bar_view.cc create mode 100644 chrome/browser/ui/views/location_bar/location_bar_view.h create mode 100644 chrome/browser/ui/views/location_bar/location_icon_view.cc create mode 100644 chrome/browser/ui/views/location_bar/location_icon_view.h create mode 100644 chrome/browser/ui/views/location_bar/page_action_image_view.cc create mode 100644 chrome/browser/ui/views/location_bar/page_action_image_view.h create mode 100644 chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc create mode 100644 chrome/browser/ui/views/location_bar/page_action_with_badge_view.h create mode 100644 chrome/browser/ui/views/location_bar/selected_keyword_view.cc create mode 100644 chrome/browser/ui/views/location_bar/selected_keyword_view.h create mode 100644 chrome/browser/ui/views/location_bar/star_view.cc create mode 100644 chrome/browser/ui/views/location_bar/star_view.h create mode 100644 chrome/browser/ui/views/location_bar/suggested_text_view.cc create mode 100644 chrome/browser/ui/views/location_bar/suggested_text_view.h create mode 100644 chrome/browser/ui/views/login_view.cc create mode 100644 chrome/browser/ui/views/login_view.h create mode 100644 chrome/browser/ui/views/modal_dialog_delegate.cc create mode 100644 chrome/browser/ui/views/modal_dialog_delegate.h create mode 100644 chrome/browser/ui/views/notifications/balloon_view.cc create mode 100644 chrome/browser/ui/views/notifications/balloon_view.h create mode 100644 chrome/browser/ui/views/notifications/balloon_view_host.cc create mode 100644 chrome/browser/ui/views/notifications/balloon_view_host.h create mode 100644 chrome/browser/ui/views/options/advanced_contents_view.cc create mode 100644 chrome/browser/ui/views/options/advanced_contents_view.h create mode 100644 chrome/browser/ui/views/options/advanced_page_view.cc create mode 100644 chrome/browser/ui/views/options/advanced_page_view.h create mode 100644 chrome/browser/ui/views/options/content_exceptions_table_view.cc create mode 100644 chrome/browser/ui/views/options/content_exceptions_table_view.h create mode 100644 chrome/browser/ui/views/options/content_filter_page_view.cc create mode 100644 chrome/browser/ui/views/options/content_filter_page_view.h create mode 100644 chrome/browser/ui/views/options/content_page_view.cc create mode 100644 chrome/browser/ui/views/options/content_page_view.h create mode 100644 chrome/browser/ui/views/options/content_settings_window_view.cc create mode 100644 chrome/browser/ui/views/options/content_settings_window_view.h create mode 100644 chrome/browser/ui/views/options/cookie_filter_page_view.cc create mode 100644 chrome/browser/ui/views/options/cookie_filter_page_view.h create mode 100644 chrome/browser/ui/views/options/cookies_view.cc create mode 100644 chrome/browser/ui/views/options/cookies_view.h create mode 100644 chrome/browser/ui/views/options/exception_editor_view.cc create mode 100644 chrome/browser/ui/views/options/exception_editor_view.h create mode 100644 chrome/browser/ui/views/options/exceptions_page_view.cc create mode 100644 chrome/browser/ui/views/options/exceptions_page_view.h create mode 100644 chrome/browser/ui/views/options/exceptions_view.cc create mode 100644 chrome/browser/ui/views/options/exceptions_view.h create mode 100644 chrome/browser/ui/views/options/fonts_languages_window_view.cc create mode 100644 chrome/browser/ui/views/options/fonts_languages_window_view.h create mode 100644 chrome/browser/ui/views/options/fonts_page_view.cc create mode 100644 chrome/browser/ui/views/options/fonts_page_view.h create mode 100644 chrome/browser/ui/views/options/general_page_view.cc create mode 100644 chrome/browser/ui/views/options/general_page_view.h create mode 100644 chrome/browser/ui/views/options/languages_page_view.cc create mode 100644 chrome/browser/ui/views/options/languages_page_view.h create mode 100644 chrome/browser/ui/views/options/managed_prefs_banner_view.cc create mode 100644 chrome/browser/ui/views/options/managed_prefs_banner_view.h create mode 100644 chrome/browser/ui/views/options/options_group_view.cc create mode 100644 chrome/browser/ui/views/options/options_group_view.h create mode 100644 chrome/browser/ui/views/options/options_page_view.cc create mode 100644 chrome/browser/ui/views/options/options_page_view.h create mode 100644 chrome/browser/ui/views/options/options_window_view.cc create mode 100644 chrome/browser/ui/views/options/passwords_exceptions_window_view.cc create mode 100644 chrome/browser/ui/views/options/passwords_exceptions_window_view.h create mode 100644 chrome/browser/ui/views/options/passwords_page_view.cc create mode 100644 chrome/browser/ui/views/options/passwords_page_view.h create mode 100644 chrome/browser/ui/views/options/plugin_filter_page_view.cc create mode 100644 chrome/browser/ui/views/options/plugin_filter_page_view.h create mode 100644 chrome/browser/ui/views/options/simple_content_exceptions_view.cc create mode 100644 chrome/browser/ui/views/options/simple_content_exceptions_view.h create mode 100644 chrome/browser/ui/views/page_info_bubble_view.cc create mode 100644 chrome/browser/ui/views/page_info_bubble_view.h create mode 100644 chrome/browser/ui/views/pinned_contents_info_bubble.cc create mode 100644 chrome/browser/ui/views/pinned_contents_info_bubble.h create mode 100644 chrome/browser/ui/views/reload_button.cc create mode 100644 chrome/browser/ui/views/reload_button.h create mode 100644 chrome/browser/ui/views/reload_button_unittest.cc create mode 100644 chrome/browser/ui/views/repost_form_warning_view.cc create mode 100644 chrome/browser/ui/views/repost_form_warning_view.h create mode 100644 chrome/browser/ui/views/restart_message_box.cc create mode 100644 chrome/browser/ui/views/restart_message_box.h create mode 100644 chrome/browser/ui/views/sad_tab_view.cc create mode 100644 chrome/browser/ui/views/sad_tab_view.h create mode 100644 chrome/browser/ui/views/select_file_dialog.cc create mode 100644 chrome/browser/ui/views/shell_dialogs_win.cc create mode 100644 chrome/browser/ui/views/shell_dialogs_win_unittest.cc create mode 100644 chrome/browser/ui/views/ssl_client_certificate_selector_win.cc create mode 100644 chrome/browser/ui/views/status_bubble_views.cc create mode 100644 chrome/browser/ui/views/status_bubble_views.h create mode 100644 chrome/browser/ui/views/status_icons/status_icon_win.cc create mode 100644 chrome/browser/ui/views/status_icons/status_icon_win.h create mode 100644 chrome/browser/ui/views/status_icons/status_tray_gtk.cc create mode 100644 chrome/browser/ui/views/status_icons/status_tray_win.cc create mode 100644 chrome/browser/ui/views/status_icons/status_tray_win.h create mode 100644 chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc create mode 100644 chrome/browser/ui/views/tab_contents/native_tab_contents_container.h create mode 100644 chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.cc create mode 100644 chrome/browser/ui/views/tab_contents/native_tab_contents_container_gtk.h create mode 100644 chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.cc create mode 100644 chrome/browser/ui/views/tab_contents/native_tab_contents_container_win.h create mode 100644 chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc create mode 100644 chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_container.cc create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_container.h create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_drag_win.cc create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_drag_win.h create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_view_win.cc create mode 100644 chrome/browser/ui/views/tab_contents/tab_contents_view_win.h create mode 100644 chrome/browser/ui/views/tab_icon_view.cc create mode 100644 chrome/browser/ui/views/tab_icon_view.h create mode 100644 chrome/browser/ui/views/tabs/base_tab.cc create mode 100644 chrome/browser/ui/views/tabs/base_tab.h create mode 100644 chrome/browser/ui/views/tabs/base_tab_strip.cc create mode 100644 chrome/browser/ui/views/tabs/base_tab_strip.h create mode 100644 chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc create mode 100644 chrome/browser/ui/views/tabs/browser_tab_strip_controller.h create mode 100644 chrome/browser/ui/views/tabs/dragged_tab_controller.cc create mode 100644 chrome/browser/ui/views/tabs/dragged_tab_controller.h create mode 100644 chrome/browser/ui/views/tabs/dragged_tab_view.cc create mode 100644 chrome/browser/ui/views/tabs/dragged_tab_view.h create mode 100644 chrome/browser/ui/views/tabs/native_view_photobooth.h create mode 100644 chrome/browser/ui/views/tabs/native_view_photobooth_gtk.cc create mode 100644 chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h create mode 100644 chrome/browser/ui/views/tabs/native_view_photobooth_win.cc create mode 100644 chrome/browser/ui/views/tabs/native_view_photobooth_win.h create mode 100644 chrome/browser/ui/views/tabs/side_tab.cc create mode 100644 chrome/browser/ui/views/tabs/side_tab.h create mode 100644 chrome/browser/ui/views/tabs/side_tab_strip.cc create mode 100644 chrome/browser/ui/views/tabs/side_tab_strip.h create mode 100644 chrome/browser/ui/views/tabs/tab.cc create mode 100644 chrome/browser/ui/views/tabs/tab.h create mode 100644 chrome/browser/ui/views/tabs/tab_controller.h create mode 100644 chrome/browser/ui/views/tabs/tab_dragging_test.cc create mode 100644 chrome/browser/ui/views/tabs/tab_renderer_data.h create mode 100644 chrome/browser/ui/views/tabs/tab_strip.cc create mode 100644 chrome/browser/ui/views/tabs/tab_strip.h create mode 100644 chrome/browser/ui/views/tabs/tab_strip_controller.h create mode 100644 chrome/browser/ui/views/task_manager_view.cc create mode 100644 chrome/browser/ui/views/textfield_views.cc create mode 100644 chrome/browser/ui/views/textfield_views.h create mode 100644 chrome/browser/ui/views/theme_background.cc create mode 100644 chrome/browser/ui/views/theme_background.h create mode 100644 chrome/browser/ui/views/theme_helpers.cc create mode 100644 chrome/browser/ui/views/theme_helpers.h create mode 100644 chrome/browser/ui/views/theme_install_bubble_view.cc create mode 100644 chrome/browser/ui/views/theme_install_bubble_view.h create mode 100644 chrome/browser/ui/views/toolbar_view.cc create mode 100644 chrome/browser/ui/views/toolbar_view.h create mode 100644 chrome/browser/ui/views/unhandled_keyboard_event_handler.cc create mode 100644 chrome/browser/ui/views/unhandled_keyboard_event_handler.h create mode 100644 chrome/browser/ui/views/uninstall_view.cc create mode 100644 chrome/browser/ui/views/uninstall_view.h create mode 100644 chrome/browser/ui/views/update_recommended_message_box.cc create mode 100644 chrome/browser/ui/views/update_recommended_message_box.h create mode 100644 chrome/browser/ui/views/url_picker.cc create mode 100644 chrome/browser/ui/views/url_picker.h create mode 100644 chrome/browser/ui/views/user_data_dir_dialog.cc create mode 100644 chrome/browser/ui/views/user_data_dir_dialog.h create mode 100644 chrome/browser/ui/views/window.cc create mode 100644 chrome/browser/ui/views/window.h create mode 100644 chrome/browser/ui/views/wrench_menu.cc create mode 100644 chrome/browser/ui/views/wrench_menu.h delete mode 100755 chrome/browser/views/PRESUBMIT.py delete mode 100644 chrome/browser/views/about_chrome_view.cc delete mode 100644 chrome/browser/views/about_ipc_dialog.cc delete mode 100644 chrome/browser/views/accelerator_table_gtk.cc delete mode 100644 chrome/browser/views/accessibility_event_router_views.cc delete mode 100644 chrome/browser/views/accessibility_event_router_views_unittest.cc delete mode 100644 chrome/browser/views/accessible_pane_view.cc delete mode 100644 chrome/browser/views/accessible_view_helper.cc delete mode 100644 chrome/browser/views/app_launched_animation_win.cc delete mode 100644 chrome/browser/views/appcache_info_view.cc delete mode 100644 chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc delete mode 100644 chrome/browser/views/autocomplete/autocomplete_popup_gtk.cc delete mode 100644 chrome/browser/views/autocomplete/autocomplete_popup_win.cc delete mode 100644 chrome/browser/views/autofill_profiles_view_win.cc delete mode 100644 chrome/browser/views/bookmark_bar_instructions_view.cc delete mode 100644 chrome/browser/views/bookmark_bar_view.cc delete mode 100644 chrome/browser/views/bookmark_bar_view_test.cc delete mode 100644 chrome/browser/views/bookmark_bar_view_unittest.cc delete mode 100644 chrome/browser/views/bookmark_bubble_view.cc delete mode 100644 chrome/browser/views/bookmark_context_menu.cc delete mode 100644 chrome/browser/views/bookmark_context_menu_controller_views.cc delete mode 100644 chrome/browser/views/bookmark_context_menu_test.cc delete mode 100644 chrome/browser/views/bookmark_editor_view.cc delete mode 100644 chrome/browser/views/bookmark_editor_view_unittest.cc create mode 100644 chrome/browser/views/bookmark_editor_viw.h delete mode 100644 chrome/browser/views/bookmark_menu_controller_views.cc delete mode 100644 chrome/browser/views/browser_actions_container.cc delete mode 100644 chrome/browser/views/browser_actions_container_browsertest.cc delete mode 100644 chrome/browser/views/browser_bubble.cc delete mode 100644 chrome/browser/views/browser_bubble_gtk.cc delete mode 100644 chrome/browser/views/browser_bubble_win.cc delete mode 100644 chrome/browser/views/browser_keyboard_accessibility_test_win.cc delete mode 100644 chrome/browser/views/bubble_border.cc delete mode 100644 chrome/browser/views/certificate_viewer_win.cc delete mode 100644 chrome/browser/views/chrome_views_delegate.cc delete mode 100644 chrome/browser/views/clear_browsing_data.cc delete mode 100644 chrome/browser/views/clear_browsing_data_view.cc delete mode 100644 chrome/browser/views/clear_data_view.cc delete mode 100644 chrome/browser/views/clear_server_data.cc delete mode 100644 chrome/browser/views/collected_cookies_win.cc delete mode 100644 chrome/browser/views/confirm_message_box_dialog.cc delete mode 100644 chrome/browser/views/constrained_html_delegate_win.cc delete mode 100644 chrome/browser/views/constrained_window_win.cc delete mode 100644 chrome/browser/views/content_setting_bubble_contents.cc delete mode 100644 chrome/browser/views/cookie_info_view.cc delete mode 100644 chrome/browser/views/create_application_shortcut_view.cc delete mode 100644 chrome/browser/views/database_info_view.cc delete mode 100644 chrome/browser/views/database_open_info_view.cc delete mode 100644 chrome/browser/views/default_search_view.cc delete mode 100644 chrome/browser/views/detachable_toolbar_view.cc delete mode 100644 chrome/browser/views/dialog_stubs_gtk.cc delete mode 100644 chrome/browser/views/dom_view.cc delete mode 100644 chrome/browser/views/dom_view_browsertest.cc delete mode 100644 chrome/browser/views/download_item_view.cc delete mode 100644 chrome/browser/views/download_shelf_view.cc delete mode 100644 chrome/browser/views/download_started_animation_win.cc delete mode 100644 chrome/browser/views/dropdown_bar_host.cc delete mode 100644 chrome/browser/views/dropdown_bar_host_gtk.cc delete mode 100644 chrome/browser/views/dropdown_bar_host_win.cc delete mode 100644 chrome/browser/views/edit_search_engine_dialog.cc delete mode 100644 chrome/browser/views/event_utils.cc delete mode 100644 chrome/browser/views/extensions/browser_action_drag_data.cc delete mode 100644 chrome/browser/views/extensions/browser_action_drag_data_unittest.cc delete mode 100644 chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc delete mode 100644 chrome/browser/views/extensions/extension_install_prompt.cc delete mode 100644 chrome/browser/views/extensions/extension_install_prompt2.cc delete mode 100644 chrome/browser/views/extensions/extension_installed_bubble.cc delete mode 100644 chrome/browser/views/extensions/extension_popup.cc delete mode 100644 chrome/browser/views/extensions/extension_view.cc delete mode 100644 chrome/browser/views/external_protocol_dialog.cc delete mode 100644 chrome/browser/views/find_bar_host.cc delete mode 100644 chrome/browser/views/find_bar_host_gtk.cc delete mode 100644 chrome/browser/views/find_bar_host_interactive_uitest.cc delete mode 100644 chrome/browser/views/find_bar_host_uitest.cc delete mode 100644 chrome/browser/views/find_bar_host_win.cc delete mode 100644 chrome/browser/views/find_bar_view.cc delete mode 100644 chrome/browser/views/first_run_bubble.cc delete mode 100644 chrome/browser/views/first_run_search_engine_view.cc delete mode 100644 chrome/browser/views/frame/app_panel_browser_frame_view.cc delete mode 100644 chrome/browser/views/frame/browser_bubble_host.cc delete mode 100644 chrome/browser/views/frame/browser_frame_gtk.cc delete mode 100644 chrome/browser/views/frame/browser_frame_win.cc delete mode 100644 chrome/browser/views/frame/browser_root_view.cc delete mode 100644 chrome/browser/views/frame/browser_view.cc delete mode 100644 chrome/browser/views/frame/browser_view_layout.cc delete mode 100644 chrome/browser/views/frame/contents_container.cc delete mode 100644 chrome/browser/views/frame/glass_browser_frame_view.cc delete mode 100644 chrome/browser/views/frame/opaque_browser_frame_view.cc delete mode 100644 chrome/browser/views/frame/popup_non_client_frame_view.cc delete mode 100644 chrome/browser/views/fullscreen_exit_bubble.cc delete mode 100644 chrome/browser/views/generic_info_view.cc delete mode 100644 chrome/browser/views/generic_info_view_unittest.cc delete mode 100644 chrome/browser/views/html_dialog_view.cc delete mode 100644 chrome/browser/views/html_dialog_view_browsertest.cc delete mode 100644 chrome/browser/views/hung_renderer_view.cc delete mode 100644 chrome/browser/views/importer_lock_view.cc delete mode 100644 chrome/browser/views/importer_view.cc delete mode 100644 chrome/browser/views/importing_progress_view.cc delete mode 100644 chrome/browser/views/indexed_db_info_view.cc delete mode 100644 chrome/browser/views/info_bubble.cc delete mode 100644 chrome/browser/views/info_bubble_unittest.cc delete mode 100644 chrome/browser/views/infobars/after_translate_infobar.cc delete mode 100644 chrome/browser/views/infobars/before_translate_infobar.cc delete mode 100644 chrome/browser/views/infobars/extension_infobar.cc delete mode 100644 chrome/browser/views/infobars/infobar_button_border.cc delete mode 100644 chrome/browser/views/infobars/infobar_container.cc delete mode 100644 chrome/browser/views/infobars/infobar_text_button.cc delete mode 100644 chrome/browser/views/infobars/infobars.cc delete mode 100644 chrome/browser/views/infobars/translate_infobar_base.cc delete mode 100644 chrome/browser/views/infobars/translate_message_infobar.cc delete mode 100644 chrome/browser/views/instant_confirm_view.cc delete mode 100644 chrome/browser/views/js_modal_dialog_views.cc delete mode 100644 chrome/browser/views/keyword_editor_view.cc delete mode 100644 chrome/browser/views/local_storage_info_view.cc delete mode 100644 chrome/browser/views/local_storage_set_item_info_view.cc delete mode 100644 chrome/browser/views/location_bar/click_handler.cc delete mode 100644 chrome/browser/views/location_bar/content_setting_image_view.cc delete mode 100644 chrome/browser/views/location_bar/ev_bubble_view.cc delete mode 100644 chrome/browser/views/location_bar/icon_label_bubble_view.cc delete mode 100644 chrome/browser/views/location_bar/keyword_hint_view.cc delete mode 100644 chrome/browser/views/location_bar/location_bar_view.cc delete mode 100644 chrome/browser/views/location_bar/location_icon_view.cc delete mode 100644 chrome/browser/views/location_bar/page_action_image_view.cc delete mode 100644 chrome/browser/views/location_bar/page_action_with_badge_view.cc delete mode 100644 chrome/browser/views/location_bar/selected_keyword_view.cc delete mode 100644 chrome/browser/views/location_bar/star_view.cc delete mode 100644 chrome/browser/views/login_view.cc delete mode 100644 chrome/browser/views/modal_dialog_delegate.cc delete mode 100644 chrome/browser/views/notifications/balloon_view.cc delete mode 100644 chrome/browser/views/notifications/balloon_view_host.cc delete mode 100644 chrome/browser/views/options/advanced_contents_view.cc delete mode 100644 chrome/browser/views/options/advanced_page_view.cc delete mode 100644 chrome/browser/views/options/content_exceptions_table_view.cc delete mode 100644 chrome/browser/views/options/content_filter_page_view.cc delete mode 100644 chrome/browser/views/options/content_page_view.cc delete mode 100644 chrome/browser/views/options/content_settings_window_view.cc delete mode 100644 chrome/browser/views/options/cookie_filter_page_view.cc delete mode 100644 chrome/browser/views/options/cookies_view.cc delete mode 100644 chrome/browser/views/options/exception_editor_view.cc delete mode 100644 chrome/browser/views/options/exceptions_page_view.cc delete mode 100644 chrome/browser/views/options/exceptions_view.cc delete mode 100644 chrome/browser/views/options/fonts_languages_window_view.cc delete mode 100644 chrome/browser/views/options/fonts_page_view.cc delete mode 100644 chrome/browser/views/options/general_page_view.cc delete mode 100644 chrome/browser/views/options/languages_page_view.cc delete mode 100644 chrome/browser/views/options/managed_prefs_banner_view.cc delete mode 100644 chrome/browser/views/options/options_group_view.cc delete mode 100644 chrome/browser/views/options/options_page_view.cc delete mode 100644 chrome/browser/views/options/options_window_view.cc delete mode 100644 chrome/browser/views/options/passwords_exceptions_window_view.cc delete mode 100644 chrome/browser/views/options/passwords_page_view.cc delete mode 100644 chrome/browser/views/options/plugin_filter_page_view.cc delete mode 100644 chrome/browser/views/options/simple_content_exceptions_view.cc delete mode 100644 chrome/browser/views/page_info_bubble_view.cc delete mode 100644 chrome/browser/views/pinned_contents_info_bubble.cc delete mode 100644 chrome/browser/views/reload_button.cc delete mode 100644 chrome/browser/views/reload_button_unittest.cc delete mode 100644 chrome/browser/views/repost_form_warning_view.cc delete mode 100644 chrome/browser/views/restart_message_box.cc delete mode 100644 chrome/browser/views/sad_tab_view.cc delete mode 100644 chrome/browser/views/select_file_dialog.cc delete mode 100644 chrome/browser/views/shell_dialogs_win.cc delete mode 100644 chrome/browser/views/shell_dialogs_win_unittest.cc delete mode 100644 chrome/browser/views/ssl_client_certificate_selector_win.cc delete mode 100644 chrome/browser/views/status_bubble_views.cc delete mode 100644 chrome/browser/views/status_icons/status_icon_win.cc delete mode 100644 chrome/browser/views/status_icons/status_tray_gtk.cc delete mode 100644 chrome/browser/views/status_icons/status_tray_win.cc delete mode 100644 chrome/browser/views/status_icons/status_tray_win_unittest.cc delete mode 100644 chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc delete mode 100644 chrome/browser/views/tab_contents/native_tab_contents_container_win.cc delete mode 100644 chrome/browser/views/tab_contents/render_view_context_menu_views.cc delete mode 100644 chrome/browser/views/tab_contents/tab_contents_container.cc delete mode 100644 chrome/browser/views/tab_contents/tab_contents_drag_win.cc delete mode 100644 chrome/browser/views/tab_contents/tab_contents_view_gtk.cc delete mode 100644 chrome/browser/views/tab_contents/tab_contents_view_win.cc delete mode 100644 chrome/browser/views/tab_icon_view.cc delete mode 100644 chrome/browser/views/tabs/base_tab.cc delete mode 100644 chrome/browser/views/tabs/base_tab_strip.cc delete mode 100644 chrome/browser/views/tabs/browser_tab_strip_controller.cc delete mode 100644 chrome/browser/views/tabs/dragged_tab_controller.cc delete mode 100644 chrome/browser/views/tabs/dragged_tab_view.cc delete mode 100644 chrome/browser/views/tabs/native_view_photobooth_gtk.cc delete mode 100644 chrome/browser/views/tabs/native_view_photobooth_win.cc delete mode 100644 chrome/browser/views/tabs/side_tab.cc delete mode 100644 chrome/browser/views/tabs/side_tab_strip.cc delete mode 100644 chrome/browser/views/tabs/tab.cc delete mode 100644 chrome/browser/views/tabs/tab_dragging_test.cc delete mode 100644 chrome/browser/views/tabs/tab_strip.cc delete mode 100644 chrome/browser/views/task_manager_view.cc delete mode 100644 chrome/browser/views/textfield_views.cc delete mode 100644 chrome/browser/views/theme_background.cc delete mode 100644 chrome/browser/views/theme_helpers.cc delete mode 100644 chrome/browser/views/theme_install_bubble_view.cc delete mode 100644 chrome/browser/views/toolbar_view.cc delete mode 100644 chrome/browser/views/unhandled_keyboard_event_handler.cc delete mode 100644 chrome/browser/views/uninstall_view.cc delete mode 100644 chrome/browser/views/update_recommended_message_box.cc delete mode 100644 chrome/browser/views/url_picker.cc delete mode 100644 chrome/browser/views/user_data_dir_dialog.cc delete mode 100644 chrome/browser/views/window.cc delete mode 100644 chrome/browser/views/wrench_menu.cc create mode 100644 chrome/common/automation_messages.cc create mode 100644 chrome/common/automation_messages.h create mode 100644 chrome/common/automation_messages_internal.h create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar.zip create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/_locales/en/messages.json create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/images/calendar_logo.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/images/icon-128.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/images/icon-16.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/images/icon-16_bw.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/javascript/background.js create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/javascript/options.js create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/javascript/util.js create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/manifest.json create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/views/background.html create mode 100644 chrome/common/extensions/docs/examples/extensions/calendar/views/options.html create mode 100644 chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json create mode 100644 chrome/common/extensions/docs/examples/extensions/news/css/feed.css create mode 100644 chrome/common/extensions/docs/examples/extensions/news/css/options.css delete mode 100644 chrome/common/extensions/docs/examples/extensions/news/feed.html create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/buzz.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/fb.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/news.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/news_action.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/news/images/twitter.png create mode 100644 chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js create mode 100644 chrome/common/extensions/docs/examples/extensions/news/javascript/options.js create mode 100644 chrome/common/extensions/docs/examples/extensions/news/javascript/util.js delete mode 100644 chrome/common/extensions/docs/examples/extensions/news/news_action.png delete mode 100644 chrome/common/extensions/docs/examples/extensions/news/news_icon.png delete mode 100644 chrome/common/extensions/docs/examples/extensions/news/sprite_arrows.gif create mode 100644 chrome/common/extensions/docs/examples/extensions/news/views/background.html create mode 100644 chrome/common/extensions/docs/examples/extensions/news/views/feed.html create mode 100644 chrome/common/extensions/docs/examples/extensions/news/views/options.html create mode 100644 chrome/common/json_schema_validator.cc create mode 100644 chrome/common/json_schema_validator.h create mode 100644 chrome/common/json_schema_validator_unittest.cc create mode 100644 chrome/common/json_schema_validator_unittest_base.cc create mode 100644 chrome/common/json_schema_validator_unittest_base.h create mode 100644 chrome/common/multi_process_lock.h create mode 100644 chrome/common/multi_process_lock_linux.cc create mode 100644 chrome/common/multi_process_lock_mac.cc create mode 100644 chrome/common/multi_process_lock_unittest.cc create mode 100644 chrome/common/multi_process_lock_win.cc create mode 100644 chrome/common/net/gaia/gaia_auth_fetcher.cc create mode 100644 chrome/common/net/gaia/gaia_auth_fetcher.h create mode 100644 chrome/common/net/gaia/gaia_auth_fetcher_unittest.cc create mode 100644 chrome/common/net/gaia/gaia_auth_fetcher_unittest.h delete mode 100644 chrome/common/net/gaia/gaia_authenticator2.cc delete mode 100644 chrome/common/net/gaia/gaia_authenticator2.h delete mode 100644 chrome/common/net/gaia/gaia_authenticator2_unittest.cc delete mode 100644 chrome/common/net/gaia/gaia_authenticator2_unittest.h create mode 100644 chrome/common/page_type.h create mode 100644 chrome/common/security_style.h create mode 100644 chrome/common/web_app_schema.json create mode 100644 chrome/common/web_apps.cc create mode 100644 chrome/common/web_apps.h create mode 100644 chrome/common/web_apps_unittest.cc delete mode 100644 net/base/openssl_util.cc delete mode 100644 net/base/openssl_util.h create mode 100644 net/base/x509_openssl_util_unittest.cc create mode 100644 net/data/cache_tests/bad_rankings3/contents.txt create mode 100644 net/data/cache_tests/bad_rankings3/data_0 create mode 100644 net/data/cache_tests/bad_rankings3/data_1 create mode 100644 net/data/cache_tests/bad_rankings3/data_2 create mode 100644 net/data/cache_tests/bad_rankings3/data_3 create mode 100644 net/data/cache_tests/bad_rankings3/index create mode 100644 net/socket/ssl_client_socket_snapstart_unittest.cc create mode 100644 net/socket/ssl_error_params.cc create mode 100644 net/socket/ssl_error_params.h create mode 100644 net/test/openssl_helper.cc create mode 100644 net/tools/testserver/device_management.py create mode 100644 net/websockets/websocket_net_log_params_unittest.cc delete mode 100644 third_party/libjingle/source/talk/examples/call/call_main.cc~ create mode 100644 third_party/libjingle/source/talk/session/phone/mediasink.h delete mode 100644 third_party/libjingle/source/talk/site_scons/site_tools/talk_noops.pyc delete mode 100644 third_party/libjingle/source/talk/site_scons/talk.pyc diff --git a/AUTHORS b/AUTHORS index 0bbe166..25e8ab1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -86,3 +86,6 @@ Shreyas VA Steven Pennington Jorge Villatoro Paul Nettleship +David Benjamin +Sevan Janiyan +Peter Beverloo diff --git a/base/base.gyp b/base/base.gyp index 6ae1a95..f68359a 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -129,11 +129,13 @@ 'simple_thread_unittest.cc', 'singleton_unittest.cc', 'stack_container_unittest.cc', + 'string16_unittest.cc', 'string_number_conversions_unittest.cc', 'string_piece_unittest.cc', 'string_split_unittest.cc', 'string_tokenizer_unittest.cc', 'string_util_unittest.cc', + 'stringize_macros_unittest.cc', 'stringprintf_unittest.cc', 'sys_info_unittest.cc', 'sys_string_conversions_mac_unittest.mm', @@ -163,6 +165,7 @@ 'win/event_trace_consumer_unittest.cc', 'win/event_trace_controller_unittest.cc', 'win/event_trace_provider_unittest.cc', + 'win/i18n_unittest.cc', 'win/pe_image_unittest.cc', 'win/registry_unittest.cc', 'win/scoped_bstr_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 78c97aa..8b876bd 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -121,6 +121,7 @@ 'mac_util.h', 'mac_util.mm', 'mac/scoped_aedesc.h', + 'mac/scoped_cftyperef.h', 'mac/scoped_nsautorelease_pool.h', 'mac/scoped_nsautorelease_pool.mm', 'mach_ipc_mac.h', @@ -142,7 +143,7 @@ 'metrics/histogram.cc', 'metrics/histogram.h', 'metrics/nacl_histogram.cc', - 'metrics/nacl_histogram.h', + 'metrics/nacl_histogram.h', 'metrics/stats_counters.cc', 'metrics/stats_counters.h', 'metrics/stats_table.cc', @@ -196,8 +197,9 @@ 'safe_strerror_posix.cc', 'safe_strerror_posix.h', 'scoped_callback_factory.h', - 'mac/scoped_cftyperef.h', 'scoped_handle.h', + 'scoped_native_library.cc', + 'scoped_native_library.h', 'scoped_nsobject.h', 'scoped_open_process.h', 'scoped_ptr.h', @@ -226,6 +228,7 @@ 'string_util.cc', 'string_util.h', 'string_util_win.h', + 'stringize_macros.h', 'stringprintf.cc', 'stringprintf.h', 'sys_info.h', @@ -278,6 +281,8 @@ 'utf_string_conversions.h', 'values.cc', 'values.h', + 'version.cc', + 'version.h', 'vlog.cc', 'vlog.h', 'waitable_event.h', @@ -290,6 +295,8 @@ 'watchdog.h', 'weak_ptr.cc', 'weak_ptr.h', + 'win/i18n.cc', + 'win/i18n.h', 'win/pe_image.cc', 'win/event_trace_consumer.h', 'win/event_trace_controller.cc', @@ -474,6 +481,8 @@ 'nsimage_cache_mac.mm', 'nss_util.cc', 'nss_util.h', + 'openssl_util.cc', + 'openssl_util.h', 'setproctitle_linux.c', 'setproctitle_linux.h', 'sha2.cc', @@ -486,8 +495,6 @@ 'sync_socket_posix.cc', 'time_mac.cc', 'time_posix.cc', - 'version.cc', - 'version.h', ], 'conditions': [ [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { @@ -563,6 +570,8 @@ 'crypto/signature_verifier_openssl.cc', 'crypto/symmetric_key_openssl.cc', 'hmac_openssl.cc', + 'openssl_util.cc', + 'openssl_util.h', 'sha2_openssl.cc', ], },], diff --git a/base/base_paths_mac.mm b/base/base_paths_mac.mm index 793bece..b9225d8 100644 --- a/base/base_paths_mac.mm +++ b/base/base_paths_mac.mm @@ -4,7 +4,7 @@ #include "base/base_paths_mac.h" -#import +#import #include #include "base/compiler_specific.h" @@ -52,7 +52,8 @@ bool PathProviderMac(int key, FilePath* result) { case base::DIR_APP_DATA: return mac_util::GetUserDirectory(NSApplicationSupportDirectory, result); case base::DIR_SOURCE_ROOT: { - if (GetNSExecutablePath(result)) { + // Go through PathService to catch overrides. + if (PathService::Get(base::FILE_EXE, result)) { // Start with the executable's directory. *result = result->DirName(); if (mac_util::AmIBundled()) { diff --git a/base/command_line.cc b/base/command_line.cc index 2e6021d..b335e7c 100644 --- a/base/command_line.cc +++ b/base/command_line.cc @@ -224,7 +224,7 @@ void CommandLine::Init(int argc, const char* const* argv) { #endif } -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL) // static void CommandLine::SetProcTitle() { // Build a single string which consists of all the arguments separated @@ -431,7 +431,14 @@ void CommandLine::AppendArguments(const CommandLine& other, // Verify include_program is used correctly. // Logic could be shorter but this is clearer. DCHECK_EQ(include_program, !other.GetProgram().empty()); - command_line_string_ += L" " + other.command_line_string_; + if (include_program) + program_ = other.program_; + + if (!command_line_string_.empty()) + command_line_string_ += L' '; + + command_line_string_ += other.command_line_string_; + std::map::const_iterator i; for (i = other.switches_.begin(); i != other.switches_.end(); ++i) switches_[i->first] = i->second; @@ -482,9 +489,15 @@ void CommandLine::AppendArguments(const CommandLine& other, // Verify include_program is used correctly. // Logic could be shorter but this is clearer. DCHECK_EQ(include_program, !other.GetProgram().empty()); - size_t first_arg = include_program ? 0 : 1; - for (size_t i = first_arg; i < other.argv_.size(); ++i) + + if (include_program) + argv_[0] = other.argv_[0]; + + // Skip the first arg when copying since it's the program but push all + // arguments to our arg vector. + for (size_t i = 1; i < other.argv_.size(); ++i) argv_.push_back(other.argv_[i]); + std::map::const_iterator i; for (i = other.switches_.begin(); i != other.switches_.end(); ++i) switches_[i->first] = i->second; diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc index 9184aa3..5c525ae 100644 --- a/base/command_line_unittest.cc +++ b/base/command_line_unittest.cc @@ -5,8 +5,8 @@ #include #include -#include "base/command_line.h" #include "base/basictypes.h" +#include "base/command_line.h" #include "base/file_path.h" #include "base/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -154,3 +154,28 @@ TEST(CommandLineTest, AppendSwitches) { cl.command_line_string()); #endif } + +// Tests that when AppendArguments is called that the program is set correctly +// on the target CommandLine object and the switches from the source +// CommandLine are added to the target. +TEST(CommandLineTest, AppendArguments) { + CommandLine cl1(FilePath(FILE_PATH_LITERAL("Program"))); + cl1.AppendSwitch("switch1"); + cl1.AppendSwitchASCII("switch2", "foo"); + + CommandLine cl2(CommandLine::NO_PROGRAM); + cl2.AppendArguments(cl1, true); + EXPECT_EQ(cl1.GetProgram().value(), cl2.GetProgram().value()); + EXPECT_EQ(cl1.command_line_string(), cl2.command_line_string()); + + CommandLine c1(FilePath(FILE_PATH_LITERAL("Program1"))); + c1.AppendSwitch("switch1"); + CommandLine c2(FilePath(FILE_PATH_LITERAL("Program2"))); + c2.AppendSwitch("switch2"); + + c1.AppendArguments(c2, true); + EXPECT_EQ(c1.GetProgram().value(), c2.GetProgram().value()); + EXPECT_TRUE(c1.HasSwitch("switch1")); + EXPECT_TRUE(c1.HasSwitch("switch2")); +} + diff --git a/base/crypto/encryptor.h b/base/crypto/encryptor.h index f1d6f28..7718240 100644 --- a/base/crypto/encryptor.h +++ b/base/crypto/encryptor.h @@ -44,7 +44,12 @@ class Encryptor { SymmetricKey* key_; Mode mode_; -#if defined(USE_NSS) +#if defined(USE_OPENSSL) + bool Crypt(bool encrypt, // Pass true to encrypt, false to decrypt. + const std::string& input, + std::string* output); + std::string iv_; +#elif defined(USE_NSS) ScopedPK11Slot slot_; ScopedSECItem param_; #elif defined(OS_MACOSX) diff --git a/base/crypto/encryptor_nss.cc b/base/crypto/encryptor_nss.cc index ef77d9d..737e8f2 100644 --- a/base/crypto/encryptor_nss.cc +++ b/base/crypto/encryptor_nss.cc @@ -48,9 +48,6 @@ bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { } bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - if (plaintext.size() == 0) - return false; - ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, CKA_ENCRYPT, key_->key(), diff --git a/base/crypto/encryptor_openssl.cc b/base/crypto/encryptor_openssl.cc index 71a84be..44ae932 100644 --- a/base/crypto/encryptor_openssl.cc +++ b/base/crypto/encryptor_openssl.cc @@ -4,29 +4,123 @@ #include "base/crypto/encryptor.h" +#include +#include + +#include "base/crypto/symmetric_key.h" #include "base/logging.h" +#include "base/openssl_util.h" +#include "base/string_util.h" namespace base { -Encryptor::Encryptor() { +namespace { + +const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { + switch (key->key().length()) { + case 16: return EVP_aes_128_cbc(); + case 24: return EVP_aes_192_cbc(); + case 32: return EVP_aes_256_cbc(); + default: return NULL; + } +} + +// On destruction this class will cleanup the ctx, and also clear the OpenSSL +// ERR stack as a convenience. +class ScopedCipherCTX { + public: + explicit ScopedCipherCTX() { + EVP_CIPHER_CTX_init(&ctx_); + } + ~ScopedCipherCTX() { + EVP_CIPHER_CTX_cleanup(&ctx_); + ClearOpenSSLERRStack(); + } + EVP_CIPHER_CTX* get() { return &ctx_; } + + private: + EVP_CIPHER_CTX ctx_; +}; + +} // namespace + +Encryptor::Encryptor() + : key_(NULL) { } Encryptor::~Encryptor() { } bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { - NOTIMPLEMENTED(); - return false; + DCHECK(key); + DCHECK_EQ(CBC, mode); + + EnsureOpenSSLInit(); + if (iv.size() != AES_BLOCK_SIZE) + return false; + + if (GetCipherForKey(key) == NULL) + return false; + + key_ = key; + mode_ = mode; + iv_ = iv; + return true; } bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { - NOTIMPLEMENTED(); - return false; + return Crypt(true, plaintext, ciphertext); } bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { - NOTIMPLEMENTED(); - return false; + return Crypt(false, ciphertext, plaintext); +} + +bool Encryptor::Crypt(bool do_encrypt, + const std::string& input, + std::string* output) { + DCHECK(key_); // Must call Init() before En/De-crypt. + // Work on the result in a local variable, and then only transfer it to + // |output| on success to ensure no partial data is returned. + std::string result; + output->swap(result); + + const EVP_CIPHER* cipher = GetCipherForKey(key_); + DCHECK(cipher); // Already handled in Init(); + + const std::string& key = key_->key(); + DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast(iv_.length())); + DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast(key.length())); + + ScopedCipherCTX ctx; + if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, + reinterpret_cast(key.data()), + reinterpret_cast(iv_.data()), + do_encrypt)) + return false; + + // When encrypting, add another block size of space to allow for any padding. + const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0); + uint8* out_ptr = reinterpret_cast(WriteInto(&result, + output_size + 1)); + int out_len; + if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len, + reinterpret_cast(input.data()), + input.length())) + return false; + + // Write out the final block plus padding (if any) to the end of the data + // just written. + int tail_len; + if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len)) + return false; + + out_len += tail_len; + DCHECK_LE(out_len, static_cast(output_size)); + result.resize(out_len); + + output->swap(result); + return true; } } // namespace base diff --git a/base/crypto/encryptor_unittest.cc b/base/crypto/encryptor_unittest.cc index bc66e55..e8d055b 100644 --- a/base/crypto/encryptor_unittest.cc +++ b/base/crypto/encryptor_unittest.cc @@ -8,6 +8,7 @@ #include "base/crypto/symmetric_key.h" #include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" #include "testing/gtest/include/gtest/gtest.h" TEST(EncryptorTest, EncryptDecrypt) { @@ -108,3 +109,124 @@ TEST(EncryptorTest, EncryptAES256CBC) { EXPECT_EQ(plaintext, decypted); } + +// Expected output derived from the NSS implementation. +TEST(EncryptorTest, EncryptAES128CBCRegression) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + std::string plaintext = "Plain text with a g-clef U+1D11E \360\235\204\236"; + std::string expected_ciphertext_hex = + "D4A67A0BA33C30F207344D81D1E944BBE65587C3D7D9939A" + "C070C62B9C15A3EA312EA4AD1BC7929F4D3C16B03AD5ADA8"; + + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); + + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), + ciphertext.size())); + + std::string decypted; + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); + EXPECT_EQ(plaintext, decypted); +} + +// Expected output derived from the NSS implementation. +TEST(EncryptorTest, EncryptAES192CBCRegression) { + std::string key = "192bitsIsTwentyFourByte!"; + std::string iv = "Sweet Sixteen IV"; + std::string plaintext = "Small text"; + std::string expected_ciphertext_hex = "78DE5D7C2714FC5C61346C5416F6C89A"; + + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); + + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), + ciphertext.size())); + + std::string decypted; + EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decypted)); + EXPECT_EQ(plaintext, decypted); +} + +// Not all platforms allow import/generation of symmetric keys with an +// unsupported size. +#if !defined(OS_WIN) && !defined(USE_NSS) +TEST(EncryptorTest, UnsupportedKeySize) { + std::string key = "7 = bad"; + std::string iv = "Sweet Sixteen IV"; + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_FALSE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); +} +#endif // unsupported platforms. + +TEST(EncryptorTest, UnsupportedIV) { + std::string key = "128=SixteenBytes"; + std::string iv = "OnlyForteen :("; + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + EXPECT_FALSE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); +} + +TEST(EncryptorTest, EmptyEncrypt) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + std::string plaintext; + std::string expected_ciphertext_hex = "8518B8878D34E7185E300D0FCC426396"; + + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); + + std::string ciphertext; + EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); + EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), + ciphertext.size())); +} + +TEST(EncryptorTest, EmptyDecrypt) { + std::string key = "128=SixteenBytes"; + std::string iv = "Sweet Sixteen IV"; + + scoped_ptr sym_key(base::SymmetricKey::Import( + base::SymmetricKey::AES, key)); + ASSERT_TRUE(NULL != sym_key.get()); + + base::Encryptor encryptor; + // The IV must be exactly as long a the cipher block size. + EXPECT_EQ(16U, iv.size()); + EXPECT_TRUE(encryptor.Init(sym_key.get(), base::Encryptor::CBC, iv)); + + std::string decrypted; + EXPECT_FALSE(encryptor.Decrypt("", &decrypted)); + EXPECT_EQ("", decrypted); +} diff --git a/base/crypto/encryptor_win.cc b/base/crypto/encryptor_win.cc index fe1f5a8..4a137b3 100644 --- a/base/crypto/encryptor_win.cc +++ b/base/crypto/encryptor_win.cc @@ -93,6 +93,8 @@ bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { DWORD data_len = ciphertext.size(); + if (data_len == 0) + return false; std::vector tmp(data_len); memcpy(&tmp[0], ciphertext.data(), data_len); diff --git a/base/crypto/rsa_private_key.h b/base/crypto/rsa_private_key.h index 4492c3d..ea5daac 100644 --- a/base/crypto/rsa_private_key.h +++ b/base/crypto/rsa_private_key.h @@ -8,7 +8,10 @@ #include "build/build_config.h" -#if defined(USE_NSS) +#if defined(USE_OPENSSL) +// Forward declaration for openssl/*.h +typedef struct evp_pkey_st EVP_PKEY; +#elif defined(USE_NSS) // Forward declaration. struct SECKEYPrivateKeyStr; struct SECKEYPublicKeyStr; @@ -216,7 +219,7 @@ class RSAPrivateKey { // Exports the public key to an X509 SubjectPublicKeyInfo block. bool ExportPublicKey(std::vector* output); -private: + private: #if defined(USE_NSS) FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FindFromPublicKey); FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); @@ -238,7 +241,9 @@ private: static RSAPrivateKey* CreateFromPrivateKeyInfoWithParams( const std::vector& input, bool permanent, bool sensitive); -#if defined(USE_NSS) +#if defined(USE_OPENSSL) + EVP_PKEY* key_; +#elif defined(USE_NSS) SECKEYPrivateKeyStr* key_; SECKEYPublicKeyStr* public_key_; #elif defined(OS_WIN) diff --git a/base/crypto/rsa_private_key_openssl.cc b/base/crypto/rsa_private_key_openssl.cc index ec1d8b5..e14965f 100644 --- a/base/crypto/rsa_private_key_openssl.cc +++ b/base/crypto/rsa_private_key_openssl.cc @@ -4,35 +4,69 @@ #include "base/crypto/rsa_private_key.h" +#include +#include +#include + #include "base/logging.h" +#include "base/openssl_util.h" +#include "base/scoped_ptr.h" +#include "base/stl_util-inl.h" namespace base { -// static -RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, - bool permanent, - bool sensitive) { - NOTIMPLEMENTED(); - return NULL; +namespace { + +// Function pointer definition, for injecting the required key export function +// into ExportKey, below. The supplied function should export EVP_PKEY into +// the supplied BIO, returning 1 on success or 0 on failure. +typedef int (ExportFunction)(BIO*, EVP_PKEY*); + +// Helper to export |key| into |output| via the specified ExportFunction. +bool ExportKey(EVP_PKEY* key, + ExportFunction export_fn, + std::vector* output) { + if (!key) + return false; + + ScopedOpenSSL bio(BIO_new(BIO_s_mem())); + + int res = export_fn(bio.get(), key); + ClearOpenSSLERRStack(); + if (!res) + return false; + + char* data = NULL; + long len = BIO_get_mem_data(bio.get(), &data); + if (!data || len < 0) + return false; + + STLAssignToVector(output, reinterpret_cast(data), len); + return true; } +} // namespace + // static RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - return CreateWithParams(num_bits, - false /* not permanent */, - false /* not sensitive */); -} + EnsureOpenSSLInit(); -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { - return CreateWithParams(num_bits, - true /* permanent */, - true /* sensitive */); + ScopedOpenSSL rsa_key(RSA_generate_key(num_bits, 65537L, + NULL, NULL)); + ClearOpenSSLERRStack(); + if (!rsa_key.get()) + return NULL; + + scoped_ptr result(new RSAPrivateKey); + result->key_ = EVP_PKEY_new(); + if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) + return NULL; + + return result.release(); } // static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( - const std::vector& input, bool permanent, bool sensitive) { +RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { NOTIMPLEMENTED(); return NULL; } @@ -40,17 +74,37 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( // static RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( const std::vector& input) { - return CreateFromPrivateKeyInfoWithParams(input, - false /* not permanent */, - false /* not sensitive */); + EnsureOpenSSLInit(); + + // BIO_new_mem_buf is not const aware, but it does not modify the buffer. + char* data = reinterpret_cast(const_cast(input.data())); + ScopedOpenSSL bio(BIO_new_mem_buf(data, input.size())); + if (!bio.get()) + return NULL; + + // Importing is a little more involved than exporting, as we must first + // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key + // Info structure returned. + ScopedOpenSSL p8inf( + d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); + ClearOpenSSLERRStack(); + if (!p8inf.get()) + return NULL; + + scoped_ptr result(new RSAPrivateKey); + result->key_ = EVP_PKCS82PKEY(p8inf.get()); + ClearOpenSSLERRStack(); + if (!result->key_) + return NULL; + + return result.release(); } // static RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( const std::vector& input) { - return CreateFromPrivateKeyInfoWithParams(input, - true /* permanent */, - true /* seneitive */); + NOTIMPLEMENTED(); + return NULL; } // static @@ -60,20 +114,21 @@ RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( return NULL; } -RSAPrivateKey::RSAPrivateKey() { +RSAPrivateKey::RSAPrivateKey() + : key_(NULL) { } RSAPrivateKey::~RSAPrivateKey() { + if (key_) + EVP_PKEY_free(key_); } bool RSAPrivateKey::ExportPrivateKey(std::vector* output) { - NOTIMPLEMENTED(); - return false; + return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); } bool RSAPrivateKey::ExportPublicKey(std::vector* output) { - NOTIMPLEMENTED(); - return false; + return ExportKey(key_, i2d_PUBKEY_bio, output); } } // namespace base diff --git a/base/crypto/symmetric_key.h b/base/crypto/symmetric_key.h index 3f2be76..6ad0646 100644 --- a/base/crypto/symmetric_key.h +++ b/base/crypto/symmetric_key.h @@ -24,6 +24,8 @@ namespace base { // scoped_ptr. class SymmetricKey { public: + // Defines the algorithm that a key will be used with. See also + // classs Encrptor. enum Algorithm { AES, HMAC_SHA1, @@ -31,14 +33,16 @@ class SymmetricKey { virtual ~SymmetricKey(); - // Generates a random key suitable to be used with |cipher| and of + // Generates a random key suitable to be used with |algorithm| and of // |key_size_in_bits| bits. // The caller is responsible for deleting the returned SymmetricKey. static SymmetricKey* GenerateRandomKey(Algorithm algorithm, size_t key_size_in_bits); - // Derives a key from the supplied password and salt using PBKDF2. The caller - // is responsible for deleting the returned SymmetricKey. + // Derives a key from the supplied password and salt using PBKDF2, suitable + // for use with specified |algorithm|. Note |algorithm| is not the algorithm + // used to derive the key from the password. The caller is responsible for + // deleting the returned SymmetricKey. static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm, const std::string& password, const std::string& salt, @@ -51,7 +55,9 @@ class SymmetricKey { // SymmetricKey. static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); -#if defined(USE_NSS) +#if defined(USE_OPENSSL) + const std::string& key() { return key_; } +#elif defined(USE_NSS) PK11SymKey* key() const { return key_.get(); } #elif defined(OS_MACOSX) CSSM_DATA cssm_data() const; @@ -66,8 +72,8 @@ class SymmetricKey { private: #if defined(USE_OPENSSL) - // TODO(joth): Add a constructor that accepts OpenSSL symmetric key data, and - // the appropriate data members to store it in. + SymmetricKey() {} + std::string key_; #elif defined(USE_NSS) explicit SymmetricKey(PK11SymKey* key); ScopedPK11SymKey key_; diff --git a/base/crypto/symmetric_key_openssl.cc b/base/crypto/symmetric_key_openssl.cc index 591252d..9f0ad38 100644 --- a/base/crypto/symmetric_key_openssl.cc +++ b/base/crypto/symmetric_key_openssl.cc @@ -4,18 +4,44 @@ #include "base/crypto/symmetric_key.h" +#include +#include + +#include + #include "base/logging.h" +#include "base/openssl_util.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" namespace base { SymmetricKey::~SymmetricKey() { + std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key. } // static SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, size_t key_size_in_bits) { - NOTIMPLEMENTED(); - return NULL; + DCHECK_EQ(AES, algorithm); + int key_size_in_bytes = key_size_in_bits / 8; + DCHECK_EQ(static_cast(key_size_in_bits), key_size_in_bytes * 8); + + if (key_size_in_bits == 0) + return NULL; + + EnsureOpenSSLInit(); + scoped_ptr key(new SymmetricKey); + uint8* key_data = + reinterpret_cast(WriteInto(&key->key_, key_size_in_bytes + 1)); + + int res = RAND_bytes(key_data, key_size_in_bytes); + if (res != 1) { + DLOG(ERROR) << "RAND_bytes failed. res = " << res; + ClearOpenSSLERRStack(); + return NULL; + } + return key.release(); } // static @@ -24,20 +50,37 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, const std::string& salt, size_t iterations, size_t key_size_in_bits) { - NOTIMPLEMENTED(); - return NULL; + DCHECK(algorithm == AES || algorithm == HMAC_SHA1); + int key_size_in_bytes = key_size_in_bits / 8; + DCHECK_EQ(static_cast(key_size_in_bits), key_size_in_bytes * 8); + + EnsureOpenSSLInit(); + scoped_ptr key(new SymmetricKey); + uint8* key_data = + reinterpret_cast(WriteInto(&key->key_, key_size_in_bytes + 1)); + int res = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(), + reinterpret_cast(salt.data()), + salt.length(), iterations, + key_size_in_bytes, key_data); + if (res != 1) { + DLOG(ERROR) << "HMAC SHA1 failed. res = " << res; + ClearOpenSSLERRStack(); + return NULL; + } + return key.release(); } // static SymmetricKey* SymmetricKey::Import(Algorithm algorithm, const std::string& raw_key) { - NOTIMPLEMENTED(); - return NULL; + scoped_ptr key(new SymmetricKey); + key->key_ = raw_key; + return key.release(); } bool SymmetricKey::GetRawKey(std::string* raw_key) { - NOTIMPLEMENTED(); - return false; + *raw_key = key_; + return true; } } // namespace base diff --git a/base/crypto/symmetric_key_unittest.cc b/base/crypto/symmetric_key_unittest.cc index 664bcb5..a9b0b9e 100644 --- a/base/crypto/symmetric_key_unittest.cc +++ b/base/crypto/symmetric_key_unittest.cc @@ -7,6 +7,7 @@ #include #include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -66,156 +67,160 @@ TEST(SymmetricKeyTest, ImportDerivedKey) { } struct PBKDF2TestVector { + base::SymmetricKey::Algorithm algorithm; const char* password; const char* salt; unsigned int rounds; unsigned int key_size_in_bits; - const uint8 expected[21]; // string literals need 1 extra NUL byte + const char* expected; // ASCII encoded hex bytes }; -static const PBKDF2TestVector test_vectors[] = { +class SymmetricKeyDeriveKeyFromPasswordTest + : public testing::TestWithParam { +}; + +TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { + PBKDF2TestVector test_data(GetParam()); +#if defined(OS_MACOSX) + // The OS X crypto libraries have minimum salt and iteration requirements + // so some of the tests below will cause them to barf. Skip these. + if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { + VLOG(1) << "Skipped test vector for " << test_data.expected; + return; + } +#endif // OS_MACOSX + + scoped_ptr key( + base::SymmetricKey::DeriveKeyFromPassword( + test_data.algorithm, + test_data.password, test_data.salt, + test_data.rounds, test_data.key_size_in_bits)); + ASSERT_TRUE(NULL != key.get()); + + std::string raw_key; + key->GetRawKey(&raw_key); + EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); + EXPECT_EQ(test_data.expected, + StringToLowerASCII(base::HexEncode(raw_key.data(), + raw_key.size()))); +} + +static const PBKDF2TestVector kTestVectors[] = { // These tests come from // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt { + base::SymmetricKey::HMAC_SHA1, "password", "salt", 1, 160, - "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" - "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", + "0c60c80f961f0e71f3a9b524af6012062fe037a6", }, { + base::SymmetricKey::HMAC_SHA1, "password", "salt", 2, 160, - "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e" - "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", + "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", }, { + base::SymmetricKey::HMAC_SHA1, "password", "salt", 4096, 160, - "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad" - "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", + "4b007901b765489abead49d926f721d065a429c1", }, // This test takes over 30s to run on the trybots. #if 0 { + base::SymmetricKey::HMAC_SHA1, "password", "salt", 16777216, 160, - "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94" - "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", + "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", }, #endif // These tests come from RFC 3962, via BSD source code at // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain { + base::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn", 1, 160, - { - 0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, - 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15, - 0x0a, 0xd1, 0xf7, 0xa0 - }, + "cdedb5281bb2f801565a1122b25635150ad1f7a0", }, { + base::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn", 2, 160, - { - 0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e, - 0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d, - 0xa0, 0x53, 0x78, 0xb9 - }, + "01dbee7f4a9e243e988b62c73cda935da05378b9", }, { + base::SymmetricKey::HMAC_SHA1, "password", "ATHENA.MIT.EDUraeburn", 1200, 160, - { - 0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, - 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b, - 0xa7, 0xe5, 0x2d, 0xdb - }, + "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", }, { + base::SymmetricKey::HMAC_SHA1, "password", "\0224VxxV4\022", /* 0x1234567878563412 */ 5, 160, - { - 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, - 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49, - 0x3f, 0x98, 0xd2, 0x03 - }, + "d1daa78615f287e6a1c8b120d7062a493f98d203", }, { + base::SymmetricKey::HMAC_SHA1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase equals block size", 1200, 160, - { - 0x13, 0x9c, 0x30, 0xc0, 0x96, 0x6b, 0xc3, 0x2b, - 0xa5, 0x5f, 0xdb, 0xf2, 0x12, 0x53, 0x0a, 0xc9, - 0xc5, 0xec, 0x59, 0xf1 - }, + "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", }, { + base::SymmetricKey::HMAC_SHA1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", 1200, 160, - { - 0x9c, 0xca, 0xd6, 0xd4, 0x68, 0x77, 0x0c, 0xd5, - 0x1b, 0x10, 0xe6, 0xa6, 0x87, 0x21, 0xbe, 0x61, - 0x1a, 0x8b, 0x4d, 0x28 - }, + "9ccad6d468770cd51b10e6a68721be611a8b4d28", }, { + base::SymmetricKey::HMAC_SHA1, "\360\235\204\236", /* g-clef (0xf09d849e) */ "EXAMPLE.COMpianist", 50, 160, - { - 0x6b, 0x9c, 0xf2, 0x6d, 0x45, 0x45, 0x5a, 0x43, - 0xa5, 0xb8, 0xbb, 0x27, 0x6a, 0x40, 0x3b, 0x39, - 0xe7, 0xfe, 0x37, 0xa0 - }, - } + "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", + }, + + // Regression tests for AES keys, derived from the Linux NSS implementation. + { + base::SymmetricKey::AES, + "A test password", + "saltsalt", + 1, + 256, + "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", + }, + { + base::SymmetricKey::AES, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", + 20, + 256, + "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", + }, }; -TEST(SymmetricKeyTest, DeriveKeyFromPassword) { - for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_vectors); ++i) { - SCOPED_TRACE(StringPrintf("Test[%u]", i)); -#if defined(OS_MACOSX) - // The OS X crypto libraries have minimum salt and iteration requirements - // so some of the above tests will cause them to barf. Skip these. - if (strlen(test_vectors[i].salt) < 8 || test_vectors[i].rounds < 1000) { - VLOG(1) << "Skipped test vector #" << i; - continue; - } -#endif // OS_MACOSX - scoped_ptr key( - base::SymmetricKey::DeriveKeyFromPassword( - base::SymmetricKey::HMAC_SHA1, - test_vectors[i].password, test_vectors[i].salt, - test_vectors[i].rounds, test_vectors[i].key_size_in_bits)); - ASSERT_TRUE(NULL != key.get()); - - std::string raw_key; - key->GetRawKey(&raw_key); - EXPECT_EQ(test_vectors[i].key_size_in_bits / 8, raw_key.size()); - EXPECT_EQ(0, memcmp(test_vectors[i].expected, - raw_key.data(), - raw_key.size())); - } -} +INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, + testing::ValuesIn(kTestVectors)); diff --git a/base/file_path.cc b/base/file_path.cc index 5165828..eba9afe 100644 --- a/base/file_path.cc +++ b/base/file_path.cc @@ -7,7 +7,7 @@ #if defined(OS_WIN) #include #elif defined(OS_MACOSX) -#include +#include #endif #include "base/logging.h" diff --git a/base/file_util_mac.mm b/base/file_util_mac.mm index 43bf6e9..ca0284c 100644 --- a/base/file_util_mac.mm +++ b/base/file_util_mac.mm @@ -4,7 +4,7 @@ #include "base/file_util.h" -#import +#import #include #include "base/basictypes.h" diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc index 85123e9..f1caa29 100644 --- a/base/file_util_posix.cc +++ b/base/file_util_posix.cc @@ -132,7 +132,7 @@ int CountFilesCreatedAfter(const FilePath& path, // which are older than |comparison_time| are considered newer // (current implementation) 2. files newer than // |comparison_time| are considered older. - if (st.st_ctime >= comparison_time.ToTimeT()) + if (static_cast(st.st_ctime) >= comparison_time.ToTimeT()) ++file_count; } closedir(dir); @@ -762,7 +762,7 @@ void MemoryMappedFile::CloseHandles() { bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo& find_info, const base::Time& cutoff_time) { - return find_info.stat.st_mtime >= cutoff_time.ToTimeT(); + return static_cast(find_info.stat.st_mtime) >= cutoff_time.ToTimeT(); } bool NormalizeFilePath(const FilePath& path, FilePath* normalized_path) { diff --git a/base/i18n/rtl.cc b/base/i18n/rtl.cc index 9ff12d8..0881fb7 100644 --- a/base/i18n/rtl.cc +++ b/base/i18n/rtl.cc @@ -44,22 +44,6 @@ namespace i18n { // Represents the locale-specific ICU text direction. static TextDirection g_icu_text_direction = UNKNOWN_DIRECTION; -#if defined(OS_WIN) -void GetLanguageAndRegionFromOS(std::string* lang, std::string* region) { - // Later we may have to change this to be OS-dependent so that - // it's not affected by ICU's default locale. It's all right - // to do this way because SetICUDefaultLocale is internal - // to this file and we know that it's not yet called when this function - // is called. - const icu::Locale& locale = icu::Locale::getDefault(); - const char* language = locale.getLanguage(); - const char* country = locale.getCountry(); - DCHECK(language); - *lang = language; - *region = country; -} -#endif - // Convert the ICU default locale to a string. std::string GetConfiguredLocale() { return GetLocaleString(icu::Locale::getDefault()); diff --git a/base/i18n/rtl.h b/base/i18n/rtl.h index 52b1a2b..ed0882f 100644 --- a/base/i18n/rtl.h +++ b/base/i18n/rtl.h @@ -6,6 +6,8 @@ #define BASE_I18N_RTL_H_ #pragma once +#include + #include "base/compiler_specific.h" #include "base/string16.h" #include "build/build_config.h" @@ -29,11 +31,6 @@ enum TextDirection { LEFT_TO_RIGHT, }; -#if defined(OS_WIN) -// Get language and region from the OS. Used by Chrome Frame. -void GetLanguageAndRegionFromOS(std::string* lang, std::string* region); -#endif - // Get the locale that the currently running process has been configured to use. // The return value is of the form language[-country] (e.g., en-US) where the // language is the 2 or 3 letter code from ISO-639. diff --git a/base/logging.cc b/base/logging.cc index d8681a9..9cc191d 100644 --- a/base/logging.cc +++ b/base/logging.cc @@ -19,7 +19,12 @@ typedef HANDLE MutexHandle; #include #include #elif defined(OS_POSIX) +#if defined(OS_NACL) +#include +#include // timespec doesn't seem to be in +#else #include +#endif #include #endif @@ -132,6 +137,8 @@ int32 CurrentThreadId() { #elif defined(OS_FREEBSD) // TODO(BSD): find a better thread ID return reinterpret_cast(pthread_self()); +#elif defined(OS_NACL) + return pthread_self(); #endif } @@ -140,6 +147,10 @@ uint64 TickCount() { return GetTickCount(); #elif defined(OS_MACOSX) return mach_absolute_time(); +#elif defined(OS_NACL) + // NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h + // So we have to use clock() for now. + return clock(); #elif defined(OS_POSIX) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); diff --git a/base/mac_util.h b/base/mac_util.h index 182fcc8..d31bf82 100644 --- a/base/mac_util.h +++ b/base/mac_util.h @@ -50,6 +50,7 @@ bool FSRefFromPath(const std::string& path, FSRef* ref); // Returns true if the application is running from a bundle bool AmIBundled(); +void SetOverrideAmIBundled(bool value); // Returns true if this process is marked as a "Background only process". bool IsBackgroundOnlyProcess(); diff --git a/base/mac_util.mm b/base/mac_util.mm index 4e6b105..9610d37 100644 --- a/base/mac_util.mm +++ b/base/mac_util.mm @@ -145,8 +145,14 @@ bool FSRefFromPath(const std::string& path, FSRef* ref) { return status == noErr; } +static bool g_override_am_i_bundled = false; +static bool g_override_am_i_bundled_value = false; + // Adapted from http://developer.apple.com/carbon/tipsandtricks.html#AmIBundled -bool AmIBundled() { +static bool UncachedAmIBundled() { + if (g_override_am_i_bundled) + return g_override_am_i_bundled_value; + ProcessSerialNumber psn = {0, kCurrentProcess}; FSRef fsref; @@ -167,6 +173,23 @@ bool AmIBundled() { return info.nodeFlags & kFSNodeIsDirectoryMask; } +bool AmIBundled() { + // If the return value is not cached, this function will return different + // values depending on when it's called. This confuses some client code, see + // http://crbug.com/63183 . + static bool result = UncachedAmIBundled(); + DCHECK_EQ(result, UncachedAmIBundled()) + << "The return value of AmIBundled() changed. This will confuse tests. " + << "Call SetAmIBundled() override manually if your test binary " + << "delay-loads the framework."; + return result; +} + +void SetOverrideAmIBundled(bool value) { + g_override_am_i_bundled = true; + g_override_am_i_bundled_value = value; +} + bool IsBackgroundOnlyProcess() { // This function really does want to examine NSBundle's idea of the main // bundle dictionary, and not the overriden MainAppBundle. It needs to look diff --git a/base/message_loop.cc b/base/message_loop.cc index de0b271..1e472e0 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -163,7 +163,7 @@ MessageLoop::MessageLoop(Type type) } MessageLoop::~MessageLoop() { - DCHECK(this == current()); + DCHECK_EQ(this, current()); // Let interested parties have one last shot at accessing this. FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, @@ -194,13 +194,13 @@ MessageLoop::~MessageLoop() { void MessageLoop::AddDestructionObserver( DestructionObserver* destruction_observer) { - DCHECK(this == current()); + DCHECK_EQ(this, current()); destruction_observers_.AddObserver(destruction_observer); } void MessageLoop::RemoveDestructionObserver( DestructionObserver* destruction_observer) { - DCHECK(this == current()); + DCHECK_EQ(this, current()); destruction_observers_.RemoveObserver(destruction_observer); } @@ -254,7 +254,7 @@ __declspec(noinline) void MessageLoop::RunInternalInSEHFrame() { //------------------------------------------------------------------------------ void MessageLoop::RunInternal() { - DCHECK(this == current()); + DCHECK_EQ(this, current()); #ifndef ANDROID StartHistogrammer(); @@ -291,7 +291,7 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() { //------------------------------------------------------------------------------ void MessageLoop::Quit() { - DCHECK(current() == this); + DCHECK_EQ(this, current()); if (state_) { state_->quit_received = true; } else { @@ -300,7 +300,7 @@ void MessageLoop::Quit() { } void MessageLoop::QuitNow() { - DCHECK(current() == this); + DCHECK_EQ(this, current()); if (state_) { pump_->Quit(); } else { diff --git a/base/message_pump_glib_x.cc b/base/message_pump_glib_x.cc index 675774e..78c1799 100644 --- a/base/message_pump_glib_x.cc +++ b/base/message_pump_glib_x.cc @@ -5,7 +5,11 @@ #include "base/message_pump_glib_x.h" #include +#if defined(HAVE_XINPUT2) +#include +#else #include +#endif #include "base/message_pump_glib_x_dispatch.h" @@ -17,17 +21,61 @@ gboolean PlaceholderDispatch(GSource* source, return TRUE; } +#if defined(HAVE_XINPUT2) + +// Setup XInput2 select for the GtkWidget. +gboolean GtkWidgetRealizeCallback(GSignalInvocationHint* hint, guint nparams, + const GValue* pvalues, gpointer data) { + GtkWidget* widget = GTK_WIDGET(g_value_get_object(pvalues)); + GdkWindow* window = widget->window; + base::MessagePumpGlibX* msgpump = static_cast(data); + + DCHECK(window); // TODO(sad): Remove once determined if necessary. + + // TODO(sad): Do we need to set a flag on |window| to make sure we don't + // select for the same GdkWindow multiple times? Does it matter? + msgpump->SetupXInput2ForXWindow(GDK_WINDOW_XID(window)); + + return true; +} + +// We need to capture all the GDK windows that get created, and start +// listening for XInput2 events. So we setup a callback to the 'realize' +// signal for GTK+ widgets, so that whenever the signal triggers for any +// GtkWidget, which means the GtkWidget should now have a GdkWindow, we can +// setup XInput2 events for the GdkWindow. +void SetupGtkWidgetRealizeNotifier(base::MessagePumpGlibX* msgpump) { + guint signal_id; + gpointer klass = g_type_class_ref(GTK_TYPE_WIDGET); + + g_signal_parse_name("realize", GTK_TYPE_WIDGET, &signal_id, NULL, FALSE); + g_signal_add_emission_hook(signal_id, 0, GtkWidgetRealizeCallback, + static_cast(msgpump), NULL); + + g_type_class_unref(klass); +} + +#endif // HAVE_XINPUT2 + } // namespace namespace base { MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), +#if defined(HAVE_XINPUT2) + xiopcode_(-1), + masters_(), + slaves_(), +#endif gdksource_(NULL), dispatching_event_(false), capture_x_events_(0), capture_gdk_events_(0) { gdk_event_handler_set(&EventDispatcherX, this, NULL); +#if defined(HAVE_XINPUT2) + InitializeXInput2(); +#endif InitializeEventsToCapture(); } @@ -40,7 +88,11 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { if (XPending(display)) { XEvent xev; XPeekEvent(display, &xev); - if (capture_x_events_[xev.type]) { + if (capture_x_events_[xev.type] +#if defined(HAVE_XINPUT2) + && (xev.type != GenericEvent || xev.xcookie.extension == xiopcode_) +#endif + ) { XNextEvent(display, &xev); bool processed = static_cast @@ -48,6 +100,13 @@ bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { if (!processed) { DLOG(WARNING) << "Event (" << xev.type << ") not handled."; + + // TODO(sad): It is necessary to put back the event so that the default + // GDK events handler can take care of it. Without this, it is + // impossible to use the omnibox at the moment. However, this will + // eventually be removed once the omnibox code is updated for touchui. + XPutBackEvent(display, &xev); + g_main_context_iteration(context, FALSE); } } else { // TODO(sad): A couple of extra events can still sneak in during this. @@ -94,8 +153,90 @@ void MessagePumpGlibX::InitializeEventsToCapture(void) { capture_x_events_[MotionNotify] = true; capture_gdk_events_[GDK_MOTION_NOTIFY] = true; + +#if defined(HAVE_XINPUT2) + capture_x_events_[GenericEvent] = true; +#endif +} + +#if defined(HAVE_XINPUT2) +void MessagePumpGlibX::InitializeXInput2(void) { + GdkDisplay* display = gdk_display_get_default(); + Display* xdisplay = GDK_DISPLAY_XDISPLAY(display); + int event, err; + + if (!XQueryExtension(xdisplay, "XInputExtension", &xiopcode_, &event, &err)) { + DLOG(WARNING) << "X Input extension not available."; + xiopcode_ = -1; + return; + } + + int major = 2, minor = 0; + if (XIQueryVersion(xdisplay, &major, &minor) == BadRequest) { + DLOG(WARNING) << "XInput2 not supported in the server."; + xiopcode_ = -1; + return; + } + + SetupGtkWidgetRealizeNotifier(this); + + // Instead of asking X for the list of devices all the time, let's maintain a + // list of slave (physical) and master (virtual) pointer devices. + int count = 0; + XIDeviceInfo* devices = XIQueryDevice(xdisplay, XIAllDevices, &count); + for (int i = 0; i < count; i++) { + XIDeviceInfo* devinfo = devices + i; + if (devinfo->use == XISlavePointer) { + slaves_.insert(devinfo->deviceid); + } else if (devinfo->use == XIMasterPointer) { + masters_.insert(devinfo->deviceid); + } + // We do not need to care about XIFloatingSlave, because the callback for + // XI_HierarchyChanged event will take care of it. + } + XIFreeDeviceInfo(devices); + + // TODO(sad): Select on root for XI_HierarchyChanged so that slaves_ and + // masters_ can be kept up-to-date. This is a relatively rare event, so we can + // put it off for a later time. + // Note: It is not necessary to listen for XI_DeviceChanged events. } +void MessagePumpGlibX::SetupXInput2ForXWindow(Window xwindow) { + Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + + // Setup mask for mouse events. + unsigned char mask[(XI_LASTEVENT + 7)/8]; + memset(mask, 0, sizeof(mask)); + + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + + // It is necessary to select only for the master devices. XInput2 provides + // enough information to the event callback to decide which slave device + // triggered the event, thus decide whether the 'pointer event' is a 'mouse + // event' or a 'touch event'. So it is not necessary to select for the slave + // devices here. + XIEventMask evmasks[masters_.size()]; + int count = 0; + for (std::set::const_iterator iter = masters_.begin(); + iter != masters_.end(); + ++iter, ++count) { + evmasks[count].deviceid = *iter; + evmasks[count].mask_len = sizeof(mask); + evmasks[count].mask = mask; + } + + XISelectEvents(xdisplay, xwindow, evmasks, masters_.size()); + + // TODO(sad): Setup masks for keyboard events. + + XFlush(xdisplay); +} + +#endif // HAVE_XINPUT2 + void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) { MessagePumpGlibX* pump_x = reinterpret_cast(data); diff --git a/base/message_pump_glib_x.h b/base/message_pump_glib_x.h index 2f50731..c6d98e3 100644 --- a/base/message_pump_glib_x.h +++ b/base/message_pump_glib_x.h @@ -9,6 +9,7 @@ #include "base/message_pump_glib.h" #include +#include #include #include @@ -28,6 +29,11 @@ class MessagePumpGlibX : public MessagePumpForUI { // was captured and being processed by GDK (when |false|). bool IsDispatchingEvent(void) { return dispatching_event_; } +#if defined(HAVE_XINPUT2) + // Setup an X Window for XInput2 events. + void SetupXInput2ForXWindow(Window xid); +#endif + private: static void EventDispatcherX(GdkEvent* event, gpointer data); @@ -35,6 +41,22 @@ class MessagePumpGlibX : public MessagePumpForUI { // processed so that GDK doesn't get to them. void InitializeEventsToCapture(void); +#if defined(HAVE_XINPUT2) + // Initialize X2 input. + void InitializeXInput2(void); + + // The opcode used for checking events. + int xiopcode_; + + // The list of master pointer devices. We maintain this list so that it is not + // necessary to query X for the list of devices for each GdkWindow created. + std::set masters_; + + // The list of slave (physical) pointer devices. + // TODO(sad): This is currently unused, and may be removed eventually. + std::set slaves_; +#endif + // The event source for GDK events. GSource* gdksource_; diff --git a/base/native_library.h b/base/native_library.h index 2bb8497..3d8c280 100644 --- a/base/native_library.h +++ b/base/native_library.h @@ -14,12 +14,12 @@ #if defined(OS_WIN) #include #elif defined(OS_MACOSX) -#import +#import #endif // OS_* #include "base/string16.h" -// Macro usefull for writing cross-platform function pointers. +// Macro useful for writing cross-platform function pointers. #if defined(OS_WIN) && !defined(CDECL) #define CDECL __cdecl #else diff --git a/base/native_library_linux.cc b/base/native_library_linux.cc index b6d7aef..d5ab128 100644 --- a/base/native_library_linux.cc +++ b/base/native_library_linux.cc @@ -8,12 +8,16 @@ #include "base/file_path.h" #include "base/logging.h" +#include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" namespace base { // static NativeLibrary LoadNativeLibrary(const FilePath& library_path) { + // dlopen() opens the file off disk. + base::ThreadRestrictions::AssertIOAllowed(); + // We deliberately do not use RTLD_DEEPBIND. For the history why, please // refer to the bug tracker. Some useful bug reports to read include: // http://crbug.com/17943, http://crbug.com/17557, http://crbug.com/36892, diff --git a/base/native_library_mac.mm b/base/native_library_mac.mm index 95cac15..0669bee 100644 --- a/base/native_library_mac.mm +++ b/base/native_library_mac.mm @@ -5,18 +5,19 @@ #include "base/native_library.h" #include -#import #include "base/file_path.h" #include "base/file_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/string_util.h" +#include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" namespace base { // static NativeLibrary LoadNativeLibrary(const FilePath& library_path) { + // dlopen() etc. open the file off disk. if (library_path.Extension() == "dylib" || !file_util::DirectoryExists(library_path)) { void* dylib = dlopen(library_path.value().c_str(), RTLD_LAZY); diff --git a/base/native_library_win.cc b/base/native_library_win.cc index 94e4b63..b498eba 100644 --- a/base/native_library_win.cc +++ b/base/native_library_win.cc @@ -7,12 +7,16 @@ #include #include "base/file_util.h" +#include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" namespace base { // static NativeLibrary LoadNativeLibrary(const FilePath& library_path) { + // LoadLibrary() opens the file off disk. + base::ThreadRestrictions::AssertIOAllowed(); + // Switch the current directory to the library directory as the library // may have dependencies on DLLs in this directory. bool restore_directory = false; diff --git a/base/openssl_util.cc b/base/openssl_util.cc new file mode 100644 index 0000000..894c710 --- /dev/null +++ b/base/openssl_util.cc @@ -0,0 +1,88 @@ +// 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 "base/openssl_util.h" + +#include +#include + +#include "base/lock.h" +#include "base/logging.h" +#include "base/scoped_vector.h" +#include "base/singleton.h" + +namespace base { + +namespace { + +unsigned long CurrentThreadId() { + return static_cast(PlatformThread::CurrentId()); +} + +// Singleton for initializing and cleaning up the OpenSSL library. +class OpenSSLInitSingleton { + private: + friend struct DefaultSingletonTraits; + OpenSSLInitSingleton() { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + int num_locks = CRYPTO_num_locks(); + locks_.reserve(num_locks); + for (int i = 0; i < num_locks; ++i) + locks_.push_back(new Lock()); + CRYPTO_set_locking_callback(LockingCallback); + CRYPTO_set_id_callback(CurrentThreadId); + } + + ~OpenSSLInitSingleton() { + CRYPTO_set_locking_callback(NULL); + EVP_cleanup(); + ERR_free_strings(); + } + + static void LockingCallback(int mode, int n, const char* file, int line) { + Singleton::get()->OnLockingCallback(mode, n, file, + line); + } + + void OnLockingCallback(int mode, int n, const char* file, int line) { + CHECK_LT(static_cast(n), locks_.size()); + if (mode & CRYPTO_LOCK) + locks_[n]->Acquire(); + else + locks_[n]->Release(); + } + + // These locks are used and managed by OpenSSL via LockingCallback(). + ScopedVector locks_; + + DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton); +}; + +} // namespace + +void EnsureOpenSSLInit() { + (void)Singleton::get(); +} + +void ClearOpenSSLERRStack() { + if (logging::DEBUG_MODE && VLOG_IS_ON(1)) { + int error_num = ERR_get_error(); + if (error_num == 0) + return; + + DVLOG(1) << "OpenSSL ERR_get_error stack:"; + char buf[140]; + do { + ERR_error_string_n(error_num, buf, arraysize(buf)); + DVLOG(1) << "\t" << error_num << ": " << buf; + error_num = ERR_get_error(); + } while (error_num != 0); + } else { + ERR_clear_error(); + } +} + +} // namespace base diff --git a/base/openssl_util.h b/base/openssl_util.h index 4f564cf..1d290ae 100644 --- a/base/openssl_util.h +++ b/base/openssl_util.h @@ -2,14 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_OPENNSSL_UTIL_H_ -#define BASE_OPENNSSL_UTIL_H_ +#ifndef BASE_OPENSSL_UTIL_H_ +#define BASE_OPENSSL_UTIL_H_ #pragma once #include "base/basictypes.h" +#include "base/tracked.h" namespace base { +// A helper class that takes care of destroying OpenSSL objects when it goes out +// of scope. +template +class ScopedOpenSSL { + public: + explicit ScopedOpenSSL(T* ptr_) : ptr_(ptr_) { } + ~ScopedOpenSSL() { if (ptr_) (*destructor)(ptr_); } + + T* get() const { return ptr_; } + + private: + T* ptr_; +}; + // Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's // SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those // of the our base wrapper APIs. @@ -46,8 +61,20 @@ class ScopedOpenSSLSafeSizeBuffer { // Temporary buffer writen into in the case where the caller's // buffer is not of sufficient size. unsigned char min_sized_buffer_[MIN_SIZE]; + + DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSLSafeSizeBuffer); }; +// Initialize OpenSSL if it isn't already initialized. This must be called +// before any other OpenSSL functions. +// This function is thread-safe, and OpenSSL will only ever be initialized once. +// OpenSSL will be properly shut down on program exit. +void EnsureOpenSSLInit(); + +// Drains the OpenSSL ERR_get_error stack. On a debug build the error codes +// are send to VLOG(1), on a release build they are disregarded. +void ClearOpenSSLERRStack(); + } // namespace base -#endif // BASE_NSS_UTIL_H_ +#endif // BASE_OPENSSL_UTIL_H_ diff --git a/base/path_service.cc b/base/path_service.cc index 8660c42..9eed56d 100644 --- a/base/path_service.cc +++ b/base/path_service.cc @@ -215,6 +215,14 @@ bool PathService::Get(int key, std::wstring* result) { } #endif +// TODO(evan): remove me -- see comments in header. +bool PathService::IsOverridden(int key) { + PathData* path_data = GetPathData(); + DCHECK(path_data); + AutoLock scoped_lock(path_data->lock); + return path_data->overrides.find(key) != path_data->overrides.end(); +} + bool PathService::Override(int key, const FilePath& path) { PathData* path_data = GetPathData(); DCHECK(path_data); diff --git a/base/path_service.h b/base/path_service.h index 4d99cdc..6873e1f 100644 --- a/base/path_service.h +++ b/base/path_service.h @@ -45,6 +45,11 @@ class PathService { // over the lifetime of the app, so this method should be used with caution. static bool Override(int key, const FilePath& path); + // Return whether a path was overridden. + // TODO(evan): temporarily restoring this to quick-fix a regression. + // Remove me again once it's fixed properly. + static bool IsOverridden(int key); + // To extend the set of supported keys, you can register a path provider, // which is just a function mirroring PathService::Get. The ProviderFunc // returns false if it cannot provide a non-empty path for the given key. diff --git a/base/pickle.cc b/base/pickle.cc index 06a3be1..3f376e3 100644 --- a/base/pickle.cc +++ b/base/pickle.cc @@ -41,11 +41,21 @@ Pickle::Pickle(int header_size) Pickle::Pickle(const char* data, int data_len) : header_(reinterpret_cast(const_cast(data))), - header_size_(data_len - header_->payload_size), + header_size_(0), capacity_(kCapacityReadOnly), variable_buffer_offset_(0) { - DCHECK(header_size_ >= sizeof(Header)); - DCHECK(header_size_ == AlignInt(header_size_, sizeof(uint32))); + if (data_len >= static_cast(sizeof(Header))) + header_size_ = data_len - header_->payload_size; + + if (header_size_ > static_cast(data_len)) + header_size_ = 0; + + if (header_size_ != AlignInt(header_size_, sizeof(uint32))) + header_size_ = 0; + + // If there is anything wrong with the data, we're not going to use it. + if (!header_size_) + header_ = NULL; } Pickle::Pickle(const Pickle& other) diff --git a/base/pickle.h b/base/pickle.h index c7aee67..6006e62 100644 --- a/base/pickle.h +++ b/base/pickle.h @@ -177,10 +177,12 @@ class Pickle { // Returns the address of the byte immediately following the currently valid // header + payload. char* end_of_payload() { + // We must have a valid header_. return payload() + payload_size(); } const char* end_of_payload() const { - return payload() + payload_size(); + // This object may be invalid. + return header_ ? payload() + payload_size() : NULL; } size_t capacity() const { diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc index aea3830..fdc0664 100644 --- a/base/pickle_unittest.cc +++ b/base/pickle_unittest.cc @@ -87,6 +87,39 @@ TEST(PickleTest, EncodeDecode) { VerifyResult(pickle3); } +// Tests that we can handle really small buffers. +TEST(PickleTest, SmallBuffer) { + scoped_array buffer(new char[1]); + + // We should not touch the buffer. + Pickle pickle(buffer.get(), 1); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + +// Tests that we can handle improper headers. +TEST(PickleTest, BigSize) { + int buffer[] = { 0x56035200, 25, 40, 50 }; + + Pickle pickle(reinterpret_cast(buffer), sizeof(buffer)); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + +TEST(PickleTest, UnalignedSize) { + int buffer[] = { 10, 25, 40, 50 }; + + Pickle pickle(reinterpret_cast(buffer), sizeof(buffer)); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + TEST(PickleTest, ZeroLenStr) { Pickle pickle; EXPECT_TRUE(pickle.WriteString("")); diff --git a/base/platform_thread_posix.cc b/base/platform_thread_posix.cc index 040452e..66f3928 100644 --- a/base/platform_thread_posix.cc +++ b/base/platform_thread_posix.cc @@ -4,7 +4,6 @@ #include "base/platform_thread.h" -#include #include #include @@ -15,11 +14,16 @@ #endif #if defined(OS_LINUX) +#include #include #include #include #endif +#if defined(OS_NACL) +#include +#endif + #include "base/logging.h" #include "base/safe_strerror_posix.h" @@ -47,6 +51,8 @@ PlatformThreadId PlatformThread::CurrentId() { #elif defined(OS_FREEBSD) // TODO(BSD): find a better thread ID return reinterpret_cast(pthread_self()); +#elif defined(OS_NACL) + return pthread_self(); #endif } diff --git a/base/process_util.h b/base/process_util.h index 77d772b..ca43289 100644 --- a/base/process_util.h +++ b/base/process_util.h @@ -36,14 +36,6 @@ typedef struct _malloc_zone_t malloc_zone_t; #include "base/file_descriptor_shuffle.h" #include "base/process.h" -#ifndef NAME_MAX // Solaris and some BSDs have no NAME_MAX -#ifdef MAXNAMLEN -#define NAME_MAX MAXNAMLEN -#else -#define NAME_MAX 256 -#endif -#endif - class CommandLine; class FilePath; diff --git a/base/safe_strerror_posix.cc b/base/safe_strerror_posix.cc index 68b2fca..a91bb8d 100644 --- a/base/safe_strerror_posix.cc +++ b/base/safe_strerror_posix.cc @@ -2,13 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" #include "base/safe_strerror_posix.h" #include #include #include -#if defined(__GLIBC__) && defined(__GNUC__) +#define USE_HISTORICAL_STRERRO_R (defined(__GLIBC__) || defined(OS_NACL)) + +#if USE_HISTORICAL_STRERRO_R && defined(__GNUC__) // GCC will complain about the unused second wrap function unless we tell it // that we meant for them to be potentially unused, which is exactly what this // attribute is for. @@ -17,7 +20,7 @@ #define POSSIBLY_UNUSED #endif -#if defined(__GLIBC__) +#if USE_HISTORICAL_STRERRO_R // glibc has two strerror_r functions: a historical GNU-specific one that // returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4 // that returns int. This wraps the GNU-specific one. @@ -37,7 +40,7 @@ static void POSSIBLY_UNUSED wrap_posix_strerror_r( // The GNU version never fails. Unknown errors get an "unknown error" message. // The result is always null terminated. } -#endif // __GLIBC__ +#endif // USE_HISTORICAL_STRERRO_R // Wrapper for strerror_r functions that implement the POSIX interface. POSIX // does not define the behaviour for some of the edge cases, so we wrap it to diff --git a/base/scoped_native_library.cc b/base/scoped_native_library.cc new file mode 100644 index 0000000..9d34449 --- /dev/null +++ b/base/scoped_native_library.cc @@ -0,0 +1,44 @@ +// 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 "base/scoped_native_library.h" + +namespace base { + +ScopedNativeLibrary::ScopedNativeLibrary() : library_(NULL) { +} + +ScopedNativeLibrary::ScopedNativeLibrary(NativeLibrary library) + : library_(library) { +} + +ScopedNativeLibrary::ScopedNativeLibrary(const FilePath& library_path) { + library_ = base::LoadNativeLibrary(library_path); +} + +ScopedNativeLibrary::~ScopedNativeLibrary() { + if (library_) + base::UnloadNativeLibrary(library_); +} + +void* ScopedNativeLibrary::GetFunctionPointer( + const char* function_name) const { + if (!library_) + return NULL; + return base::GetFunctionPointerFromNativeLibrary(library_, function_name); +} + +void ScopedNativeLibrary::Reset(NativeLibrary library) { + if (library_) + base::UnloadNativeLibrary(library_); + library_ = library; +} + +NativeLibrary ScopedNativeLibrary::Release() { + NativeLibrary result = library_; + library_ = NULL; + return result; +} + +} // namespace base diff --git a/base/scoped_native_library.h b/base/scoped_native_library.h index bed5c39..28b29b3 100644 --- a/base/scoped_native_library.h +++ b/base/scoped_native_library.h @@ -17,23 +17,33 @@ namespace base { // This class automatically unloads the loaded library in its destructor. class ScopedNativeLibrary { public: - explicit ScopedNativeLibrary(const FilePath& library_path) { - library_ = base::LoadNativeLibrary(library_path); - } + // Initializes with a NULL library. + ScopedNativeLibrary(); - ~ScopedNativeLibrary() { - if (library_) - base::UnloadNativeLibrary(library_); - } + // Takes ownership of the given library handle. + explicit ScopedNativeLibrary(NativeLibrary library); - void* GetFunctionPointer(const char* function_name) { - if (!library_) - return NULL; - return base::GetFunctionPointerFromNativeLibrary(library_, function_name); - } + // Opens the given library and manages its lifetime. + explicit ScopedNativeLibrary(const FilePath& library_path); + + ~ScopedNativeLibrary(); + + // Returns true if there's a valid library loaded. + bool is_valid() const { return !!library_; } + + void* GetFunctionPointer(const char* function_name) const; + + // Takes ownership of the given library handle. Any existing handle will + // be freed. + void Reset(NativeLibrary library); + + // Returns the native library handle and removes it from this object. The + // caller must manage the lifetime of the handle. + NativeLibrary Release(); private: - base::NativeLibrary library_; + NativeLibrary library_; + DISALLOW_COPY_AND_ASSIGN(ScopedNativeLibrary); }; diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 88ee41b..0a90150 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -42,8 +42,8 @@ // scoped_array, scoped_ptr_malloc. #include +#include #include -#include #include "base/compiler_specific.h" @@ -193,7 +193,7 @@ class scoped_array { // Get one element of the current object. // Will assert() if there is no current object, or index i is negative. - C& operator[](std::ptrdiff_t i) const { + C& operator[](ptrdiff_t i) const { assert(i >= 0); assert(array_ != NULL); return array_[i]; diff --git a/base/scoped_vector.h b/base/scoped_vector.h index ec152c9..9d372f3 100644 --- a/base/scoped_vector.h +++ b/base/scoped_vector.h @@ -54,6 +54,7 @@ class ScopedVector { } void reset() { STLDeleteElements(&v); } + void reserve(size_t capacity) { v.reserve(capacity); } void resize(size_t new_size) { v.resize(new_size); } // Lets the ScopedVector take ownership of |x|. diff --git a/base/shared_memory.h b/base/shared_memory.h index 719eb69..a088682 100644 --- a/base/shared_memory.h +++ b/base/shared_memory.h @@ -173,9 +173,11 @@ class SharedMemory { void Lock(); #if defined(OS_WIN) - // A Lock() implementation with a timeout. Returns true if the Lock() has - // been acquired, false if the timeout was reached. - bool Lock(uint32 timeout_ms); + // A Lock() implementation with a timeout that also allows setting + // security attributes on the mutex. sec_attr may be NULL. + // Returns true if the Lock() has been acquired, false if the timeout was + // reached. + bool Lock(uint32 timeout_ms, SECURITY_ATTRIBUTES* sec_attr); #endif // Releases the shared memory lock. diff --git a/base/shared_memory_win.cc b/base/shared_memory_win.cc index 5f293fc..15c61dd 100644 --- a/base/shared_memory_win.cc +++ b/base/shared_memory_win.cc @@ -197,17 +197,16 @@ void SharedMemory::Close() { } void SharedMemory::Lock() { - Lock(INFINITE); + Lock(INFINITE, NULL); } -bool SharedMemory::Lock(uint32 timeout_ms) { +bool SharedMemory::Lock(uint32 timeout_ms, SECURITY_ATTRIBUTES* sec_attr) { if (lock_ == NULL) { std::wstring name = name_; name.append(L"lock"); - lock_ = CreateMutex(NULL, FALSE, name.c_str()); - DCHECK(lock_ != NULL); + lock_ = CreateMutex(sec_attr, FALSE, name.c_str()); if (lock_ == NULL) { - DLOG(ERROR) << "Could not create mutex" << GetLastError(); + PLOG(ERROR) << "Could not create mutex."; return false; // there is nothing good we can do here. } } diff --git a/base/singleton.h b/base/singleton.h index 3fe16ce..564b686 100644 --- a/base/singleton.h +++ b/base/singleton.h @@ -239,12 +239,14 @@ class Singleton { private: // Adapter function for use with AtExit(). This should be called single - // threaded, but we might as well take the precautions anyway. + // threaded, so don't use atomic operations. + // Calling OnExit while singleton is in use by other threads is a mistake. static void OnExit(void* unused) { // AtExit should only ever be register after the singleton instance was // created. We should only ever get here with a valid instance_ pointer. - Traits::Delete(reinterpret_cast( - base::subtle::NoBarrier_AtomicExchange(&instance_, 0))); + Traits::Delete( + reinterpret_cast(base::subtle::NoBarrier_Load(&instance_))); + instance_ = 0; } static base::subtle::AtomicWord instance_; }; diff --git a/base/string16_unittest.cc b/base/string16_unittest.cc index 06b3dca..e833ed2 100644 --- a/base/string16_unittest.cc +++ b/base/string16_unittest.cc @@ -43,7 +43,7 @@ TEST(String16Test, OutputStream) { std::ostringstream stream; stream << initial_surrogate << "," << final_surrogate << "," - << surrogate_pair << ",", unterminated_surrogate; + << surrogate_pair << "," << unterminated_surrogate; EXPECT_STREQ("\xef\xbf\xbd,\xef\xbf\xbd,\xf0\x90\x8c\x80z,\xef\xbf\xbds", stream.str().c_str()); diff --git a/base/string_split.cc b/base/string_split.cc index bc7955d..44b5d06 100644 --- a/base/string_split.cc +++ b/base/string_split.cc @@ -168,4 +168,61 @@ void SplitStringDontTrim(const std::string& str, SplitStringT(str, c, false, r); } +template +void SplitStringAlongWhitespaceT(const STR& str, std::vector* result) { + const size_t length = str.length(); + if (!length) + return; + + bool last_was_ws = false; + size_t last_non_ws_start = 0; + for (size_t i = 0; i < length; ++i) { + switch (str[i]) { + // HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR. + case L' ': + case L'\t': + case L'\xA': + case L'\xB': + case L'\xC': + case L'\xD': + if (!last_was_ws) { + if (i > 0) { + result->push_back( + str.substr(last_non_ws_start, i - last_non_ws_start)); + } + last_was_ws = true; + } + break; + + default: // Not a space character. + if (last_was_ws) { + last_was_ws = false; + last_non_ws_start = i; + } + break; + } + } + if (!last_was_ws) { + result->push_back( + str.substr(last_non_ws_start, length - last_non_ws_start)); + } +} + +void SplitStringAlongWhitespace(const std::wstring& str, + std::vector* result) { + SplitStringAlongWhitespaceT(str, result); +} + +#if !defined(WCHAR_T_IS_UTF16) +void SplitStringAlongWhitespace(const string16& str, + std::vector* result) { + SplitStringAlongWhitespaceT(str, result); +} +#endif + +void SplitStringAlongWhitespace(const std::string& str, + std::vector* result) { + SplitStringAlongWhitespaceT(str, result); +} + } // namespace base diff --git a/base/string_split.h b/base/string_split.h index 6af1511..9a9030a 100644 --- a/base/string_split.h +++ b/base/string_split.h @@ -69,6 +69,21 @@ void SplitStringDontTrim(const std::string& str, char c, std::vector* r); +// WARNING: this uses whitespace as defined by the HTML5 spec. If you need +// a function similar to this but want to trim all types of whitespace, then +// factor this out into a function that takes a string containing the characters +// that are treated as whitespace. +// +// Splits the string along whitespace (where whitespace is the five space +// characters defined by HTML 5). Each contiguous block of non-whitespace +// characters is added to result. +void SplitStringAlongWhitespace(const std::wstring& str, + std::vector* result); +void SplitStringAlongWhitespace(const string16& str, + std::vector* result); +void SplitStringAlongWhitespace(const std::string& str, + std::vector* result); + } // namespace base #endif // BASE_STRING_SPLIT_H diff --git a/base/string_split_unittest.cc b/base/string_split_unittest.cc index afdc526..749d566 100644 --- a/base/string_split_unittest.cc +++ b/base/string_split_unittest.cc @@ -262,4 +262,36 @@ TEST(StringSplitTest, StringSplitDontTrim) { r.clear(); } +TEST(StringSplitTest, SplitStringAlongWhitespace) { + struct TestData { + const std::wstring input; + const size_t expected_result_count; + const std::wstring output1; + const std::wstring output2; + } data[] = { + { L"a", 1, L"a", L"" }, + { L" ", 0, L"", L"" }, + { L" a", 1, L"a", L"" }, + { L" ab ", 1, L"ab", L"" }, + { L" ab c", 2, L"ab", L"c" }, + { L" ab c ", 2, L"ab", L"c" }, + { L" ab cd", 2, L"ab", L"cd" }, + { L" ab cd ", 2, L"ab", L"cd" }, + { L" \ta\t", 1, L"a", L"" }, + { L" b\ta\t", 2, L"b", L"a" }, + { L" b\tat", 2, L"b", L"at" }, + { L"b\tat", 2, L"b", L"at" }, + { L"b\t at", 2, L"b", L"at" }, + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { + std::vector results; + SplitStringAlongWhitespace(data[i].input, &results); + ASSERT_EQ(data[i].expected_result_count, results.size()); + if (data[i].expected_result_count > 0) + ASSERT_EQ(data[i].output1, results[0]); + if (data[i].expected_result_count > 1) + ASSERT_EQ(data[i].output2, results[1]); + } +} + } // namespace base diff --git a/base/string_util.cc b/base/string_util.cc index 6717ca5..1c97487 100644 --- a/base/string_util.cc +++ b/base/string_util.cc @@ -826,63 +826,6 @@ string16 JoinString(const std::vector& parts, char16 sep) { return JoinStringT(parts, sep); } -template -void SplitStringAlongWhitespaceT(const STR& str, std::vector* result) { - const size_t length = str.length(); - if (!length) - return; - - bool last_was_ws = false; - size_t last_non_ws_start = 0; - for (size_t i = 0; i < length; ++i) { - switch (str[i]) { - // HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR. - case L' ': - case L'\t': - case L'\xA': - case L'\xB': - case L'\xC': - case L'\xD': - if (!last_was_ws) { - if (i > 0) { - result->push_back( - str.substr(last_non_ws_start, i - last_non_ws_start)); - } - last_was_ws = true; - } - break; - - default: // Not a space character. - if (last_was_ws) { - last_was_ws = false; - last_non_ws_start = i; - } - break; - } - } - if (!last_was_ws) { - result->push_back( - str.substr(last_non_ws_start, length - last_non_ws_start)); - } -} - -void SplitStringAlongWhitespace(const std::wstring& str, - std::vector* result) { - SplitStringAlongWhitespaceT(str, result); -} - -#if !defined(WCHAR_T_IS_UTF16) -void SplitStringAlongWhitespace(const string16& str, - std::vector* result) { - SplitStringAlongWhitespaceT(str, result); -} -#endif - -void SplitStringAlongWhitespace(const std::string& str, - std::vector* result) { - SplitStringAlongWhitespaceT(str, result); -} - template OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, const std::vector& subst, std::vector* offsets) { diff --git a/base/string_util.h b/base/string_util.h index c238e4a..498ccc5 100644 --- a/base/string_util.h +++ b/base/string_util.h @@ -122,6 +122,12 @@ template inline Char ToLowerASCII(Char c) { return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; } +// ASCII-specific toupper. The standard library's toupper is locale sensitive, +// so we don't want to use it here. +template inline Char ToUpperASCII(Char c) { + return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; +} + // Function objects to aid in comparing/searching strings. template struct CaseInsensitiveCompare { @@ -295,17 +301,11 @@ template inline str StringToLowerASCII(const str& s) { return output; } -// ASCII-specific toupper. The standard library's toupper is locale sensitive, -// so we don't want to use it here. -template inline Char ToUpperASCII(Char c) { - return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; -} - // Converts the elements of the given string. This version uses a pointer to // clearly differentiate it from the non-pointer variant. template inline void StringToUpperASCII(str* s) { for (typename str::iterator i = s->begin(); i != s->end(); ++i) - *i = ToUpperASCII(*i); + *i = base::ToUpperASCII(*i); } template inline str StringToUpperASCII(const str& s) { @@ -486,7 +486,6 @@ inline typename string_type::value_type* WriteInto(string_type* str, //----------------------------------------------------------------------------- - // Splits a string into its fields delimited by any of the characters in // |delimiters|. Each field is added to the |tokens| vector. Returns the // number of tokens found. @@ -507,21 +506,6 @@ size_t Tokenize(const base::StringPiece& str, string16 JoinString(const std::vector& parts, char16 s); std::string JoinString(const std::vector& parts, char s); -// WARNING: this uses whitespace as defined by the HTML5 spec. If you need -// a function similar to this but want to trim all types of whitespace, then -// factor this out into a function that takes a string containing the characters -// that are treated as whitespace. -// -// Splits the string along whitespace (where whitespace is the five space -// characters defined by HTML 5). Each contiguous block of non-whitespace -// characters is added to result. -void SplitStringAlongWhitespace(const std::wstring& str, - std::vector* result); -void SplitStringAlongWhitespace(const string16& str, - std::vector* result); -void SplitStringAlongWhitespace(const std::string& str, - std::vector* result); - // Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. // Additionally, any number of consecutive '$' characters is replaced by that // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be diff --git a/base/string_util_unittest.cc b/base/string_util_unittest.cc index 0f7d79d..b7639bb 100644 --- a/base/string_util_unittest.cc +++ b/base/string_util_unittest.cc @@ -925,38 +925,6 @@ TEST(StringUtilTest, ReplaceStringPlaceholdersConsecutiveDollarSigns) { "$1 $$2 $$$3"); } -TEST(StringUtilTest, SplitStringAlongWhitespace) { - struct TestData { - const std::wstring input; - const size_t expected_result_count; - const std::wstring output1; - const std::wstring output2; - } data[] = { - { L"a", 1, L"a", L"" }, - { L" ", 0, L"", L"" }, - { L" a", 1, L"a", L"" }, - { L" ab ", 1, L"ab", L"" }, - { L" ab c", 2, L"ab", L"c" }, - { L" ab c ", 2, L"ab", L"c" }, - { L" ab cd", 2, L"ab", L"cd" }, - { L" ab cd ", 2, L"ab", L"cd" }, - { L" \ta\t", 1, L"a", L"" }, - { L" b\ta\t", 2, L"b", L"a" }, - { L" b\tat", 2, L"b", L"at" }, - { L"b\tat", 2, L"b", L"at" }, - { L"b\t at", 2, L"b", L"at" }, - }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { - std::vector results; - SplitStringAlongWhitespace(data[i].input, &results); - ASSERT_EQ(data[i].expected_result_count, results.size()); - if (data[i].expected_result_count > 0) - ASSERT_EQ(data[i].output1, results[0]); - if (data[i].expected_result_count > 1) - ASSERT_EQ(data[i].output2, results[1]); - } -} - TEST(StringUtilTest, MatchPatternTest) { EXPECT_TRUE(MatchPattern("www.google.com", "*.com")); EXPECT_TRUE(MatchPattern("www.google.com", "*")); diff --git a/base/stringize_macros.h b/base/stringize_macros.h new file mode 100644 index 0000000..7c3af49 --- /dev/null +++ b/base/stringize_macros.h @@ -0,0 +1,57 @@ +// 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. +// +// This file defines preprocessor macros for stringizing preprocessor +// symbols (or their output) and manipulating preprocessor symbols +// that define strings. + +#ifndef BASE_STRINGIZE_MACROS_H_ +#define BASE_STRINGIZE_MACROS_H_ +#pragma once + +#include "build/build_config.h" + +// This is not very useful as it does not expand defined symbols if +// called directly. Use its counterpart without the _NO_EXPANSION +// suffix, below. +#define STRINGIZE_NO_EXPANSION(x) #x + +// Use this to quote the provided parameter, first expanding it if it +// is a preprocessor symbol. +// +// For example, if: +// #define A FOO +// #define B(x) myobj->FunctionCall(x) +// +// Then: +// STRINGIZE(A) produces "FOO" +// STRINGIZE(B(y)) produces "myobj->FunctionCall(y)" +#define STRINGIZE(x) STRINGIZE_NO_EXPANSION(x) + +// The following are defined only on Windows (for use when interacting +// with Windows APIs) as wide strings are otherwise deprecated. +#if defined(OS_WIN) + +// Second-level utility macros to let us expand symbols. +#define LSTRINGIZE_NO_EXPANSION(x) L ## #x +#define TO_L_STRING_NO_EXPANSION(x) L ## x + +// L version of STRINGIZE(). For examples above, +// LSTRINGIZE(A) produces L"FOO" +// LSTRINGIZE(B(y)) produces L"myobj->FunctionCall(y)" +#define LSTRINGIZE(x) LSTRINGIZE_NO_EXPANSION(x) + +// Adds an L in front of an existing ASCII string constant (after +// expanding symbols). Does not do any quoting. +// +// For example, if: +// #define C "foo" +// +// Then: +// TO_L_STRING(C) produces L"foo" +#define TO_L_STRING(x) TO_L_STRING_NO_EXPANSION(x) + +#endif // defined(OS_WIN) + +#endif // BASE_STRINGIZE_MACROS_H_ diff --git a/base/stringize_macros_unittest.cc b/base/stringize_macros_unittest.cc new file mode 100644 index 0000000..8d92d53 --- /dev/null +++ b/base/stringize_macros_unittest.cc @@ -0,0 +1,59 @@ +// 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. +// +// Unit tests for stringize_macros.h + +#include "base/stringize_macros.h" + +#include "testing/gtest/include/gtest/gtest.h" + +// Macros as per documentation in header file. +#define PREPROCESSOR_UTIL_UNITTEST_A FOO +#define PREPROCESSOR_UTIL_UNITTEST_B(x) myobj->FunctionCall(x) +#define PREPROCESSOR_UTIL_UNITTEST_C "foo" + +TEST(StringizeTest, Ansi) { + EXPECT_STREQ( + "PREPROCESSOR_UTIL_UNITTEST_A", + STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_A)); + EXPECT_STREQ( + "PREPROCESSOR_UTIL_UNITTEST_B(y)", + STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_B(y))); + EXPECT_STREQ( + "PREPROCESSOR_UTIL_UNITTEST_C", + STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_C)); + + EXPECT_STREQ("FOO", STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_A)); + EXPECT_STREQ("myobj->FunctionCall(y)", + STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_B(y))); + EXPECT_STREQ("\"foo\"", STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_C)); +} + +#if defined(OS_WIN) + +TEST(StringizeTest, Wide) { + EXPECT_STREQ( + L"PREPROCESSOR_UTIL_UNITTEST_A", + LSTRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_A)); + EXPECT_STREQ( + L"PREPROCESSOR_UTIL_UNITTEST_B(y)", + LSTRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_B(y))); + EXPECT_STREQ( + L"PREPROCESSOR_UTIL_UNITTEST_C", + LSTRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_C)); + + EXPECT_STREQ(L"FOO", LSTRINGIZE(PREPROCESSOR_UTIL_UNITTEST_A)); + EXPECT_STREQ(L"myobj->FunctionCall(y)", + LSTRINGIZE(PREPROCESSOR_UTIL_UNITTEST_B(y))); + EXPECT_STREQ(L"\"foo\"", LSTRINGIZE(PREPROCESSOR_UTIL_UNITTEST_C)); +} + +TEST(ToLStringTest, Main) { + EXPECT_STREQ(L"blat", TO_L_STRING_NO_EXPANSION("blat")); + + EXPECT_STREQ(L"foo", TO_L_STRING(PREPROCESSOR_UTIL_UNITTEST_C)); + EXPECT_STREQ(L"blat", TO_L_STRING("blat")); +} + +#endif // defined(OS_WIN) diff --git a/base/stringprintf.h b/base/stringprintf.h index 3608f9d..f3ca6e7 100644 --- a/base/stringprintf.h +++ b/base/stringprintf.h @@ -50,7 +50,5 @@ void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) // TODO(brettw) remove these when calling code is converted. using base::StringPrintf; using base::StringAppendV; -using base::StringAppendF; -using base::StringAppendV; #endif // BASE_STRINGPRINTF_H_ diff --git a/base/thread_local.h b/base/thread_local.h index 075e209..eba48d2 100644 --- a/base/thread_local.h +++ b/base/thread_local.h @@ -57,6 +57,8 @@ namespace base { +namespace internal { + // Helper functions that abstract the cross-platform APIs. Do not use directly. struct ThreadLocalPlatform { #if defined(OS_WIN) @@ -71,27 +73,30 @@ struct ThreadLocalPlatform { static void SetValueInSlot(SlotType& slot, void* value); }; +} // namespace internal + template class ThreadLocalPointer { public: ThreadLocalPointer() : slot_() { - ThreadLocalPlatform::AllocateSlot(slot_); + internal::ThreadLocalPlatform::AllocateSlot(slot_); } ~ThreadLocalPointer() { - ThreadLocalPlatform::FreeSlot(slot_); + internal::ThreadLocalPlatform::FreeSlot(slot_); } Type* Get() { - return static_cast(ThreadLocalPlatform::GetValueFromSlot(slot_)); + return static_cast( + internal::ThreadLocalPlatform::GetValueFromSlot(slot_)); } void Set(Type* ptr) { - ThreadLocalPlatform::SetValueInSlot(slot_, ptr); + internal::ThreadLocalPlatform::SetValueInSlot(slot_, ptr); } private: - typedef ThreadLocalPlatform::SlotType SlotType; + typedef internal::ThreadLocalPlatform::SlotType SlotType; SlotType slot_; diff --git a/base/thread_local_posix.cc b/base/thread_local_posix.cc index 2abfc0e..4d03403 100644 --- a/base/thread_local_posix.cc +++ b/base/thread_local_posix.cc @@ -10,6 +10,8 @@ namespace base { +namespace internal { + // static void ThreadLocalPlatform::AllocateSlot(SlotType& slot) { int error = pthread_key_create(&slot, NULL); @@ -33,4 +35,6 @@ void ThreadLocalPlatform::SetValueInSlot(SlotType& slot, void* value) { CHECK_EQ(error, 0); } +} // namespace internal + } // namespace base diff --git a/base/thread_local_win.cc b/base/thread_local_win.cc index 368c0d6..ea14a67 100644 --- a/base/thread_local_win.cc +++ b/base/thread_local_win.cc @@ -10,6 +10,8 @@ namespace base { +namespace internal { + // static void ThreadLocalPlatform::AllocateSlot(SlotType& slot) { slot = TlsAlloc(); @@ -35,4 +37,6 @@ void ThreadLocalPlatform::SetValueInSlot(SlotType& slot, void* value) { } } +} // namespace internal + } // namespace base diff --git a/base/time_mac.cc b/base/time_mac.cc index 6dfaa20..ad31410 100644 --- a/base/time_mac.cc +++ b/base/time_mac.cc @@ -80,8 +80,8 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { void Time::Explode(bool is_local, Exploded* exploded) const { CFAbsoluteTime seconds = - (static_cast((us_ - kWindowsEpochDeltaMicroseconds) / - kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970); + ((static_cast(us_) - kWindowsEpochDeltaMicroseconds) / + kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970; base::mac::ScopedCFTypeRef time_zone(is_local ? CFTimeZoneCopySystem() : NULL); diff --git a/base/time_unittest.cc b/base/time_unittest.cc index 21e6f89..6ddf4d3 100644 --- a/base/time_unittest.cc +++ b/base/time_unittest.cc @@ -52,6 +52,19 @@ TEST(Time, TimeT) { EXPECT_EQ(0, Time::FromTimeT(0).ToInternalValue()); } +TEST(Time, FromExplodedWithMilliseconds) { + // Some platform implementations of FromExploded are liable to drop + // milliseconds if we aren't careful. + Time now = Time::NowFromSystemTime(); + Time::Exploded exploded1 = {0}; + now.UTCExplode(&exploded1); + exploded1.millisecond = 500; + Time time = Time::FromUTCExploded(exploded1); + Time::Exploded exploded2 = {0}; + time.UTCExplode(&exploded2); + EXPECT_EQ(exploded1.millisecond, exploded2.millisecond); +} + TEST(Time, ZeroIsSymmetric) { Time zero_time(Time::FromTimeT(0)); EXPECT_EQ(0, zero_time.ToTimeT()); diff --git a/base/tuple.h b/base/tuple.h index b67d924..bfe6562 100644 --- a/base/tuple.h +++ b/base/tuple.h @@ -544,6 +544,13 @@ inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& arg) { + +#if defined(OS_CHROMEOS) && defined(CHECK) + // To troubleshoot crosbug.com/7327. + CHECK(obj); + CHECK(&arg); + CHECK(method); +#endif (obj->*method)(arg.a); } diff --git a/base/version.cc b/base/version.cc index 9fbcb6a..fe224eb 100644 --- a/base/version.cc +++ b/base/version.cc @@ -63,8 +63,8 @@ int Version::CompareTo(const Version& other) const { const std::string Version::GetString() const { DCHECK(is_valid_); std::string version_str; - int count = components_.size(); - for (int i = 0; i < count - 1; ++i) { + size_t count = components_.size(); + for (size_t i = 0; i < count - 1; ++i) { version_str.append(base::IntToString(components_[i])); version_str.append("."); } diff --git a/base/win/i18n.cc b/base/win/i18n.cc new file mode 100644 index 0000000..59480f2 --- /dev/null +++ b/base/win/i18n.cc @@ -0,0 +1,169 @@ +// 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 "base/win/i18n.h" + +#include + +#include "base/logging.h" + +namespace { + +// Keep this enum in sync with kLanguageFunctionNames. +enum LanguageFunction { + SYSTEM_LANGUAGES, + USER_LANGUAGES, + PROCESS_LANGUAGES, + THREAD_LANGUAGES, + NUM_FUNCTIONS +}; + +const char kSystemLanguagesFunctionName[] = "GetSystemPreferredUILanguages"; +const char kUserLanguagesFunctionName[] = "GetUserPreferredUILanguages"; +const char kProcessLanguagesFunctionName[] = "GetProcessPreferredUILanguages"; +const char kThreadLanguagesFunctionName[] = "GetThreadPreferredUILanguages"; + +// Keep this array in sync with enum LanguageFunction. +const char *const kLanguageFunctionNames[] = { + &kSystemLanguagesFunctionName[0], + &kUserLanguagesFunctionName[0], + &kProcessLanguagesFunctionName[0], + &kThreadLanguagesFunctionName[0] +}; + +COMPILE_ASSERT(NUM_FUNCTIONS == arraysize(kLanguageFunctionNames), + language_function_enum_and_names_out_of_sync); + +// Calls one of the MUI Get*PreferredUILanguages functions, placing the result +// in |languages|. |function| identifies the function to call and |flags| is +// the function-specific flags (callers must not specify MUI_LANGUAGE_ID or +// MUI_LANGUAGE_NAME). Returns true if at least one language is placed in +// |languages|. +bool GetMUIPreferredUILanguageList(LanguageFunction function, ULONG flags, + std::vector* languages) { + DCHECK(0 <= function && NUM_FUNCTIONS > function); + DCHECK_EQ(0U, (flags & (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME))); + DCHECK(languages); + + HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); + if (NULL != kernel32) { + typedef BOOL (WINAPI* GetPreferredUILanguages_Fn)( + DWORD, PULONG, PZZWSTR, PULONG); + GetPreferredUILanguages_Fn get_preferred_ui_languages = + reinterpret_cast( + GetProcAddress(kernel32, kLanguageFunctionNames[function])); + if (NULL != get_preferred_ui_languages) { + const ULONG call_flags = flags | MUI_LANGUAGE_NAME; + ULONG language_count = 0; + ULONG buffer_length = 0; + if (get_preferred_ui_languages(call_flags, &language_count, NULL, + &buffer_length) && + 0 != buffer_length) { + languages->resize(buffer_length); + if (get_preferred_ui_languages(call_flags, &language_count, + &(*languages)[0], &buffer_length) && + 0 != language_count) { + DCHECK(languages->size() == buffer_length); + return true; + } else { + DPCHECK(0 == language_count) + << "Failed getting preferred UI languages."; + } + } else { + DPCHECK(0 == buffer_length) + << "Failed getting size of preferred UI languages."; + } + } else { + VLOG(2) << "MUI not available."; + } + } else { + NOTREACHED() << "kernel32.dll not found."; + } + + return false; +} + +bool GetUserDefaultUILanguage(std::wstring* language, std::wstring* region) { + DCHECK(language); + + LANGID lang_id = ::GetUserDefaultUILanguage(); + if (LOCALE_CUSTOM_UI_DEFAULT != lang_id) { + const LCID locale_id = MAKELCID(lang_id, SORT_DEFAULT); + // max size for LOCALE_SISO639LANGNAME and LOCALE_SISO3166CTRYNAME is 9 + wchar_t result_buffer[9]; + int result_length = + GetLocaleInfo(locale_id, LOCALE_SISO639LANGNAME, &result_buffer[0], + arraysize(result_buffer)); + DPCHECK(0 != result_length) << "Failed getting language id"; + if (1 < result_length) { + language->assign(&result_buffer[0], result_length - 1); + region->clear(); + if (SUBLANG_NEUTRAL != SUBLANGID(lang_id)) { + result_length = + GetLocaleInfo(locale_id, LOCALE_SISO3166CTRYNAME, &result_buffer[0], + arraysize(result_buffer)); + DPCHECK(0 != result_length) << "Failed getting region id"; + if (1 < result_length) + region->assign(&result_buffer[0], result_length - 1); + } + return true; + } + } else { + // This is entirely unexpected on pre-Vista, which is the only time we + // should try GetUserDefaultUILanguage anyway. + NOTREACHED() << "Cannot determine language for a supplemental locale."; + } + return false; +} + +bool GetPreferredUILanguageList(LanguageFunction function, ULONG flags, + std::vector* languages) { + std::vector buffer; + std::wstring language; + std::wstring region; + + if (GetMUIPreferredUILanguageList(function, flags, &buffer)) { + std::vector::const_iterator scan = buffer.begin(); + language.assign(&*scan); + while (!language.empty()) { + languages->push_back(language); + scan += language.size() + 1; + language.assign(&*scan); + } + } else if (GetUserDefaultUILanguage(&language, ®ion)) { + // Mimic the MUI behavior of putting the neutral version of the lang after + // the regional one (e.g., "fr-CA, fr"). + if (!region.empty()) + languages->push_back(std::wstring(language) + .append(1, L'-') + .append(region)); + languages->push_back(language); + } else { + return false; + } + + return true; +} + +} // namespace + +namespace base { +namespace win { +namespace i18n { + +bool GetUserPreferredUILanguageList(std::vector* languages) { + DCHECK(languages); + return GetPreferredUILanguageList(USER_LANGUAGES, 0, languages); +} + +bool GetThreadPreferredUILanguageList(std::vector* languages) { + DCHECK(languages); + return GetPreferredUILanguageList( + THREAD_LANGUAGES, MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK, + languages); +} + +} // namespace i18n +} // namespace win +} // namespace base diff --git a/base/win/i18n.h b/base/win/i18n.h new file mode 100644 index 0000000..ba0f74d --- /dev/null +++ b/base/win/i18n.h @@ -0,0 +1,32 @@ +// 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 BASE_WIN_I18N_H_ +#define BASE_WIN_I18N_H_ +#pragma once + +#include +#include + +#include "base/basictypes.h" + +namespace base { +namespace win { +namespace i18n { + +// Adds to |languages| the list of user preferred UI languages from MUI, if +// available, falling-back on the user default UI language otherwise. Returns +// true if at least one language is added. +bool GetUserPreferredUILanguageList(std::vector* languages); + +// Adds to |languages| the list of thread, process, user, and system preferred +// UI languages from MUI, if available, falling-back on the user default UI +// language otherwise. Returns true if at least one language is added. +bool GetThreadPreferredUILanguageList(std::vector* languages); + +} // namespace i18n +} // namespace win +} // namespace base + +#endif // BASE_WIN_I18N_H_ diff --git a/base/win/i18n_unittest.cc b/base/win/i18n_unittest.cc new file mode 100644 index 0000000..781fc39 --- /dev/null +++ b/base/win/i18n_unittest.cc @@ -0,0 +1,42 @@ +// 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. + +// This file contains unit tests for Windows internationalization funcs. + +#include "testing/gtest/include/gtest/gtest.h" + +#include "base/win/i18n.h" +#include "base/win/windows_version.h" + +namespace base { +namespace win { +namespace i18n { + +// Tests that at least one user preferred UI language can be obtained. +TEST(I18NTest, GetUserPreferredUILanguageList) { + std::vector languages; + EXPECT_TRUE(GetUserPreferredUILanguageList(&languages)); + EXPECT_NE(static_cast::size_type>(0), + languages.size()); + for (std::vector::const_iterator scan = languages.begin(), + end = languages.end(); scan != end; ++scan) { + EXPECT_FALSE((*scan).empty()); + } +} + +// Tests that at least one thread preferred UI language can be obtained. +TEST(I18NTest, GetThreadPreferredUILanguageList) { + std::vector languages; + EXPECT_TRUE(GetThreadPreferredUILanguageList(&languages)); + EXPECT_NE(static_cast::size_type>(0), + languages.size()); + for (std::vector::const_iterator scan = languages.begin(), + end = languages.end(); scan != end; ++scan) { + EXPECT_FALSE((*scan).empty()); + } +} + +} // namespace i18n +} // namespace win +} // namespace base diff --git a/build/all.gyp b/build/all.gyp index 87fe78f..19fd005 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -43,6 +43,7 @@ '../third_party/modp_b64/modp_b64.gyp:*', '../third_party/npapi/npapi.gyp:*', '../third_party/ots/ots.gyp:*', + '../third_party/qcms/qcms.gyp:*', '../third_party/sqlite/sqlite.gyp:*', '../third_party/WebKit/WebKit/chromium/WebKit.gyp:*', '../third_party/zlib/zlib.gyp:*', diff --git a/build/build_config.h b/build/build_config.h index 1e9745f..9597eb4 100644 --- a/build/build_config.h +++ b/build/build_config.h @@ -17,6 +17,8 @@ // A set of macros to use for platform detection. #if defined(__APPLE__) #define OS_MACOSX 1 +#elif defined(__native_client__) +#define OS_NACL 1 #elif defined(__linux__) #define OS_LINUX 1 // Use TOOLKIT_GTK on linux if TOOLKIT_VIEWS isn't defined. @@ -66,7 +68,11 @@ // For access to standard POSIXish features, use OS_POSIX instead of a // more specific macro. #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ +<<<<<<< HEAD defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(ANDROID) +======= + defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_NACL) +>>>>>>> chromium.org at r66597 #define OS_POSIX 1 // Use base::DataPack for name/value pairs. #define USE_BASE_DATA_PACK 1 diff --git a/build/common.gypi b/build/common.gypi index 97863a9..abfe14c 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -314,6 +314,9 @@ # whether to compile in the sources for the GPU plugin / process. 'enable_gpu%': 1, + # Use GConf, the GNOME configuration system. + 'use_gconf%': 1, + # Use OpenSSL instead of NSS. Currently in development. 'use_openssl%': 0, @@ -612,31 +615,31 @@ ], 'conditions': [ ['OS!="win"', { - 'sources/': [ ['exclude', '_win(_unittest)?\\.cc$'], - ['exclude', '/win/'], - ['exclude', '/win_[^/]*\\.cc$'] ], + 'sources/': [ ['exclude', '_win(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)win/'], + ['exclude', '(^|/)win_[^/]*\\.(h|cc)$'] ], }], ['OS!="mac"', { - 'sources/': [ ['exclude', '_(cocoa|mac)(_unittest)?\\.cc$'], - ['exclude', '/(cocoa|mac)/'], - ['exclude', '\.mm?$' ] ], + 'sources/': [ ['exclude', '_(cocoa|mac)(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)(cocoa|mac)/'], + ['exclude', '\\.mm?$' ] ], }], ['OS!="linux" and OS!="freebsd" and OS!="openbsd"', { 'sources/': [ - ['exclude', '_(chromeos|gtk|x|x11|xdg)(_unittest)?\\.cc$'], - ['exclude', '/gtk/'], - ['exclude', '/(gtk|x11)_[^/]*\\.cc$'], + ['exclude', '_(chromeos|gtk|x|x11|xdg)(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)gtk/'], + ['exclude', '(^|/)(gtk|x11)_[^/]*\\.(h|cc)$'], ], }], ['OS!="linux"', { 'sources/': [ - ['exclude', '_linux(_unittest)?\\.cc$'], - ['exclude', '/linux/'], + ['exclude', '_linux(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)linux/'], ], }], # We use "POSIX" to refer to all non-Windows operating systems. ['OS=="win"', { - 'sources/': [ ['exclude', '_posix\\.cc$'] ], + 'sources/': [ ['exclude', '_posix\\.(h|cc)$'] ], # turn on warnings for signed/unsigned mismatch on chromium code. 'msvs_settings': { 'VCCLCompilerTool': { @@ -645,10 +648,10 @@ }, }], ['chromeos!=1', { - 'sources/': [ ['exclude', '_chromeos\\.cc$'] ] + 'sources/': [ ['exclude', '_chromeos\\.(h|cc)$'] ] }], ['toolkit_views==0', { - 'sources/': [ ['exclude', '_views\\.cc$'] ] + 'sources/': [ ['exclude', '_views\\.(h|cc)$'] ] }], ], }], @@ -1165,9 +1168,6 @@ # http://code.google.com/p/googletest/source/detail?r=446 . # TODO(thakis): Use -isystem instead (http://crbug.com/58751 ). '-Wno-unnamed-type-template-args', - # The integrated assembler chokes on one ffmpeg file. - # http://crbug.com/61931 - '-no-integrated-as', ], 'cflags!': [ # Clang doesn't seem to know know this flag. diff --git a/build/linux/pkg-config-wrapper b/build/linux/pkg-config-wrapper index fa76c2e..d94b997 100755 --- a/build/linux/pkg-config-wrapper +++ b/build/linux/pkg-config-wrapper @@ -11,4 +11,6 @@ rewrite=`dirname $0`/rewrite_dirs.py shift config_path=$root/usr/lib/pkgconfig:$root/usr/share/pkgconfig -PKG_CONFIG_PATH=$config_path pkg-config --define-variable=prefix=/usr "$@" | $rewrite $root +set -e +result=`PKG_CONFIG_PATH=$config_path pkg-config --define-variable=prefix=/usr "$@"` +echo "$result"| $rewrite $root diff --git a/build/linux/system.gyp b/build/linux/system.gyp index ed88a0a..59cf486 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp @@ -188,11 +188,14 @@ 'target_name': 'gconf', 'type': 'settings', 'conditions': [ - ['_toolset=="target"', { + ['use_gconf==1 and _toolset=="target"', { 'direct_dependent_settings': { 'cflags': [ '* result) { + DCHECK(prefs); + DCHECK(result); + if (prefs->GetBoolean(prefs::kLabsMediaplayerEnabled)) + result->insert(kMediaPlayerExperimentName); + if (prefs->GetBoolean(prefs::kLabsAdvancedFilesystemEnabled)) + result->insert(kAdvancedFileSystemExperimentName); + if (prefs->GetBoolean(prefs::kUseVerticalTabs)) + result->insert(kVerticalTabsExperimentName); + prefs->SetBoolean(prefs::kLabsMediaplayerEnabled, false); + prefs->SetBoolean(prefs::kLabsAdvancedFilesystemEnabled, false); + prefs->SetBoolean(prefs::kUseVerticalTabs, false); +} +#endif + // Extracts the list of enabled lab experiments from preferences and stores them // in a set. void GetEnabledFlags(const PrefService* prefs, std::set* result) { @@ -366,6 +427,13 @@ void FlagsState::ConvertFlagsToSwitches( return; std::set enabled_experiments; + +#if defined(OS_CHROMEOS) + // Some experiments were implemented via prefs on Chrome OS and we want to + // seamlessly migrate these prefs to about:flags for updated users. + MigrateChromeOSLabsPrefs(prefs, &enabled_experiments); +#endif + GetSanitizedEnabledFlagsForCurrentPlatform(prefs, &enabled_experiments); std::map experiment_map; diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc index 6d86cc9..f6b5193 100644 --- a/chrome/browser/about_flags_unittest.cc +++ b/chrome/browser/about_flags_unittest.cc @@ -52,6 +52,11 @@ class AboutFlagsTest : public ::testing::Test { protected: AboutFlagsTest() { prefs_.RegisterListPref(prefs::kEnabledLabsExperiments); +#if defined(OS_CHROMEOS) + prefs_.RegisterBooleanPref(prefs::kLabsMediaplayerEnabled, false); + prefs_.RegisterBooleanPref(prefs::kLabsAdvancedFilesystemEnabled, false); + prefs_.RegisterBooleanPref(prefs::kUseVerticalTabs, false); +#endif testing::ClearState(); } diff --git a/chrome/browser/accessibility/accessibility_win_browsertest.cc b/chrome/browser/accessibility/accessibility_win_browsertest.cc index 9d97988..7dd669c 100644 --- a/chrome/browser/accessibility/accessibility_win_browsertest.cc +++ b/chrome/browser/accessibility/accessibility_win_browsertest.cc @@ -7,11 +7,11 @@ #include "base/scoped_comptr_win.h" #include "chrome/browser/automation/ui_controls.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view_win.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_type.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/accessibility/browser_accessibility_win.cc b/chrome/browser/accessibility/browser_accessibility_win.cc index 442d644..011ed86 100644 --- a/chrome/browser/accessibility/browser_accessibility_win.cc +++ b/chrome/browser/accessibility/browser_accessibility_win.cc @@ -25,7 +25,11 @@ BrowserAccessibilityWin* BrowserAccessibility::toBrowserAccessibilityWin() { } BrowserAccessibilityWin::BrowserAccessibilityWin() - : instance_active_(false) { + : instance_active_(false), + ia_role_(0), + ia_state_(0), + ia2_role_(0), + ia2_state_(0) { } BrowserAccessibilityWin::~BrowserAccessibilityWin() { diff --git a/chrome/browser/accessibility/browser_accessibility_win.h b/chrome/browser/accessibility/browser_accessibility_win.h index 6352b98..214f0c0 100644 --- a/chrome/browser/accessibility/browser_accessibility_win.h +++ b/chrome/browser/accessibility/browser_accessibility_win.h @@ -486,8 +486,8 @@ class BrowserAccessibilityWin bool instance_active_; // IAccessible role and state. - int32 ia_state_; int32 ia_role_; + int32 ia_state_; // IAccessible2 role and state. int32 ia2_role_; diff --git a/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc b/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc index 1b5f33b..d0c08c1 100644 --- a/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc +++ b/chrome/browser/accessibility/browser_views_accessibility_browsertest.cc @@ -7,8 +7,8 @@ #include "app/l10n_util.h" #include "base/scoped_comptr_win.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/frame/browser_view.h" diff --git a/chrome/browser/aeropeek_manager.cc b/chrome/browser/aeropeek_manager.cc index d1837d7..34cb3da 100644 --- a/chrome/browser/aeropeek_manager.cc +++ b/chrome/browser/aeropeek_manager.cc @@ -982,7 +982,10 @@ HICON AeroPeekWindow::OnGetIcon(UINT index) { } AeroPeekManager::AeroPeekManager(HWND application_window) - : application_window_(application_window) { + : application_window_(application_window), + border_left_(0), + border_top_(0), + toolbar_top_(0) { } AeroPeekManager::~AeroPeekManager() { diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 6c8a9f1..2285aea 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -16,7 +16,6 @@ #import "base/worker_pool_mac.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser.h" -#include "chrome/browser/browser_init.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" @@ -48,6 +47,7 @@ #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/sync/sync_ui_util_mac.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser_init.h" #include "chrome/common/app_mode_common_mac.h" #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc index 007fd2b..8c47a69 100644 --- a/chrome/browser/autocomplete/autocomplete.cc +++ b/chrome/browser/autocomplete/autocomplete.cc @@ -46,6 +46,7 @@ AutocompleteInput::AutocompleteInput() : type_(INVALID), prevent_inline_autocomplete_(false), prefer_keyword_(false), + allow_exact_keyword_match_(true), synchronous_only_(false) { } @@ -53,10 +54,12 @@ AutocompleteInput::AutocompleteInput(const std::wstring& text, const std::wstring& desired_tld, bool prevent_inline_autocomplete, bool prefer_keyword, + bool allow_exact_keyword_match, bool synchronous_only) : desired_tld_(desired_tld), prevent_inline_autocomplete_(prevent_inline_autocomplete), prefer_keyword_(prefer_keyword), + allow_exact_keyword_match_(allow_exact_keyword_match), synchronous_only_(synchronous_only) { // Trim whitespace from edges of input; don't inline autocomplete if there // was trailing whitespace. @@ -671,11 +674,12 @@ void AutocompleteController::Start(const std::wstring& text, const std::wstring& desired_tld, bool prevent_inline_autocomplete, bool prefer_keyword, + bool allow_exact_keyword_match, bool synchronous_only) { const std::wstring old_input_text(input_.text()); const bool old_synchronous_only = input_.synchronous_only(); input_ = AutocompleteInput(text, desired_tld, prevent_inline_autocomplete, - prefer_keyword, synchronous_only); + prefer_keyword, allow_exact_keyword_match, synchronous_only); // See if we can avoid rerunning autocomplete when the query hasn't changed // much. When the user presses or releases the ctrl key, the desired_tld diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h index 25c8341..53fd392 100644 --- a/chrome/browser/autocomplete/autocomplete.h +++ b/chrome/browser/autocomplete/autocomplete.h @@ -42,10 +42,11 @@ // --------------------------------------------------------------------|----- // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 // HistoryURL (exact or inline autocomplete match) | 1400 +// Search Primary Provider (past query in history within 2 days) | 1399** // Search Primary Provider (what you typed) | 1300 // HistoryURL (what you typed) | 1200 // Keyword (substituting, exact match) | 1100 -// Search Primary Provider (past query in history) | 1050-- +// Search Primary Provider (past query in history older than 2 days) | 1050-- // HistoryContents (any match in title of starred page) | 1000++ // HistoryURL (inexact match) | 900++ // Search Primary Provider (navigational suggestion) | 800++ @@ -63,10 +64,11 @@ // --------------------------------------------------------------------|----- // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 // HistoryURL (exact or inline autocomplete match) | 1400 +// Search Primary Provider (past query in history within 2 days) | 1399** // HistoryURL (what you typed) | 1200 // Search Primary Provider (what you typed) | 1150 // Keyword (substituting, exact match) | 1100 -// Search Primary Provider (past query in history) | 1050-- +// Search Primary Provider (past query in history older than 2 days) | 1050-- // HistoryContents (any match in title of starred page) | 1000++ // HistoryURL (inexact match) | 900++ // Search Primary Provider (navigational suggestion) | 800++ @@ -102,8 +104,9 @@ // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 // Keyword (substituting, exact match) | 1450 // HistoryURL (exact or inline autocomplete match) | 1400 +// Search Primary Provider (past query in history within 2 days) | 1399** // Search Primary Provider (what you typed) | 1300 -// Search Primary Provider (past query in history) | 1050-- +// Search Primary Provider (past query in history older than 2 days) | 1050-- // HistoryContents (any match in title of starred page) | 1000++ // HistoryURL (inexact match) | 900++ // Search Primary Provider (navigational suggestion) | 800++ @@ -119,8 +122,9 @@ // // FORCED_QUERY input type: // --------------------------------------------------------------------|----- +// Search Primary Provider (past query in history within 2 days) | 1399** // Search Primary Provider (what you typed) | 1300 -// Search Primary Provider (past query in history) | 1050-- +// Search Primary Provider (past query in history older than 2 days) | 1050-- // HistoryContents (any match in title of starred page) | 1000++ // Search Primary Provider (navigational suggestion) | 800++ // HistoryContents (any match in title of nonstarred page) | 700++ @@ -140,6 +144,8 @@ // ++: a series of matches with relevance from n up to (n + max_matches). // --: relevance score falls off over time (discounted 50 points @ 15 minutes, // 450 points @ two weeks) +// --: relevance score falls off over two days (discounted 99 points after two +// days). class AutocompleteInput; struct AutocompleteMatch; @@ -177,6 +183,7 @@ class AutocompleteInput { const std::wstring& desired_tld, bool prevent_inline_autocomplete, bool prefer_keyword, + bool allow_exact_keyword_match, bool synchronous_only); ~AutocompleteInput(); @@ -246,6 +253,11 @@ class AutocompleteInput { // keyword, we should score it like a non-substituting keyword. bool prefer_keyword() const { return prefer_keyword_; } + // Returns whether this input is allowed to be treated as an exact + // keyword match. If not, the default result is guaranteed not to be a + // keyword search, even if the input is " ". + bool allow_exact_keyword_match() const { return allow_exact_keyword_match_; } + // Returns whether providers should avoid scheduling asynchronous work. If // this is true, providers should stop after returning all the // synchronously-available matches. This also means any in-progress @@ -267,6 +279,7 @@ class AutocompleteInput { GURL canonicalized_url_; bool prevent_inline_autocomplete_; bool prefer_keyword_; + bool allow_exact_keyword_match_; bool synchronous_only_; }; @@ -544,6 +557,10 @@ class AutocompleteController : public ACProviderListener { // bias the autocomplete result set toward the keyword provider when the input // string is a bare keyword. // + // |allow_exact_keyword_match| should be false when triggering keyword mode on + // the input string would be surprising or wrong, e.g. when highlighting text + // in a page and telling the browser to search for it or navigate to it. + // If |synchronous_only| is true, the controller asks the providers to only // return matches which are synchronously available, which should mean that // all providers will be done immediately. @@ -559,6 +576,7 @@ class AutocompleteController : public ACProviderListener { const std::wstring& desired_tld, bool prevent_inline_autocomplete, bool prefer_keyword, + bool allow_exact_keyword_match, bool synchronous_only); // Cancels the current query, ensuring there will be no future notifications diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc index 877fe7a..2828353 100644 --- a/chrome/browser/autocomplete/autocomplete_browsertest.cc +++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc @@ -9,13 +9,13 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/history/history.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_type.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" @@ -107,7 +107,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteBrowserTest, MAYBE_Autocomplete) { { autocomplete_controller->Start(L"chrome", std::wstring(), - true, false, true); + true, false, true, true); EXPECT_TRUE(autocomplete_controller->done()); EXPECT_EQ(std::wstring(), location_bar->GetInputString()); diff --git a/chrome/browser/autocomplete/autocomplete_classifier.cc b/chrome/browser/autocomplete/autocomplete_classifier.cc index 88dc89c..45635e3 100644 --- a/chrome/browser/autocomplete/autocomplete_classifier.cc +++ b/chrome/browser/autocomplete/autocomplete_classifier.cc @@ -17,9 +17,11 @@ AutocompleteClassifier::~AutocompleteClassifier() { void AutocompleteClassifier::Classify(const std::wstring& text, const std::wstring& desired_tld, + bool allow_exact_keyword_match, AutocompleteMatch* match, GURL* alternate_nav_url) { - controller_->Start(text, desired_tld, true, false, true); + controller_->Start(text, desired_tld, true, false, allow_exact_keyword_match, + true); DCHECK(controller_->done()); const AutocompleteResult& result = controller_->result(); if (result.empty()) { diff --git a/chrome/browser/autocomplete/autocomplete_classifier.h b/chrome/browser/autocomplete/autocomplete_classifier.h index facdd34..ed59306 100644 --- a/chrome/browser/autocomplete/autocomplete_classifier.h +++ b/chrome/browser/autocomplete/autocomplete_classifier.h @@ -23,15 +23,19 @@ class AutocompleteClassifier { // Given some string |text| that the user wants to use for navigation, // determines how it should be interpreted. |desired_tld| is the user's - // desired TLD, if any; see AutocompleteInput::desired_tld(). |match| should - // be a non-NULL outparam that will be set to the default match for this - // input, if any (for invalid input, there will be no default match, and - // |match| will be left unchanged). |alternate_nav_url| is a possibly-NULL - // outparam that, if non-NULL, will be set to the navigational URL (if any) in - // case of an accidental search; see comments on + // desired TLD, if any; see AutocompleteInput::desired_tld(). + // |allow_exact_keyword_match| should be true when treating the string as a + // potential keyword search is valid; see + // AutocompleteInput::allow_exact_keyword_match(). |match| should be a + // non-NULL outparam that will be set to the default match for this input, if + // any (for invalid input, there will be no default match, and |match| will be + // left unchanged). |alternate_nav_url| is a possibly-NULL outparam that, if + // non-NULL, will be set to the navigational URL (if any) in case of an + // accidental search; see comments on // AutocompleteResult::alternate_nav_url_ in autocomplete.h. void Classify(const std::wstring& text, const std::wstring& desired_tld, + bool allow_exact_keyword_match, AutocompleteMatch* match, GURL* alternate_nav_url); diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index ed18232..adf5985 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -171,6 +171,11 @@ void AutocompleteEditModel::GetDataForURLExport(GURL* url, } } +bool AutocompleteEditModel::PreventInlineAutocomplete() { + return + popup_->autocomplete_controller()->input().prevent_inline_autocomplete(); +} + std::wstring AutocompleteEditModel::GetDesiredTLD() const { // Tricky corner case: The user has typed "foo" and currently sees an inline // autocomplete suggestion of "foo.net". He now presses ctrl-a (e.g. to @@ -296,7 +301,7 @@ bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { return false; AutocompleteMatch match; - profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), + profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), false, &match, &paste_and_go_alternate_nav_url_); paste_and_go_url_ = match.destination_url; paste_and_go_transition_ = match.transition; @@ -610,10 +615,10 @@ void AutocompleteEditModel::OnPopupDataChanged( return; } - // If the above changes didn't warrant a text update but we did change keyword - // state, we have yet to notify the controller about it. - if (keyword_state_changed) - controller_->OnChanged(); + // All other code paths that return invoke OnChanged. We need to invoke + // OnChanged in case the destination url changed (as could happen when control + // is toggled). + controller_->OnChanged(); } bool AutocompleteEditModel::OnAfterPossibleChange(const std::wstring& new_text, @@ -772,8 +777,8 @@ void AutocompleteEditModel::GetInfoForCurrentText( popup_->InfoForCurrentSelection(match, alternate_nav_url); } else { profile_->GetAutocompleteClassifier()->Classify( - UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), match, - alternate_nav_url); + UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), true, + match, alternate_nav_url); } } diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h index 9e94172..1b4f4a1 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.h +++ b/chrome/browser/autocomplete/autocomplete_edit.h @@ -73,6 +73,9 @@ class AutocompleteEditController { // status of any keyword- or hint-related state. virtual void OnChanged() = 0; + // Called when the selection of the AutocompleteEditView changes. + virtual void OnSelectionBoundsChanged() = 0; + // Called whenever the user starts or stops an input session (typing, // interacting with the edit, etc.). When user input is not in progress, // the edit is guaranteed to be showing the permanent text. @@ -154,6 +157,10 @@ class AutocompleteEditModel : public NotificationObserver { // Sets the url, and if known, the title and favicon. void GetDataForURLExport(GURL* url, std::wstring* title, SkBitmap* favicon); + // Returns true if inline autocomplete was prevented the last time + // autocomplete was run. + bool PreventInlineAutocomplete(); + // If the user presses ctrl-enter, it means "add .com to the the end". The // desired TLD is the TLD the user desires to add to the end of the current // input, if any, based on their control key state and any other actions @@ -300,7 +307,7 @@ class AutocompleteEditModel : public NotificationObserver { // a different match, or the inline autocomplete text. We distinguish by // checking if |destination_for_temporary_text_change| is NULL. // |destination_for_temporary_text_change| is NULL (if temporary text should - // not change) or the pre-change desitnation URL (if temporary text should + // not change) or the pre-change destination URL (if temporary text should // change) so we can save it off to restore later. // |keyword| is the keyword to show a hint for if |is_keyword_hint| is true, // or the currently selected keyword if |is_keyword_hint| is false (see diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc index b0941ad..d2b93c5 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc @@ -33,6 +33,7 @@ class TestingAutocompleteEditView : public AutocompleteEditView { bool update_popup) {} virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos) {} + virtual void ReplaceSelection(const string16& text) {} virtual void SetForcedQuery() {} virtual bool IsSelectAll() { return false; } virtual void GetSelectionBounds(std::wstring::size_type* start, @@ -74,6 +75,7 @@ class TestingAutocompleteEditController : public AutocompleteEditController { PageTransition::Type transition, const GURL& alternate_nav_url) {} virtual void OnChanged() {} + virtual void OnSelectionBoundsChanged() {} virtual void OnInputInProgress(bool in_progress) {} virtual void OnKillFocus() {} virtual void OnSetFocus() {} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h index ce9a227..51224f8 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view.h @@ -14,6 +14,7 @@ #include +#include "base/string16.h" #include "chrome/common/page_transition_types.h" #include "gfx/native_widget_types.h" #include "webkit/glue/window_open_disposition.h" @@ -79,6 +80,9 @@ class AutocompleteEditView { virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos) = 0; + // Replaces the selection with the specified text and selects it. + virtual void ReplaceSelection(const string16& text) = 0; + // Sets the edit to forced query mode. Practically speaking, this means that // if the edit is not in forced query mode, its text is set to "?" with the // cursor at the end, and if the edit is in forced query mode (its first diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc index 6a8ef27..17ddced 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc @@ -17,7 +17,6 @@ #include "chrome/browser/autocomplete/autocomplete_popup_model.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/history/history.h" #include "chrome/browser/location_bar.h" @@ -25,6 +24,7 @@ #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" @@ -278,7 +278,7 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, // Test if ctrl-* accelerators are workable in omnibox. // See http://crbug.com/19193: omnibox blocks ctrl-* commands -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_BrowserAccelerators DISABLED_BrowserAccelerators #else @@ -337,7 +337,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_BrowserAccelerators) { #endif } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_PopupAccelerators DISABLED_PopupAccelerators #else @@ -390,7 +390,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_PopupAccelerators) { #endif } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_BackspaceInKeywordMode DISABLED_BackspaceInKeywordMode #else @@ -448,7 +448,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_BackspaceInKeywordMode) { WideToUTF8(edit_view->GetText())); } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_Escape DISABLED_Escape #else @@ -476,7 +476,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_Escape) { EXPECT_TRUE(edit_view->IsSelectAll()); } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_DesiredTLD DISABLED_DesiredTLD #else @@ -502,7 +502,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_DesiredTLD) { EXPECT_STREQ(kDesiredTLDHostname, url.host().c_str()); } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_AltEnter DISABLED_AltEnter #else @@ -522,7 +522,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_AltEnter) { ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1)); } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_EnterToSearch DISABLED_EnterToSearch #else @@ -572,7 +572,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_EnterToSearch) { // See http://crbug.com/20934: Omnibox keyboard behavior wrong for // "See recent pages in history" -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_EnterToOpenHistoryPage DISABLED_EnterToOpenHistoryPage #else @@ -615,7 +615,7 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_EnterToOpenHistoryPage) { EXPECT_STREQ(kHistoryPageURL, url.spec().c_str()); } -// FAILS on windows, http://crbug.com/57965 +// Sometimes times out on Windows: http://crbug.com/57965 #if defined(OS_WIN) #define MAYBE_EscapeToDefaultMatch DISABLED_EscapeToDefaultMatch #else @@ -660,7 +660,13 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_EscapeToDefaultMatch) { EXPECT_EQ(old_selected_line, popup_model->selected_line()); } -IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BasicTextOperations) { +// Sometimes times out on Windows: http://crbug.com/57965 +#if defined(OS_WIN) +#define MAYBE_BasicTextOperations DISABLED_BasicTextOperations +#else +#define MAYBE_BasicTextOperations BasicTextOperations +#endif +IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, MAYBE_BasicTextOperations) { ASSERT_NO_FATAL_FAILURE(SetupComponents()); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL)); browser()->FocusLocationBar(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc index 8ba3b52..9204f8f 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -545,6 +545,24 @@ void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const std::wstring& text, SetTextAndSelectedRange(text, range); } +void AutocompleteEditViewGtk::ReplaceSelection(const string16& text) { + CharRange selection = GetSelection(); + if (selection.selection_min() == selection.selection_max() && + text.empty()) { + return; + } + std::wstring current_text(GetText()); + std::wstring result = current_text.substr(0, selection.selection_min()) + + UTF16ToWide(text) + current_text.substr(selection.selection_max()); + selection.cp_min = selection.selection_min(); + selection.cp_max = UTF16ToWide(text).size() + selection.cp_min; + StartUpdatingHighlightedText(); + OnBeforePossibleChange(); + SetTextAndSelectedRange(result, selection); + OnAfterPossibleChange(); + FinishUpdatingHighlightedText(); +} + void AutocompleteEditViewGtk::SetForcedQuery() { const std::wstring current_text(GetText()); const size_t start = current_text.find_first_not_of(kWhitespaceWide); @@ -1312,7 +1330,7 @@ void AutocompleteEditViewGtk::HandleInsertText( enter_was_inserted_ = true; const gchar* p = text; - while(*p) { + while (*p) { gunichar c = g_utf8_get_char(p); const gchar* next = g_utf8_next_char(p); @@ -1702,8 +1720,10 @@ void AutocompleteEditViewGtk::SavePrimarySelection( void AutocompleteEditViewGtk::SetTextAndSelectedRange(const std::wstring& text, const CharRange& range) { - std::string utf8 = WideToUTF8(text); - gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); + if (text != GetText()) { + std::string utf8 = WideToUTF8(text); + gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); + } SetSelectedRange(range); AdjustTextJustification(); } diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h index b63c2f2..06ef3f4 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -53,8 +53,9 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, CharRange() : cp_min(0), cp_max(0) { } CharRange(int n, int x) : cp_min(n), cp_max(x) { } - // Returns the start of the selection. + // Returns the start/end of the selection. int selection_min() const { return std::min(cp_min, cp_max); } + int selection_max() const { return std::max(cp_min, cp_max); } // Work in integers to match the gint GTK APIs. int cp_min; // For a selection: Represents the start. @@ -116,6 +117,8 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos); + virtual void ReplaceSelection(const string16& text); + virtual void SetForcedQuery(); virtual bool IsSelectAll(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h index a474ce0..3bc3eff 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h @@ -57,6 +57,8 @@ class AutocompleteEditViewMac : public AutocompleteEditView, virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos); + virtual void ReplaceSelection(const string16& text); + virtual void SetForcedQuery(); virtual bool IsSelectAll(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm index aa4b9a6..12aeeb8 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm @@ -348,6 +348,10 @@ void AutocompleteEditViewMac::SetWindowTextAndCaretPos(const std::wstring& text, SetTextAndSelectedRange(text, NSMakeRange(caret_pos, caret_pos)); } +void AutocompleteEditViewMac::ReplaceSelection(const string16& text) { + NOTIMPLEMENTED(); +} + void AutocompleteEditViewMac::SetForcedQuery() { // We need to do this first, else |SetSelectedRange()| won't work. FocusLocation(true); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index e853c85..75e96d5 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -652,6 +652,20 @@ void AutocompleteEditViewWin::SetWindowTextAndCaretPos(const std::wstring& text, PlaceCaretAt(caret_pos); } +void AutocompleteEditViewWin::ReplaceSelection(const string16& text) { + CHARRANGE selection; + GetSel(selection); + if (selection.cpMin == selection.cpMax && text.empty()) + return; + + const std::wstring w_text(UTF16ToWide(text)); + ScopedFreeze freeze(this, GetTextObjectModel()); + OnBeforePossibleChange(); + ReplaceSel(w_text.c_str(), TRUE); + SetSelection(selection.cpMin, selection.cpMin + w_text.size()); + OnAfterPossibleChange(); +} + void AutocompleteEditViewWin::SetForcedQuery() { const std::wstring current_text(GetText()); const size_t start = current_text.find_first_not_of(kWhitespaceWide); @@ -886,6 +900,9 @@ bool AutocompleteEditViewWin::OnAfterPossibleChange() { const bool something_changed = model_->OnAfterPossibleChange(new_text, selection_differs, text_differs, just_deleted_text, at_end_of_edit); + if (selection_differs) + controller_->OnSelectionBoundsChanged(); + if (something_changed && text_differs) TextChanged(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h index c0abab6..fbe103f 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h @@ -22,8 +22,8 @@ #include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" #include "chrome/common/page_transition_types.h" #include "gfx/font.h" -#include "webkit/glue/window_open_disposition.h" #include "views/controls/menu/menu_2.h" +#include "webkit/glue/window_open_disposition.h" class Profile; class TabContents; @@ -114,6 +114,8 @@ class AutocompleteEditViewWin virtual void SetWindowTextAndCaretPos(const std::wstring& text, size_t caret_pos); + virtual void ReplaceSelection(const string16& text); + virtual void SetForcedQuery(); virtual bool IsSelectAll(); diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.cc b/chrome/browser/autocomplete/autocomplete_popup_model.cc index a14d19f..a857b3c 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_model.cc +++ b/chrome/browser/autocomplete/autocomplete_popup_model.cc @@ -54,7 +54,7 @@ void AutocompletePopupModel::StartAutocomplete( manually_selected_match_.Clear(); controller_->Start(text, desired_tld, prevent_inline_autocomplete, - prefer_keyword, false); + prefer_keyword, true, false); } void AutocompletePopupModel::StopAutocomplete() { diff --git a/chrome/browser/autocomplete/autocomplete_unittest.cc b/chrome/browser/autocomplete/autocomplete_unittest.cc index d78611c..f6b165e 100644 --- a/chrome/browser/autocomplete/autocomplete_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_unittest.cc @@ -9,9 +9,14 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/autocomplete/autocomplete.h" #include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/autocomplete/keyword_provider.h" +#include "chrome/browser/autocomplete/search_provider.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/browser/search_engines/template_url_model.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" +#include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" // identifiers for known autocomplete providers @@ -102,15 +107,15 @@ void TestProvider::AddResults(int start_at, int num) { class AutocompleteProviderTest : public testing::Test, public NotificationObserver { protected: - // testing::Test - virtual void SetUp(); - - void ResetController(bool same_destinations); + void ResetControllerWithTestProviders(bool same_destinations); // Runs a query on the input "a", and makes sure both providers' input is // properly collected. void RunTest(); + void ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); + void RunExactKeymatchTest(bool allow_exact_keyword_match); + // These providers are owned by the controller once it's created. ACProviders providers_; @@ -125,15 +130,11 @@ class AutocompleteProviderTest : public testing::Test, MessageLoopForUI message_loop_; scoped_ptr controller_; NotificationRegistrar registrar_; + TestingProfile profile_; }; -void AutocompleteProviderTest::SetUp() { - registrar_.Add(this, NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED, - NotificationService::AllSources()); - ResetController(false); -} - -void AutocompleteProviderTest::ResetController(bool same_destinations) { +void AutocompleteProviderTest::ResetControllerWithTestProviders( + bool same_destinations) { // Forget about any existing providers. The controller owns them and will // Release() them below, when we delete it during the call to reset(). providers_.clear(); @@ -154,17 +155,77 @@ void AutocompleteProviderTest::ResetController(bool same_destinations) { controller_.reset(controller); providerA->set_listener(controller); providerB->set_listener(controller); + + // The providers don't complete synchronously, so listen for "result updated" + // notifications. + registrar_.Add(this, NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED, + NotificationService::AllSources()); +} + +void AutocompleteProviderTest:: + ResetControllerWithTestProvidersWithKeywordAndSearchProviders() { + profile_.CreateTemplateURLModel(); + + // Reset the default TemplateURL. + TemplateURL* default_t_url = new TemplateURL(); + default_t_url->SetURL("http://defaultturl/{searchTerms}", 0, 0); + TemplateURLModel* turl_model = profile_.GetTemplateURLModel(); + turl_model->Add(default_t_url); + turl_model->SetDefaultSearchProvider(default_t_url); + TemplateURLID default_provider_id = default_t_url->id(); + ASSERT_NE(0, default_provider_id); + + // Create another TemplateURL for KeywordProvider. + TemplateURL* keyword_t_url = new TemplateURL(); + keyword_t_url->set_short_name(L"k"); + keyword_t_url->set_keyword(L"k"); + keyword_t_url->SetURL("http://keyword/{searchTerms}", 0, 0); + profile_.GetTemplateURLModel()->Add(keyword_t_url); + ASSERT_NE(0, keyword_t_url->id()); + + // Forget about any existing providers. The controller owns them and will + // Release() them below, when we delete it during the call to reset(). + providers_.clear(); + + // Create both a keyword and search provider, and add them in that order. + // (Order is important; see comments in RunExactKeymatchTest().) + AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, + &profile_); + keyword_provider->AddRef(); + providers_.push_back(keyword_provider); + AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_); + search_provider->AddRef(); + providers_.push_back(search_provider); + + AutocompleteController* controller = new AutocompleteController(providers_); + controller_.reset(controller); } void AutocompleteProviderTest::RunTest() { result_.Reset(); - controller_->Start(L"a", std::wstring(), true, false, false); + controller_->Start(L"a", std::wstring(), true, false, true, false); // The message loop will terminate when all autocomplete input has been // collected. MessageLoop::current()->Run(); } +void AutocompleteProviderTest::RunExactKeymatchTest( + bool allow_exact_keyword_match) { + // Send the controller input which exactly matches the keyword provider we + // created in ResetControllerWithKeywordAndSearchProviders(). The default + // match should thus be a keyword match iff |allow_exact_keyword_match| is + // true. + controller_->Start(L"k test", std::wstring(), true, false, + allow_exact_keyword_match, true); + EXPECT_TRUE(controller_->done()); + // ResetControllerWithKeywordAndSearchProviders() adds the keyword provider + // first, then the search provider. So if the default match is a keyword + // match, it will come from provider 0, otherwise from provider 1. + EXPECT_EQ(providers_[allow_exact_keyword_match ? 0 : 1], + controller_->result().default_match()->provider); +} + void AutocompleteProviderTest::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { @@ -176,6 +237,7 @@ void AutocompleteProviderTest::Observe(NotificationType type, // Tests that the default selection is set properly when updating results. TEST_F(AutocompleteProviderTest, Query) { + ResetControllerWithTestProviders(false); RunTest(); // Make sure the default match gets set to the highest relevance match. The @@ -186,9 +248,7 @@ TEST_F(AutocompleteProviderTest, Query) { } TEST_F(AutocompleteProviderTest, RemoveDuplicates) { - // Set up the providers to provide duplicate results. - ResetController(true); - + ResetControllerWithTestProviders(true); RunTest(); // Make sure all the first provider's results were eliminated by the second @@ -197,10 +257,12 @@ TEST_F(AutocompleteProviderTest, RemoveDuplicates) { for (AutocompleteResult::const_iterator i(result_.begin()); i != result_.end(); ++i) EXPECT_EQ(providers_[1], i->provider); +} - // Set things back to the default for the benefit of any tests that run after - // us. - ResetController(false); +TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { + ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); + RunExactKeymatchTest(true); + RunExactKeymatchTest(false); } TEST(AutocompleteTest, InputType) { @@ -283,7 +345,7 @@ TEST(AutocompleteTest, InputType) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) { AutocompleteInput input(input_cases[i].input, std::wstring(), true, false, - false); + true, false); EXPECT_EQ(input_cases[i].type, input.type()) << "Input: " << input_cases[i].input; } @@ -299,7 +361,8 @@ TEST(AutocompleteTest, InputTypeWithDesiredTLD) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) { - AutocompleteInput input(input_cases[i].input, L"com", true, false, false); + AutocompleteInput input(input_cases[i].input, L"com", true, false, true, + false); EXPECT_EQ(input_cases[i].type, input.type()) << "Input: " << input_cases[i].input; } @@ -308,7 +371,8 @@ TEST(AutocompleteTest, InputTypeWithDesiredTLD) { // This tests for a regression where certain input in the omnibox caused us to // crash. As long as the test completes without crashing, we're fine. TEST(AutocompleteTest, InputCrash) { - AutocompleteInput input(L"\uff65@s", std::wstring(), true, false, false); + AutocompleteInput input(L"\uff65@s", std::wstring(), true, false, true, + false); } // Test that we can properly compare matches' relevance when at least one is @@ -372,7 +436,7 @@ TEST(AutocompleteInput, ParseForEmphasizeComponent) { &scheme, &host); AutocompleteInput input(input_cases[i].input, std::wstring(), true, false, - false); + true, false); EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin) << "Input: " << input_cases[i].input; EXPECT_EQ(input_cases[i].scheme.len, scheme.len) << "Input: " << diff --git a/chrome/browser/autocomplete/history_contents_provider_unittest.cc b/chrome/browser/autocomplete/history_contents_provider_unittest.cc index 9f1119b..b6c3208 100644 --- a/chrome/browser/autocomplete/history_contents_provider_unittest.cc +++ b/chrome/browser/autocomplete/history_contents_provider_unittest.cc @@ -105,7 +105,7 @@ class HistoryContentsProviderTest : public testing::Test, }; TEST_F(HistoryContentsProviderTest, Body) { - AutocompleteInput input(L"FOO", std::wstring(), true, false, false); + AutocompleteInput input(L"FOO", std::wstring(), true, false, true, false); RunQuery(input, false); // The results should be the first two pages, in decreasing order. @@ -118,7 +118,7 @@ TEST_F(HistoryContentsProviderTest, Body) { } TEST_F(HistoryContentsProviderTest, Title) { - AutocompleteInput input(L"PAGEONE", std::wstring(), true, false, false); + AutocompleteInput input(L"PAGEONE", std::wstring(), true, false, true, false); RunQuery(input, false); // The results should be the first two pages. @@ -134,13 +134,15 @@ TEST_F(HistoryContentsProviderTest, Title) { TEST_F(HistoryContentsProviderTest, MinimalChanges) { // A minimal changes request when there have been no real queries should // give us no results. - AutocompleteInput sync_input(L"PAGEONE", std::wstring(), true, false, true); + AutocompleteInput sync_input(L"PAGEONE", std::wstring(), true, false, true, + true); RunQuery(sync_input, true); const ACMatches& m1 = matches(); EXPECT_EQ(0U, m1.size()); // Now do a "regular" query to get the results. - AutocompleteInput async_input(L"PAGEONE", std::wstring(), true, false, false); + AutocompleteInput async_input(L"PAGEONE", std::wstring(), true, false, true, + false); RunQuery(async_input, false); const ACMatches& m2 = matches(); EXPECT_EQ(2U, m2.size()); @@ -163,7 +165,7 @@ TEST_F(HistoryContentsProviderTest, Bookmarks) { ASCIIToUTF16("bar"), true); // Ask for synchronous. This should only get the bookmark. - AutocompleteInput sync_input(L"bar", std::wstring(), true, false, true); + AutocompleteInput sync_input(L"bar", std::wstring(), true, false, true, true); RunQuery(sync_input, false); const ACMatches& m1 = matches(); ASSERT_EQ(1U, m1.size()); @@ -172,7 +174,8 @@ TEST_F(HistoryContentsProviderTest, Bookmarks) { EXPECT_TRUE(m1[0].starred); // Ask for async. We should get the bookmark immediately. - AutocompleteInput async_input(L"bar", std::wstring(), true, false, false); + AutocompleteInput async_input(L"bar", std::wstring(), true, false, true, + false); provider()->Start(async_input, false); const ACMatches& m2 = matches(); ASSERT_EQ(1U, m2.size()); diff --git a/chrome/browser/autocomplete/history_quick_provider_unittest.cc b/chrome/browser/autocomplete/history_quick_provider_unittest.cc index 6de941a..7dab5dc 100644 --- a/chrome/browser/autocomplete/history_quick_provider_unittest.cc +++ b/chrome/browser/autocomplete/history_quick_provider_unittest.cc @@ -169,7 +169,7 @@ void HistoryQuickProviderTest::RunTest(const std::wstring text, std::sort(expected_urls.begin(), expected_urls.end()); MessageLoop::current()->RunAllPending(); - AutocompleteInput input(text, std::wstring(), false, false, false); + AutocompleteInput input(text, std::wstring(), false, false, true, false); provider_->Start(input, false); EXPECT_TRUE(provider_->done()); diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc index 19f3053..89ed06c 100644 --- a/chrome/browser/autocomplete/history_url_provider_unittest.cc +++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc @@ -189,7 +189,7 @@ void HistoryURLProviderTest::RunTest(const std::wstring text, const std::string* expected_urls, size_t num_results) { AutocompleteInput input(text, desired_tld, prevent_inline_autocomplete, - false, false); + false, true, false); autocomplete_->Start(input, false); if (!autocomplete_->done()) MessageLoop::current()->Run(); @@ -203,7 +203,7 @@ void HistoryURLProviderTest::RunTest(const std::wstring text, void HistoryURLProviderTest::RunAdjustOffsetTest(const std::wstring text, size_t expected_offset) { - AutocompleteInput input(text, std::wstring(), false, false, false); + AutocompleteInput input(text, std::wstring(), false, false, true, false); autocomplete_->Start(input, false); if (!autocomplete_->done()) MessageLoop::current()->Run(); diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc index af9c125..ffa1e09 100644 --- a/chrome/browser/autocomplete/keyword_provider.cc +++ b/chrome/browser/autocomplete/keyword_provider.cc @@ -102,6 +102,9 @@ const TemplateURL* KeywordProvider::GetSubstitutingTemplateURLForInput( Profile* profile, const AutocompleteInput& input, std::wstring* remaining_input) { + if (!input.allow_exact_keyword_match()) + return NULL; + std::wstring keyword; if (!ExtractKeywordFromInput(input, &keyword, remaining_input)) return NULL; @@ -301,7 +304,11 @@ void KeywordProvider::FillInURLAndContents( int message_id = element->IsExtensionKeyword() ? IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH; if (remaining_input.empty()) { - if (element->url()->SupportsReplacement()) { + // Allow extension keyword providers to accept empty string input. This is + // useful to allow extensions to do something in the case where no input is + // entered. + if (element->url()->SupportsReplacement() && + !element->IsExtensionKeyword()) { // No query input; return a generic, no-destination placeholder. match->contents.assign(l10n_util::GetStringF(message_id, element->AdjustedShortNameForLocaleDirection(), @@ -344,9 +351,12 @@ void KeywordProvider::FillInURLAndContents( // static int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type, bool complete, - bool no_query_text_needed) { + bool no_query_text_needed, + bool allow_exact_keyword_match) { if (!complete) return (type == AutocompleteInput::URL) ? 700 : 450; + if (!allow_exact_keyword_match) + return 1100; if (no_query_text_needed) return 1500; return (type == AutocompleteInput::QUERY) ? 1450 : 1100; @@ -375,7 +385,8 @@ AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( // When the user wants keyword matches to take // preference, score them highly regardless of // whether the input provides query text. - input.prefer_keyword() || !supports_replacement); + input.prefer_keyword() || !supports_replacement, + input.allow_exact_keyword_match()); } AutocompleteMatch result(this, relevance, false, supports_replacement ? AutocompleteMatch::SEARCH_OTHER_ENGINE : @@ -451,8 +462,8 @@ void KeywordProvider::Observe(NotificationType type, // and subtract 1 for each subsequent suggestion from the extension. // We know that |complete| is true, because we wouldn't get results from // the extension unless the full keyword had been typed. - int first_relevance = - CalculateRelevance(input.type(), true, input.prefer_keyword()); + int first_relevance = CalculateRelevance(input.type(), true, + input.prefer_keyword(), input.allow_exact_keyword_match()); extension_suggest_matches_.push_back(CreateAutocompleteMatch( model, keyword, input, keyword.length(), UTF16ToWide(suggestion.content), first_relevance - (i + 1))); diff --git a/chrome/browser/autocomplete/keyword_provider.h b/chrome/browser/autocomplete/keyword_provider.h index 711562a..e39b5b6 100644 --- a/chrome/browser/autocomplete/keyword_provider.h +++ b/chrome/browser/autocomplete/keyword_provider.h @@ -105,9 +105,12 @@ class KeywordProvider : public AutocompleteProvider, // typed the complete keyword, and whether the keyword needs query text (true // if the keyword supports replacement and the user isn't in "prefer keyword // matches" mode). + // If |allow_exact_keyword_match| is false, the relevance for complete + // keywords is degraded. static int CalculateRelevance(AutocompleteInput::Type type, bool complete, - bool no_query_text_needed); + bool no_query_text_needed, + bool allow_exact_keyword_match); // Creates a fully marked-up AutocompleteMatch from the user's input. // If |relevance| is negative, calculate a relevance based on heuristics. diff --git a/chrome/browser/autocomplete/keyword_provider_unittest.cc b/chrome/browser/autocomplete/keyword_provider_unittest.cc index e63d548..165662e 100644 --- a/chrome/browser/autocomplete/keyword_provider_unittest.cc +++ b/chrome/browser/autocomplete/keyword_provider_unittest.cc @@ -64,7 +64,7 @@ void KeywordProviderTest::RunTest( ACMatches matches; for (int i = 0; i < num_cases; ++i) { AutocompleteInput input(keyword_cases[i].input, std::wstring(), true, - false, false); + false, true, false); kw_provider_->Start(input, false); EXPECT_TRUE(kw_provider_->done()); matches = kw_provider_->matches(); diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index 408e647..a18a5ea 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -565,11 +565,26 @@ int SearchProvider::CalculateRelevanceForWhatYouTyped() const { int SearchProvider::CalculateRelevanceForHistory(const Time& time, bool is_keyword) const { - // The relevance of past searches falls off over time. This curve is chosen - // so that the relevance of a search 15 minutes ago is discounted about 50 - // points, while the relevance of a search two weeks ago is discounted about - // 450 points. - const double elapsed_time = std::max((Time::Now() - time).InSecondsF(), 0.); + // The relevance of past searches falls off over time. There are two distinct + // equations used. If the first equation is used (searches to the primary + // provider with a type other than URL) the score starts at 1399 and falls to + // 1300. If the second equation is used the relevance of a search 15 minutes + // ago is discounted about 50 points, while the relevance of a search two + // weeks ago is discounted about 450 points. + double elapsed_time = std::max((Time::Now() - time).InSecondsF(), 0.); + + if (providers_.is_primary_provider(is_keyword) && + input_.type() != AutocompleteInput::URL && + !input_.prevent_inline_autocomplete()) { + // Searches with the past two days get a different curve. + const double autocomplete_time= 2 * 24 * 60 * 60; + if (elapsed_time < autocomplete_time) { + return 1399 - static_cast(99 * + std::pow(elapsed_time / autocomplete_time, 2.5)); + } + elapsed_time -= autocomplete_time; + } + const int score_discount = static_cast(6.5 * std::pow(elapsed_time, 0.3)); diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc index 43ae43b..6c20d55 100644 --- a/chrome/browser/autocomplete/search_provider_unittest.cc +++ b/chrome/browser/autocomplete/search_provider_unittest.cc @@ -58,7 +58,8 @@ class SearchProviderTest : public testing::Test, void RunTillProviderDone(); // Invokes Start on provider_, then runs all pending tasks. - void QueryForInput(const string16& text); + void QueryForInput(const string16& text, + bool prevent_inline_autocomplete); // See description above class for details of these fields. TemplateURL* default_t_url_; @@ -162,10 +163,11 @@ void SearchProviderTest::RunTillProviderDone() { #endif } -void SearchProviderTest::QueryForInput(const string16& text) { +void SearchProviderTest::QueryForInput(const string16& text, + bool prevent_inline_autocomplete) { // Start a query. AutocompleteInput input(UTF16ToWide(text), std::wstring(), - false, false, false); + prevent_inline_autocomplete, false, true, false); provider_->Start(input, false); // RunAllPending so that the task scheduled by SearchProvider to create the @@ -198,7 +200,7 @@ AutocompleteMatch SearchProviderTest::FindMatchWithDestination( // created for the default provider suggest results. TEST_F(SearchProviderTest, QueryDefaultProvider) { string16 term = term1_.substr(0, term1_.size() - 1); - QueryForInput(term); + QueryForInput(term, false); // Make sure the default providers suggest service was queried. TestURLFetcher* fetcher = test_factory_.GetFetcherByID( @@ -226,12 +228,21 @@ TEST_F(SearchProviderTest, QueryDefaultProvider) { ASSERT_TRUE(!match.destination_url.is_empty()); } +TEST_F(SearchProviderTest, HonorPreventInlineAutocomplete) { + string16 term = term1_.substr(0, term1_.size() - 1); + QueryForInput(term, true); + + ASSERT_FALSE(provider_->matches().empty()); + ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, + provider_->matches()[0].type); +} + // Issues a query that matches the registered keyword and makes sure history // is queried as well as URLFetchers getting created. TEST_F(SearchProviderTest, QueryKeywordProvider) { string16 term = keyword_term_.substr(0, keyword_term_.size() - 1); QueryForInput(WideToUTF16(keyword_t_url_->keyword()) + - UTF8ToUTF16(" ") + term); + UTF8ToUTF16(" ") + term, false); // Make sure the default providers suggest service was queried. TestURLFetcher* default_fetcher = test_factory_.GetFetcherByID( @@ -295,7 +306,7 @@ TEST_F(SearchProviderTest, DontSendPrivateDataToSuggest) { }; for (size_t i = 0; i < arraysize(inputs); ++i) { - QueryForInput(ASCIIToUTF16(inputs[i])); + QueryForInput(ASCIIToUTF16(inputs[i]), false); // Make sure the default providers suggest service was not queried. ASSERT_TRUE(test_factory_.GetFetcherByID( SearchProvider::kDefaultProviderURLFetcherID) == NULL); diff --git a/chrome/browser/autocomplete_history_manager.cc b/chrome/browser/autocomplete_history_manager.cc index 2243bcb..763445b 100644 --- a/chrome/browser/autocomplete_history_manager.cc +++ b/chrome/browser/autocomplete_history_manager.cc @@ -73,8 +73,7 @@ bool IsSSN(const string16& text) { AutocompleteHistoryManager::AutocompleteHistoryManager( TabContents* tab_contents) : tab_contents_(tab_contents), - pending_query_handle_(0), - query_id_(0) { + pending_query_handle_(0) { DCHECK(tab_contents); profile_ = tab_contents_->profile(); @@ -94,17 +93,17 @@ void AutocompleteHistoryManager::FormSubmitted(const FormData& form) { StoreFormEntriesInWebDatabase(form); } -bool AutocompleteHistoryManager::GetAutocompleteSuggestions( - int query_id, const string16& name, const string16& prefix) { - if (!*autofill_enabled_) - return false; +void AutocompleteHistoryManager::GetAutocompleteSuggestions( + const string16& name, const string16& prefix) { + if (!*autofill_enabled_) { + SendSuggestions(NULL); + return; + } CancelPendingQuery(); - query_id_ = query_id; pending_query_handle_ = web_data_service_->GetFormValuesForElementName( name, prefix, kMaxAutocompleteMenuItems, this); - return true; } void AutocompleteHistoryManager::RemoveAutocompleteEntry( @@ -130,8 +129,7 @@ AutocompleteHistoryManager::AutocompleteHistoryManager( Profile* profile, WebDataService* wds) : tab_contents_(NULL), profile_(profile), web_data_service_(wds), - pending_query_handle_(0), - query_id_(0) { + pending_query_handle_(0) { autofill_enabled_.Init( prefs::kAutoFillEnabled, profile_->GetPrefs(), NULL); } @@ -187,10 +185,8 @@ void AutocompleteHistoryManager::SendSuggestions(const WDTypedResult* result) { DCHECK(result->GetType() == AUTOFILL_VALUE_RESULT); const WDResult >* autofill_result = static_cast >*>(result); - host->AutocompleteSuggestionsReturned( - query_id_, autofill_result->GetValue()); + host->AutocompleteSuggestionsReturned(autofill_result->GetValue()); } else { - host->AutocompleteSuggestionsReturned( - query_id_, std::vector()); + host->AutocompleteSuggestionsReturned(std::vector()); } } diff --git a/chrome/browser/autocomplete_history_manager.h b/chrome/browser/autocomplete_history_manager.h index 23493b3..5752942 100644 --- a/chrome/browser/autocomplete_history_manager.h +++ b/chrome/browser/autocomplete_history_manager.h @@ -28,8 +28,7 @@ class AutocompleteHistoryManager // RenderViewHostDelegate::Autocomplete implementation. virtual void FormSubmitted(const webkit_glue::FormData& form); - virtual bool GetAutocompleteSuggestions(int query_id, - const string16& name, + virtual void GetAutocompleteSuggestions(const string16& name, const string16& prefix); virtual void RemoveAutocompleteEntry(const string16& name, const string16& value); @@ -59,7 +58,6 @@ class AutocompleteHistoryManager // is queried on another thread, we record the query handle until we // get called back. WebDataService::Handle pending_query_handle_; - int query_id_; DISALLOW_COPY_AND_ASSIGN(AutocompleteHistoryManager); }; diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc index 579f08c..d4901bd 100644 --- a/chrome/browser/autofill/autofill_browsertest.cc +++ b/chrome/browser/autofill/autofill_browsertest.cc @@ -12,11 +12,11 @@ #include "chrome/browser/autofill/autofill_common_test.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/personal_data_manager.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/net/predictor_api.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/pref_names.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm index 13aeb4f..71c9ae8 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm @@ -271,7 +271,7 @@ TEST_F(AutoFillDialogControllerTest, CreditCardDataMutation) { ASSERT_TRUE(sheet != nil); AutoFillCreditCardModel* cm = [sheet creditCardModel]; EXPECT_TRUE([[cm nameOnCard] isEqualToString:@"DCH"]); - EXPECT_TRUE([[cm creditCardNumber] isEqualToString:@"1234 5678 9101 1121"]); + EXPECT_TRUE([[cm creditCardNumber] isEqualToString:@"1234567891011121"]); EXPECT_TRUE([[cm expirationMonth] isEqualToString:@"01"]); EXPECT_TRUE([[cm expirationYear] isEqualToString:@"2012"]); diff --git a/chrome/browser/autofill/autofill_dialog_gtk.cc b/chrome/browser/autofill/autofill_dialog_gtk.cc index de74b94..46708e9 100644 --- a/chrome/browser/autofill/autofill_dialog_gtk.cc +++ b/chrome/browser/autofill/autofill_dialog_gtk.cc @@ -21,8 +21,6 @@ #include "chrome/browser/autofill/form_group.h" #include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/autofill/phone_number.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_tree.h" #include "chrome/browser/gtk/gtk_util.h" @@ -30,6 +28,8 @@ #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_type.h" diff --git a/chrome/browser/autofill/autofill_download.cc b/chrome/browser/autofill/autofill_download.cc index a1a83c5..fa819b8 100644 --- a/chrome/browser/autofill/autofill_download.cc +++ b/chrome/browser/autofill/autofill_download.cc @@ -5,6 +5,7 @@ #include "chrome/browser/autofill/autofill_download.h" #include +#include #include "base/logging.h" #include "base/rand_util.h" @@ -235,7 +236,7 @@ void AutoFillDownloadManager::OnURLFetchComplete(const URLFetcher* source, } LOG(WARNING) << "AutoFillDownloadManager: " << type_of_request - << " request has failed with response" << response_code; + << " request has failed with response " << response_code; if (observer_) { observer_->OnHeuristicsRequestError(it->second.form_signatures[0], it->second.request_type, @@ -266,4 +267,3 @@ void AutoFillDownloadManager::OnURLFetchComplete(const URLFetcher* source, delete it->first; url_fetchers_.erase(it); } - diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc index 0165f1c..2350607 100644 --- a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc +++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc @@ -133,6 +133,9 @@ bool ImportSingleProfile(FormGroup* profile, string16 field_value = ReadAndDecryptValue(key, value_name.c_str()); if (!field_value.empty()) { has_non_empty_fields = true; + if (it->second == CREDIT_CARD_NUMBER) { + field_value = DecryptCCNumber(field_value); + } profile->SetInfo(AutoFillType(it->second), field_value); } } @@ -237,12 +240,6 @@ bool ImportCurrentUserProfiles(std::vector* profiles, if (ImportSingleProfile(&credit_card, &key, reg_to_field)) { string16 cc_number = credit_card.GetFieldText( AutoFillType(CREDIT_CARD_NUMBER)); - - if (!cc_number.empty()) { - // No additional password, and CC# is not empty, decrypt CC#. - cc_number = DecryptCCNumber(cc_number); - } - credit_card.SetInfo(AutoFillType(CREDIT_CARD_NUMBER), cc_number); if (!cc_number.empty()) credit_cards->push_back(credit_card); } diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc index 5b23ee5..17e85db 100644 --- a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc +++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc @@ -60,11 +60,11 @@ ValueDescription profile2[] = { ValueDescription credit_card[] = { { L"credit_card_name", L"Tommy Gun" }, - // "12345790087665675" encrypted: - { L"credit_card_number", L"\x18B7\xE586\x459B\x7457\xA066\x3842\x71DA" - L"\x4854\xB906\x9C7C\x50A6\x4376\xFD9D\x1E02" - L"\x790A\x7330\xB77B\xAF32\x93EB\xB84F\xEC8F" - L"\x265B\xD0E1\x4E27\xB758\x7985\xB92F" }, + // "4111111111111111" encrypted: + { L"credit_card_number", L"\xE53F\x19AB\xC1BF\xC9EB\xECCC\x9BDA\x8515" + L"\xE14D\x6852\x80A8\x50A3\x4375\xFD9F\x1E07" + L"\x790E\x7336\xB773\xAF33\x93EA\xB846\xEC89" + L"\x265C\xD0E6\x4E23\xB75F\x7983" }, { L"credit_card_exp_month", L"11" }, { L"credit_card_exp_4_digit_year", L"2011" }, }; @@ -203,7 +203,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutoFillImport) { EXPECT_EQ(credit_cards[0].GetFieldText(AutoFillType(CREDIT_CARD_NAME)), credit_card[0].value); EXPECT_EQ(credit_cards[0].GetFieldText(AutoFillType(CREDIT_CARD_NUMBER)), - L"12345790087665675"); + L"4111111111111111"); EXPECT_EQ(credit_cards[0].GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH)), credit_card[2].value); EXPECT_EQ(credit_cards[0].GetFieldText( diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index ef0fee9..9b67083 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -7,6 +7,7 @@ #include #include +#include "app/l10n_util.h" #include "base/basictypes.h" #include "base/string16.h" #include "base/utf_string_conversions.h" @@ -26,6 +27,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "grit/generated_resources.h" #include "webkit/glue/form_data.h" #ifdef ANDROID #include @@ -140,7 +142,7 @@ void AutoFillManager::FormSubmitted(const FormData& form) { // Grab a copy of the form data. upload_form_structure_.reset(new FormStructure(form)); - if (!upload_form_structure_->IsAutoFillable()) + if (!upload_form_structure_->IsAutoFillable(true)) return; // Determine the possible field types and upload the form structure to the @@ -156,8 +158,7 @@ void AutoFillManager::FormsSeen(const std::vector& forms) { ParseForms(forms); } -bool AutoFillManager::GetAutoFillSuggestions(int query_id, - bool field_autofilled, +bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, const FormField& field) { if (!IsAutoFillEnabled()) return false; @@ -186,7 +187,7 @@ bool AutoFillManager::GetAutoFillSuggestions(int query_id, form = *form_iter; // Don't send suggestions for forms that aren't auto-fillable. - if (!form->IsAutoFillable()) + if (!form->IsAutoFillable(false)) continue; for (std::vector::const_iterator iter = form->begin(); @@ -228,6 +229,30 @@ bool AutoFillManager::GetAutoFillSuggestions(int query_id, if (values.empty()) return false; + // Don't provide AutoFill suggestions when AutoFill is disabled, but provide a + // warning to the user. + if (!form->IsAutoFillable(true)) { + values.assign( + 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); + labels.assign(1, string16()); + icons.assign(1, string16()); + unique_ids.assign(1, -1); + host->AutoFillSuggestionsReturned(values, labels, icons, unique_ids); + return true; + } + + // Don't provide credit card suggestions for non-HTTPS pages, but provide a + // warning to the user. + if (!FormIsHTTPS(form) && type.group() == AutoFillType::CREDIT_CARD) { + values.assign( + 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION)); + labels.assign(1, string16()); + icons.assign(1, string16()); + unique_ids.assign(1, -1); + host->AutoFillSuggestionsReturned(values, labels, icons, unique_ids); + return true; + } + // If the form is auto-filled and the renderer is querying for suggestions, // then the user is editing the value of a field. In this case, mimick // autocomplete. In particular, don't display labels, as that information is @@ -245,8 +270,7 @@ bool AutoFillManager::GetAutoFillSuggestions(int query_id, } } - host->AutoFillSuggestionsReturned( - query_id, values, labels, icons, unique_ids); + host->AutoFillSuggestionsReturned(values, labels, icons, unique_ids); return true; } @@ -433,7 +457,7 @@ void AutoFillManager::HandleSubmit() { // require querying the FormManager for updated field values. std::vector import; import.push_back(upload_form_structure_.get()); - if (!personal_data_->ImportFormData(import, this)) + if (!personal_data_->ImportFormData(import)) return; // Did we get credit card info? @@ -551,10 +575,6 @@ void AutoFillManager::GetCreditCardSuggestions(FormStructure* form, std::vector* labels, std::vector* icons, std::vector* unique_ids) { - // Don't return CC suggestions for non-HTTPS pages. - if (!FormIsHTTPS(form)) - return; - for (std::vector::const_iterator iter = personal_data_->credit_cards().begin(); iter != personal_data_->credit_cards().end(); ++iter) { @@ -625,22 +645,33 @@ void AutoFillManager::FillPhoneNumberField(const AutoFillProfile* profile, } } -void AutoFillManager::ParseForms( - const std::vector& forms) { - for (std::vector::const_iterator iter = - forms.begin(); +void AutoFillManager::ParseForms(const std::vector& forms) { + std::vector non_queryable_forms; + for (std::vector::const_iterator iter = forms.begin(); iter != forms.end(); ++iter) { scoped_ptr form_structure(new FormStructure(*iter)); - if (!form_structure->ShouldBeParsed()) + if (!form_structure->ShouldBeParsed(false)) continue; DeterminePossibleFieldTypes(form_structure.get()); - form_structures_.push_back(form_structure.release()); + + // Set aside forms with method GET so that they are not included in the + // query to the server. + if (form_structure->ShouldBeParsed(true)) + form_structures_.push_back(form_structure.release()); + else + non_queryable_forms.push_back(form_structure.release()); } // If none of the forms were parsed, no use querying the server. if (!form_structures_.empty() && !disable_download_manager_requests_) download_manager_.StartQueryRequest(form_structures_); + + for (std::vector::const_iterator iter = + non_queryable_forms.begin(); + iter != non_queryable_forms.end(); ++iter) { + form_structures_.push_back(*iter); + } } // When sending IDs (across processes) to the renderer we pack credit card and diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h index 6e4859d..2037a11 100644 --- a/chrome/browser/autofill/autofill_manager.h +++ b/chrome/browser/autofill/autofill_manager.h @@ -57,8 +57,7 @@ class AutoFillManager : // RenderViewHostDelegate::AutoFill implementation: virtual void FormSubmitted(const webkit_glue::FormData& form); virtual void FormsSeen(const std::vector& forms); - virtual bool GetAutoFillSuggestions(int query_id, - bool field_autofilled, + virtual bool GetAutoFillSuggestions(bool field_autofilled, const webkit_glue::FormField& field); virtual bool FillAutoFillFormData(int query_id, const webkit_glue::FormData& form, diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc index 264dc80..182148d 100644 --- a/chrome/browser/autofill/autofill_manager_unittest.cc +++ b/chrome/browser/autofill/autofill_manager_unittest.cc @@ -4,6 +4,7 @@ #include +#include "app/l10n_util.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/scoped_vector.h" @@ -23,6 +24,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #include "googleurl/src/gurl.h" +#include "grit/generated_resources.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/glue/form_data.h" #include "webkit/glue/form_field.h" @@ -59,6 +61,14 @@ class TestPersonalDataManager : public PersonalDataManager { web_profiles_->push_back(profile); } + void ClearAutoFillProfiles() { + web_profiles_.reset(); + } + + void ClearCreditCards() { + credit_cards_.reset(); + } + private: void CreateTestAutoFillProfiles(ScopedVector* profiles) { AutoFillProfile* profile = new AutoFillProfile; @@ -110,7 +120,8 @@ class TestAutoFillManager : public AutoFillManager { public: TestAutoFillManager(TabContents* tab_contents, TestPersonalDataManager* personal_manager) - : AutoFillManager(tab_contents, NULL) { + : AutoFillManager(tab_contents, NULL), + autofill_enabled_(true) { test_personal_data_ = personal_manager; set_personal_data_manager(personal_manager); // Download manager requests are disabled for purposes of this unit-test. @@ -118,7 +129,11 @@ class TestAutoFillManager : public AutoFillManager { set_disable_download_manager_requests(true); } - virtual bool IsAutoFillEnabled() const { return true; } + virtual bool IsAutoFillEnabled() const { return autofill_enabled_; } + + void set_autofill_enabled(bool autofill_enabled) { + autofill_enabled_ = autofill_enabled; + } AutoFillProfile* GetLabeledProfile(const char* label) { return test_personal_data_->GetLabeledProfile(label); @@ -130,6 +145,7 @@ class TestAutoFillManager : public AutoFillManager { private: TestPersonalDataManager* test_personal_data_; + bool autofill_enabled_; DISALLOW_COPY_AND_ASSIGN(TestAutoFillManager); }; @@ -293,11 +309,12 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsEmptyValue) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -338,11 +355,12 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsMatchCharacter) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "E", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -394,8 +412,109 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsUnknownFields) { autofill_test::CreateTestFormField( "Username", "username", "", "text", &field); + rvh()->ResetAutoFillState(kPageID); EXPECT_FALSE( - autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + autofill_manager_->GetAutoFillSuggestions(false, field)); +} + +// Test that we return no suggestions when autofill is disabled. +TEST_F(AutoFillManagerTest, GetProfileSuggestionsAutofillDisabledByUser) { + FormData form; + CreateTestAddressFormData(&form); + + // Set up our FormStructures. + std::vector forms; + forms.push_back(form); + autofill_manager_->FormsSeen(forms); + + // Disable AutoFill. + autofill_manager_->set_autofill_enabled(false); + + // The page ID sent to the AutoFillManager from the RenderView, used to send + // an IPC message back to the renderer. + const int kPageID = 1; + + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First Name", "firstname", "", "text", &field); + rvh()->ResetAutoFillState(kPageID); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); +} + +// Test that we return a warning explaining that autofill suggestions are +// unavailable when the form method is GET rather than POST. +TEST_F(AutoFillManagerTest, GetProfileSuggestionsMethodGet) { + FormData form; + CreateTestAddressFormData(&form); + form.method = ASCIIToUTF16("GET"); + + // Set up our FormStructures. + std::vector forms; + forms.push_back(form); + autofill_manager_->FormsSeen(forms); + + // The page ID sent to the AutoFillManager from the RenderView, used to send + // an IPC message back to the renderer. + const int kPageID = 1; + + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First Name", "firstname", "", "text", &field); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + + // No suggestions provided, so send an empty vector as the results. + // This triggers the combined message send. + rvh()->AutocompleteSuggestionsReturned(std::vector()); + + // Test that we sent the right message to the renderer. + int page_id = 0; + std::vector values; + std::vector labels; + std::vector icons; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, + &icons)); + EXPECT_EQ(kPageID, page_id); + ASSERT_EQ(1U, values.size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED), + values[0]); + ASSERT_EQ(1U, labels.size()); + EXPECT_EQ(string16(), labels[0]); + ASSERT_EQ(1U, icons.size()); + EXPECT_EQ(string16(), icons[0]); + + // Now add some Autocomplete suggestions. We should return the autocomplete + // suggestions and the warning; these will be culled by the renderer. + process()->sink().ClearMessages(); + const int kPageID2 = 2; + rvh()->ResetAutoFillState(kPageID2); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + + std::vector suggestions; + suggestions.push_back(ASCIIToUTF16("Jay")); + suggestions.push_back(ASCIIToUTF16("Jason")); + rvh()->AutocompleteSuggestionsReturned(suggestions); + + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, + &icons)); + EXPECT_EQ(kPageID2, page_id); + ASSERT_EQ(3U, values.size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED), + values[0]); + EXPECT_EQ(ASCIIToUTF16("Jay"), values[1]); + EXPECT_EQ(ASCIIToUTF16("Jason"), values[2]); + ASSERT_EQ(3U, labels.size()); + EXPECT_EQ(string16(), labels[0]); + EXPECT_EQ(string16(), labels[1]); + EXPECT_EQ(string16(), labels[2]); + ASSERT_EQ(3U, icons.size()); + EXPECT_EQ(string16(), icons[0]); + EXPECT_EQ(string16(), icons[1]); + EXPECT_EQ(string16(), icons[2]); + + // Now clear the test profiles and try again -- we shouldn't return a warning. + test_personal_data_->ClearAutoFillProfiles(); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); } // Test that we return all credit card profile suggestions when all form fields @@ -416,11 +535,12 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsEmptyValue) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -459,11 +579,12 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsMatchCharacter) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "Card Number", "cardnumber", "4", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -499,11 +620,12 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "Name on Card", "nameoncard", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -524,8 +646,8 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) { EXPECT_EQ(ASCIIToUTF16("masterCardCC"), icons[1]); } -// Test that we return no credit card profile suggestions when the form is not -// https. +// Test that we return a warning explaining that credit card profile suggestions +// are unavailable when the form is not https. TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonHTTPS) { FormData form; CreateTestCreditCardFormData(&form, false); @@ -542,8 +664,61 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonHTTPS) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - EXPECT_FALSE( - autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + + // No suggestions provided, so send an empty vector as the results. + // This triggers the combined message send. + rvh()->AutocompleteSuggestionsReturned(std::vector()); + + // Test that we sent the right message to the renderer. + int page_id = 0; + std::vector values; + std::vector labels; + std::vector icons; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, + &icons)); + EXPECT_EQ(kPageID, page_id); + ASSERT_EQ(1U, values.size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), + values[0]); + ASSERT_EQ(1U, labels.size()); + EXPECT_EQ(string16(), labels[0]); + ASSERT_EQ(1U, icons.size()); + EXPECT_EQ(string16(), icons[0]); + + // Now add some Autocomplete suggestions. We should show the autocomplete + // suggestions and the warning. + process()->sink().ClearMessages(); + const int kPageID2 = 2; + rvh()->ResetAutoFillState(kPageID2); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + + std::vector suggestions; + suggestions.push_back(ASCIIToUTF16("Jay")); + suggestions.push_back(ASCIIToUTF16("Jason")); + rvh()->AutocompleteSuggestionsReturned(suggestions); + + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, + &icons)); + EXPECT_EQ(kPageID2, page_id); + ASSERT_EQ(3U, values.size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), + values[0]); + EXPECT_EQ(ASCIIToUTF16("Jay"), values[1]); + EXPECT_EQ(ASCIIToUTF16("Jason"), values[2]); + ASSERT_EQ(3U, labels.size()); + EXPECT_EQ(string16(), labels[0]); + EXPECT_EQ(string16(), labels[1]); + EXPECT_EQ(string16(), labels[2]); + ASSERT_EQ(3U, icons.size()); + EXPECT_EQ(string16(), icons[0]); + EXPECT_EQ(string16(), icons[1]); + EXPECT_EQ(string16(), icons[2]); + + // Clear the test credit cards and try again -- we shouldn't return a warning. + test_personal_data_->ClearCreditCards(); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); } // Test that we return profile and credit card suggestions for combined forms. @@ -564,11 +739,12 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right address suggestions to the renderer. int page_id = 0; @@ -593,11 +769,12 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { process()->sink().ClearMessages(); autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the credit card suggestions to the renderer. page_id = 0; @@ -616,7 +793,9 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { } // Test that for non-https forms with both address and credit card fields, we -// only return address suggestions. +// only return address suggestions. Instead of credit card suggestions, we +// should return a warning explaining that credit card profile suggestions are +// unavailable when the form is not https. TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) { FormData form; CreateTestAddressFormData(&form); @@ -634,11 +813,12 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right address suggestions to the renderer. int page_id = 0; @@ -660,10 +840,31 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) { EXPECT_EQ(string16(), icons[0]); EXPECT_EQ(string16(), icons[1]); + process()->sink().ClearMessages(); autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - EXPECT_FALSE( - autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + + // No suggestions provided, so send an empty vector as the results. + // This triggers the combined message send. + rvh()->AutocompleteSuggestionsReturned(std::vector()); + + // Test that we sent the right message to the renderer. + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, + &icons)); + EXPECT_EQ(kPageID, page_id); + ASSERT_EQ(1U, values.size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), + values[0]); + ASSERT_EQ(1U, labels.size()); + EXPECT_EQ(string16(), labels[0]); + ASSERT_EQ(1U, icons.size()); + EXPECT_EQ(string16(), icons[0]); + + // Clear the test credit cards and try again -- we shouldn't return a warning. + test_personal_data_->ClearCreditCards(); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); } // Test that we correctly combine autofill and autocomplete suggestions. @@ -683,14 +884,15 @@ TEST_F(AutoFillManagerTest, GetCombinedAutoFillAndAutocompleteSuggestions) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); // Add some Autocomplete suggestions. // This triggers the combined message send. std::vector suggestions; suggestions.push_back(ASCIIToUTF16("Jay")); suggestions.push_back(ASCIIToUTF16("Jason")); - rvh()->AutocompleteSuggestionsReturned(kPageID, suggestions); + rvh()->AutocompleteSuggestionsReturned(suggestions); // Test that we sent the right message to the renderer. int page_id = 0; @@ -735,11 +937,12 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsFieldIsAutoFilled) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, true, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(true, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; @@ -778,14 +981,15 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsForAutocompleteOnly) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "Some Field", "somefield", "", "text", &field); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(kPageID, true, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(true, field)); // Add some Autocomplete suggestions. // This triggers the combined message send. std::vector suggestions; suggestions.push_back(ASCIIToUTF16("one")); suggestions.push_back(ASCIIToUTF16("two")); - rvh()->AutocompleteSuggestionsReturned(kPageID, suggestions); + rvh()->AutocompleteSuggestionsReturned(suggestions); // Test that we sent the right message to the renderer. int page_id = 0; @@ -830,11 +1034,12 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsWithDuplicateValues) { webkit_glue::FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, true, field)); + rvh()->ResetAutoFillState(kPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(true, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. - rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector()); + rvh()->AutocompleteSuggestionsReturned(std::vector()); // Test that we sent the right message to the renderer. int page_id = 0; diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc index 3ce4b67..9f760b8 100644 --- a/chrome/browser/autofill/autofill_profile.cc +++ b/chrome/browser/autofill/autofill_profile.cc @@ -434,6 +434,11 @@ bool AutoFillProfile::operator!=(const AutoFillProfile& profile) const { return !operator==(profile); } +const string16 AutoFillProfile::PrimaryValue() const { + return GetFieldText(AutoFillType(NAME_FULL)) + + GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)); +} + Address* AutoFillProfile::GetHomeAddress() { return static_cast(personal_info_[AutoFillType::ADDRESS_HOME]); } diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h index 7244641..d201294 100644 --- a/chrome/browser/autofill/autofill_profile.h +++ b/chrome/browser/autofill/autofill_profile.h @@ -101,6 +101,11 @@ class AutoFillProfile : public FormGroup { virtual bool operator!=(const AutoFillProfile& profile) const; void set_label(const string16& label) { label_ = label; } + // Returns concatenation of full name and address line 1. This acts as the + // basis of comparison for new values that are submitted through forms to + // aid with correct aggregation of new data. + const string16 PrimaryValue() const; + private: Address* GetHomeAddress(); diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc index 3c4f8b2..0ca5e45 100644 --- a/chrome/browser/autofill/credit_card.cc +++ b/chrome/browser/autofill/credit_card.cc @@ -25,7 +25,6 @@ namespace { -const string16::value_type kCreditCardSeparators[] = {' ','-',0}; const char* kCreditCardObfuscationString = "************"; const AutoFillFieldType kAutoFillCreditCardTypes[] = { @@ -130,6 +129,16 @@ std::string GetCreditCardType(const string16& number) { return kGenericCard; } +// Return a version of |number| that has had any non-digit values removed. +const string16 RemoveNonAsciiDigits(const string16& number) { + string16 stripped; + for (size_t i = 0; i < number.size(); ++i) { + if (IsAsciiDigit(number[i])) + stripped.append(1, number[i]); + } + return stripped; +} + } // namespace CreditCard::CreditCard(const std::string& guid) @@ -297,6 +306,10 @@ void CreditCard::SetInfo(const AutoFillType& type, const string16& value) { SetExpirationMonthFromString(value); break; + case CREDIT_CARD_EXP_2_DIGIT_YEAR: + // This is a read-only attribute. + break; + case CREDIT_CARD_EXP_4_DIGIT_YEAR: SetExpirationYearFromString(value); break; @@ -418,8 +431,10 @@ bool CreditCard::operator!=(const CreditCard& credit_card) const { // Use the Luhn formula to validate the number. // static bool CreditCard::IsCreditCardNumber(const string16& text) { - string16 number; - RemoveChars(text, kCreditCardSeparators, &number); + string16 number = RemoveNonAsciiDigits(text); + + if (number.empty()) + return false; int sum = 0; bool odd = false; @@ -490,6 +505,10 @@ void CreditCard::SetExpirationYearFromString(const string16& text) { set_expiration_year(year); } +void CreditCard::set_number(const string16& number) { + number_ = RemoveNonAsciiDigits(number); +} + void CreditCard::set_expiration_month(int expiration_month) { if (expiration_month < 0 || expiration_month > 12) return; diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h index 91fc6ce..b6fdfde 100644 --- a/chrome/browser/autofill/credit_card.h +++ b/chrome/browser/autofill/credit_card.h @@ -70,6 +70,9 @@ class CreditCard : public FormGroup { // Returns true if there are no values (field types) set. bool IsEmpty() const; + // Returns the credit card number. + const string16& number() const { return number_; } + private: // The month and year are zero if not present. int Expiration4DigitYear() const { return expiration_year_; } @@ -84,13 +87,12 @@ class CreditCard : public FormGroup { // Sets |expiration_year_| to the integer conversion of |text|. void SetExpirationYearFromString(const string16& text); - const string16& number() const { return number_; } const string16& name_on_card() const { return name_on_card_; } const string16& last_four_digits() const { return last_four_digits_; } int expiration_month() const { return expiration_month_; } int expiration_year() const { return expiration_year_; } - void set_number(const string16& number) { number_ = number; } + void set_number(const string16& number); void set_name_on_card(const string16& name_on_card) { name_on_card_ = name_on_card; } diff --git a/chrome/browser/autofill/form_group.cc b/chrome/browser/autofill/form_group.cc index 7e91bc3..49beb16 100644 --- a/chrome/browser/autofill/form_group.cc +++ b/chrome/browser/autofill/form_group.cc @@ -76,3 +76,13 @@ void FormGroup::MergeWith(const FormGroup& form_group) { SetInfo(type, form_group.GetFieldText(type)); } } + +void FormGroup::OverwriteWith(const FormGroup& form_group) { + FieldTypeSet a;; + form_group.GetAvailableFieldTypes(&a); + + for (FieldTypeSet::const_iterator iter = a.begin(); iter != a.end(); ++iter) { + AutoFillType type(*iter); + SetInfo(type, form_group.GetFieldText(type)); + } +} diff --git a/chrome/browser/autofill/form_group.h b/chrome/browser/autofill/form_group.h index 5f16276..b1b2243 100644 --- a/chrome/browser/autofill/form_group.h +++ b/chrome/browser/autofill/form_group.h @@ -69,6 +69,9 @@ class FormGroup { // Merges the field data in |form_group| with this FormGroup. void MergeWith(const FormGroup& form_group); + + // Overwrites the field data in |form_group| with this FormGroup. + void OverwriteWith(const FormGroup& form_group); }; #endif // CHROME_BROWSER_AUTOFILL_FORM_GROUP_H_ diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc index d9ff45b..509ee33 100644 --- a/chrome/browser/autofill/form_structure.cc +++ b/chrome/browser/autofill/form_structure.cc @@ -117,7 +117,7 @@ bool FormStructure::EncodeUploadRequest(bool auto_fill_used, std::string* encoded_xml) const { DCHECK(encoded_xml); encoded_xml->clear(); - bool auto_fillable = IsAutoFillable(); + bool auto_fillable = IsAutoFillable(false); DCHECK(auto_fillable); // Caller should've checked for search pages. if (!auto_fillable) return false; @@ -242,8 +242,6 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, form->UpdateAutoFillCount(); } - - return; } std::string FormStructure::FormSignature() const { @@ -257,11 +255,11 @@ std::string FormStructure::FormSignature() const { return Hash64Bit(form_string); } -bool FormStructure::IsAutoFillable() const { +bool FormStructure::IsAutoFillable(bool require_method_post) const { if (autofill_count() < kRequiredFillableFields) return false; - return ShouldBeParsed(); + return ShouldBeParsed(require_method_post); } bool FormStructure::HasAutoFillableValues() const { @@ -278,46 +276,6 @@ bool FormStructure::HasAutoFillableValues() const { return false; } -// TODO(jhawkins): Cache this result. -bool FormStructure::HasBillingFields() const { - for (std::vector::const_iterator iter = begin(); - iter != end(); ++iter) { - if (!*iter) - return false; - - AutoFillField* field = *iter; - if (!field) - continue; - - AutoFillType type(field->type()); - if (type.group() == AutoFillType::ADDRESS_BILLING || - type.group() == AutoFillType::CREDIT_CARD) - return true; - } - - return false; -} - -// TODO(jhawkins): Cache this result. -bool FormStructure::HasNonBillingFields() const { - for (std::vector::const_iterator iter = begin(); - iter != end(); ++iter) { - if (!*iter) - return false; - - AutoFillField* field = *iter; - if (!field) - continue; - - AutoFillType type(field->type()); - if (type.group() != AutoFillType::ADDRESS_BILLING && - type.group() != AutoFillType::CREDIT_CARD) - return true; - } - - return false; -} - void FormStructure::UpdateAutoFillCount() { autofill_count_ = 0; for (std::vector::const_iterator iter = begin(); @@ -328,7 +286,7 @@ void FormStructure::UpdateAutoFillCount() { } } -bool FormStructure::ShouldBeParsed() const { +bool FormStructure::ShouldBeParsed(bool require_method_post) const { if (field_count() < kRequiredFillableFields) return false; @@ -338,10 +296,7 @@ bool FormStructure::ShouldBeParsed() const { if (target_url_.path() == "/search") return false; - if (method_ == GET) - return false; - - return true; + return !require_method_post || (method_ == POST); } void FormStructure::set_possible_types(int index, const FieldTypeSet& types) { diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h index 77e106f..fe4c5da 100644 --- a/chrome/browser/autofill/form_structure.h +++ b/chrome/browser/autofill/form_structure.h @@ -61,22 +61,15 @@ class FormStructure { // the form name, and the form field names in a 64-bit hash. std::string FormSignature() const; - // Runs a quick heuristic to rule out pages but obviously not auto-fillable, - // like google/yahoo/msn search, etc. - bool IsAutoFillable() const; + // Runs a quick heuristic to rule out forms that are obviously not + // auto-fillable, like google/yahoo/msn search, etc. The requirement that the + // form's method be POST is only applied if |require_method_post| is true. + bool IsAutoFillable(bool require_method_post) const; // Returns true if at least one of the form fields relevant for AutoFill // is not empty. bool HasAutoFillableValues() const; - // Returns true if at least one of the form fields is a billing field, which - // includes billing address fields and credit card fields. - bool HasBillingFields() const; - - // Returns true if at least one of the form fields is a non-billing field, - // which includes billing address fields and credit card fields. - bool HasNonBillingFields() const; - // Resets |autofill_count_| and counts the number of auto-fillable fields. // This is used when we receive server data for form fields. At that time, // we may have more known fields than just the number of fields we matched @@ -84,7 +77,9 @@ class FormStructure { void UpdateAutoFillCount(); // Returns true if this form matches the structural requirements for AutoFill. - bool ShouldBeParsed() const; + // The requirement that the form's method be POST is only applied if + // |require_method_post| is true. + bool ShouldBeParsed(bool require_method_post) const; // Sets the possible types for the field at |index|. void set_possible_types(int index, const FieldTypeSet& types); diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc index b5881d6..8eb03fd 100644 --- a/chrome/browser/autofill/form_structure_unittest.cc +++ b/chrome/browser/autofill/form_structure_unittest.cc @@ -199,7 +199,7 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_FALSE(form_structure->IsAutoFillable()); + EXPECT_FALSE(form_structure->IsAutoFillable(true)); // We now have three text fields, but only two auto-fillable fields. form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"), @@ -213,7 +213,7 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_FALSE(form_structure->IsAutoFillable()); + EXPECT_FALSE(form_structure->IsAutoFillable(true)); // We now have three auto-fillable fields. form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Email"), @@ -222,23 +222,25 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); - // The method must be 'post'. + // The method must be 'post', though we can intentionally ignore this + // criterion for the sake of providing a helpful warning message to the user. form.method = ASCIIToUTF16("get"); form_structure.reset(new FormStructure(form)); - EXPECT_FALSE(form_structure->IsAutoFillable()); + EXPECT_FALSE(form_structure->IsAutoFillable(true)); + EXPECT_TRUE(form_structure->IsAutoFillable(false)); // The target cannot include http(s)://*/search... form.method = ASCIIToUTF16("post"); form.action = GURL("http://google.com/search?q=hello"); form_structure.reset(new FormStructure(form)); - EXPECT_FALSE(form_structure->IsAutoFillable()); + EXPECT_FALSE(form_structure->IsAutoFillable(true)); // But search can be in the URL. form.action = GURL("http://search.com/?q=hello"); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); } TEST(FormStructureTest, HeuristicsContactInfo) { @@ -292,7 +294,7 @@ TEST(FormStructureTest, HeuristicsContactInfo) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); // Expect the correct number of fields. ASSERT_EQ(9U, form_structure->field_count()); @@ -410,7 +412,7 @@ TEST(FormStructureTest, HeuristicsHiddenFields) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); // Expect the correct number of fields. ASSERT_EQ(17U, form_structure->field_count()); @@ -503,7 +505,7 @@ TEST(FormStructureTest, HeuristicsSample8) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(10U, form_structure->field_count()); ASSERT_EQ(9U, form_structure->autofill_count()); @@ -581,7 +583,7 @@ TEST(FormStructureTest, HeuristicsSample6) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(7U, form_structure->field_count()); ASSERT_EQ(6U, form_structure->autofill_count()); @@ -655,7 +657,7 @@ TEST(FormStructureTest, HeuristicsLabelsOnly) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(9U, form_structure->field_count()); ASSERT_EQ(8U, form_structure->autofill_count()); @@ -716,7 +718,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfo) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(6U, form_structure->field_count()); ASSERT_EQ(4U, form_structure->autofill_count()); @@ -778,7 +780,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(7U, form_structure->field_count()); ASSERT_EQ(4U, form_structure->autofill_count()); @@ -829,7 +831,7 @@ TEST(FormStructureTest, ThreeAddressLines) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(3U, form_structure->autofill_count()); @@ -875,7 +877,7 @@ TEST(FormStructureTest, BillingAndShippingAddresses) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(4U, form_structure->autofill_count()); @@ -925,7 +927,7 @@ TEST(FormStructureTest, ThreeAddressLinesExpedia) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(3U, form_structure->autofill_count()); @@ -966,7 +968,7 @@ TEST(FormStructureTest, TwoAddressLinesEbay) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(3U, form_structure->field_count()); ASSERT_EQ(3U, form_structure->autofill_count()); @@ -1002,7 +1004,7 @@ TEST(FormStructureTest, HeuristicsStateWithProvince) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(3U, form_structure->field_count()); ASSERT_EQ(3U, form_structure->autofill_count()); @@ -1087,7 +1089,7 @@ TEST(FormStructureTest, HeuristicsWithBilling) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(11U, form_structure->field_count()); ASSERT_EQ(11U, form_structure->autofill_count()); @@ -1136,7 +1138,7 @@ TEST(FormStructureTest, ThreePartPhoneNumber) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); ASSERT_EQ(3U, form_structure->autofill_count()); @@ -1207,7 +1209,7 @@ TEST(FormStructureTest, MatchSpecificInputTypes) { ASCIIToUTF16("submit"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); // Expect the correct number of fields. ASSERT_EQ(10U, form_structure->field_count()); @@ -1266,7 +1268,7 @@ TEST(FormStructureTest, HeuristicsInfernoCC) { ASCIIToUTF16("text"), 0)); form_structure.reset(new FormStructure(form)); - EXPECT_TRUE(form_structure->IsAutoFillable()); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); // Expect the correct number of fields. ASSERT_EQ(5U, form_structure->field_count()); diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc index e085edf..c978aae 100644 --- a/chrome/browser/autofill/personal_data_manager.cc +++ b/chrome/browser/autofill/personal_data_manager.cc @@ -10,7 +10,6 @@ #include "base/logging.h" #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/autofill/autofill_manager.h" #include "chrome/browser/autofill/autofill_field.h" #include "chrome/browser/autofill/form_structure.h" #include "chrome/browser/autofill/phone_number.h" @@ -169,6 +168,7 @@ void PersonalDataManager::RemoveObserver( } bool PersonalDataManager::ImportFormData( +<<<<<<< HEAD const std::vector& form_structures, AutoFillManager* autofill_manager) { #ifdef ANDROID @@ -176,6 +176,9 @@ bool PersonalDataManager::ImportFormData( // based on what they've entered into forms? return false; #else +======= + const std::vector& form_structures) { +>>>>>>> chromium.org at r66597 // Parse the form and construct a profile based on the information that is // possible to import. int importable_fields = 0; @@ -184,7 +187,6 @@ bool PersonalDataManager::ImportFormData( // TODO(jhawkins): Use a hash of the CC# instead of a list of unique IDs? imported_credit_card_.reset(new CreditCard); - bool billing_address_info = false; std::vector::const_iterator iter; for (iter = form_structures.begin(); iter != form_structures.end(); ++iter) { const FormStructure* form = *iter; @@ -239,12 +241,6 @@ bool PersonalDataManager::ImportFormData( imported_profile_->SetInfo(AutoFillType(field_type.field_type()), value); - - // If we found any billing address information, then set the profile to - // use a separate billing address. - if (group == AutoFillType::ADDRESS_BILLING) - billing_address_info = true; - ++importable_fields; } } @@ -261,6 +257,25 @@ bool PersonalDataManager::ImportFormData( if (importable_credit_card_fields == 0) imported_credit_card_.reset(); + if (imported_credit_card_.get()) { + if (!CreditCard::IsCreditCardNumber(imported_credit_card_->GetFieldText( + AutoFillType(CREDIT_CARD_NUMBER)))) { + imported_credit_card_.reset(); + } + } + + // Don't import if we already have this info. + if (imported_credit_card_.get()) { + for (std::vector::const_iterator iter = credit_cards_.begin(); + iter != credit_cards_.end(); + ++iter) { + if (imported_credit_card_->IsSubsetOf(**iter)) { + imported_credit_card_.reset(); + break; + } + } + } + // We always save imported profiles. SaveImportedProfile(); @@ -396,9 +411,6 @@ void PersonalDataManager::SetCreditCards( // TODO(jhawkins): Refactor SetProfiles so this isn't so hacky. void PersonalDataManager::AddProfile(const AutoFillProfile& profile) { - // Set to true if |profile| is merged into the profile list. - bool merged = false; - // Don't save a web profile if the data in the profile is a subset of an // auxiliary profile. for (std::vector::const_iterator iter = @@ -408,24 +420,50 @@ void PersonalDataManager::AddProfile(const AutoFillProfile& profile) { return; } + // Set to true if |profile| is merged into the profile list. + bool merged = false; + + // First preference is to add missing values to an existing profile. + // Only merge with the first match. std::vector profiles; for (std::vector::const_iterator iter = web_profiles_.begin(); iter != web_profiles_.end(); ++iter) { - if (profile.IsSubsetOf(**iter)) { - // In this case, the existing profile already contains all of the data - // in |profile|, so consider the profiles already merged. - merged = true; - } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) { - // |profile| contains all of the data in this profile, plus - // more. - merged = true; - (*iter)->MergeWith(profile); + if (!merged) { + if (profile.IsSubsetOf(**iter)) { + // In this case, the existing profile already contains all of the data + // in |profile|, so consider the profiles already merged. + merged = true; + } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) { + // |profile| contains all of the data in this profile, plus more. + merged = true; + (*iter)->MergeWith(profile); + } } - profiles.push_back(**iter); } + // The second preference, if not merged above, is to alter non-primary values + // where the primary values match. + // Again, only merge with the first match. + if (!merged) { + profiles.clear(); + for (std::vector::const_iterator iter = + web_profiles_.begin(); + iter != web_profiles_.end(); ++iter) { + if (!merged) { + if (!profile.PrimaryValue().empty() && + (*iter)->PrimaryValue() == profile.PrimaryValue()) { + merged = true; + (*iter)->OverwriteWith(profile); + } + } + profiles.push_back(**iter); + } + } + + // Finally, if the new profile was not merged with an existing profile then + // add the new profile to the list. if (!merged) profiles.push_back(profile); @@ -793,10 +831,13 @@ void PersonalDataManager::SaveImportedCreditCard() { merged = true; } else if ((*iter)->IntersectionOfTypesHasEqualValues( *imported_credit_card_)) { - // |imported_profile| contains all of the data in this profile, plus - // more. + // |imported_profile| contains all of the data in this profile, plus more. merged = true; (*iter)->MergeWith(*imported_credit_card_); + } else if (!imported_credit_card_->number().empty() && + (*iter)->number() == imported_credit_card_->number()) { + merged = true; + (*iter)->OverwriteWith(*imported_credit_card_); } creditcards.push_back(**iter); diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h index 38d1979..114c109 100644 --- a/chrome/browser/autofill/personal_data_manager.h +++ b/chrome/browser/autofill/personal_data_manager.h @@ -67,8 +67,7 @@ class PersonalDataManager // field types that contain information in the FormStructures a profile will // be created with all of the information from recognized fields. Returns // whether a profile was created. - bool ImportFormData(const std::vector& form_structures, - AutoFillManager* autofill_manager); + bool ImportFormData(const std::vector& form_structures); // Gets |imported_profile_| and |imported_credit_card_| and returns their // values in |profile| and |credit_card| parameters respectively. One or diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc index 2947e08..7c2fc5f 100644 --- a/chrome/browser/autofill/personal_data_manager_unittest.cc +++ b/chrome/browser/autofill/personal_data_manager_unittest.cc @@ -500,7 +500,7 @@ TEST_F(PersonalDataManagerTest, Refresh) { update.push_back(profile2); personal_data_->SetProfiles(&update); - // And wait for the refresh. + // Wait for the refresh. EXPECT_CALL(personal_data_observer_, OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); @@ -526,9 +526,9 @@ TEST_F(PersonalDataManagerTest, ImportFormData) { FormStructure form_structure(form); std::vector forms; forms.push_back(&form_structure); - personal_data_->ImportFormData(forms, NULL); + personal_data_->ImportFormData(forms); - // And wait for the refresh. + // Wait for the refresh. EXPECT_CALL(personal_data_observer_, OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); @@ -604,123 +604,705 @@ TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) { EXPECT_EQ(ASCIIToUTF16("Work2"), results[5]->Label()); } -TEST_F(PersonalDataManagerTest, AggregateProfileData) { - scoped_ptr form(new FormData); - +TEST_F(PersonalDataManagerTest, AggregateTwoDifferentProfiles) { + FormData form1; webkit_glue::FormField field; autofill_test::CreateTestFormField( "First name:", "first_name", "George", "text", &field); - form->fields.push_back(field); + form1.fields.push_back(field); autofill_test::CreateTestFormField( "Last name:", "last_name", "Washington", "text", &field); - form->fields.push_back(field); + form1.fields.push_back(field); autofill_test::CreateTestFormField( "Email:", "email", "theprez@gmail.com", "text", &field); - form->fields.push_back(field); + form1.fields.push_back(field); - scoped_ptr form_structure(new FormStructure(*form)); - scoped_ptr > forms( - new std::vector); - forms->push_back(form_structure.get()); - personal_data_->ImportFormData(*forms, NULL); + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); - // And wait for the refresh. + // Wait for the refresh. EXPECT_CALL(personal_data_observer_, OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); MessageLoop::current()->Run(); - scoped_ptr expected( - new AutoFillProfile); - autofill_test::SetProfileInfo(expected.get(), NULL, "George", NULL, + AutoFillProfile expected; + autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, "Washington", "theprez@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - const std::vector& results = personal_data_->profiles(); - ASSERT_EQ(1U, results.size()); - EXPECT_EQ(0, expected->Compare(*results[0])); + const std::vector& results1 = personal_data_->profiles(); + ASSERT_EQ(1U, results1.size()); + EXPECT_EQ(0, expected.Compare(*results1[0])); // Now create a completely different profile. - form.reset(new FormData); + FormData form2; autofill_test::CreateTestFormField( "First name:", "first_name", "John", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "Last name:", "last_name", "Adams", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "Email:", "email", "second@gmail.com", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); - form_structure.reset(new FormStructure(*form)); - forms.reset(new std::vector); - forms->push_back(form_structure.get()); - personal_data_->ImportFormData(*forms, NULL); + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); - // And wait for the refresh. + // Wait for the refresh. EXPECT_CALL(personal_data_observer_, OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); MessageLoop::current()->Run(); const std::vector& results2 = personal_data_->profiles(); + + AutoFillProfile expected2; + autofill_test::SetProfileInfo(&expected2, NULL, "John", NULL, + "Adams", "second@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL); ASSERT_EQ(2U, results2.size()); + EXPECT_EQ(0, expected.Compare(*results2[0])); + EXPECT_EQ(0, expected2.Compare(*results2[1])); +} + +TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { + FormData form1; + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Address:", "address", "1600 Pennsylvania Avenue", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + AutoFillProfile expected; + autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, + "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + const std::vector& results1 = personal_data_->profiles(); + ASSERT_EQ(1U, results1.size()); + EXPECT_EQ(0, expected.Compare(*results1[0])); + + // Now create an updated profile. + FormData form2; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Address:", "address", "1600 Pennsylvania Avenue", "text", &field); + form2.fields.push_back(field); + // Country gets added. + autofill_test::CreateTestFormField( + "Country:", "country", "USA", "text", &field); + form2.fields.push_back(field); + // Email gets updated. + autofill_test::CreateTestFormField( + "Email:", "email", "new_email@gmail.com", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + const std::vector& results2 = personal_data_->profiles(); + + AutoFillProfile expected2; + autofill_test::SetProfileInfo(&expected2, NULL, "George", NULL, + "Washington", "new_email@gmail.com", NULL, "1600 Pennsylvania Avenue", + NULL, NULL, NULL, NULL, "USA", NULL, NULL); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); +} + +TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInOld) { + FormData form1; + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); - expected.reset(new AutoFillProfile); - autofill_test::SetProfileInfo(expected.get(), NULL, "George", NULL, + MessageLoop::current()->Run(); + + AutoFillProfile expected; + autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, "Washington", "theprez@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - EXPECT_EQ(0, expected->Compare(*results2[0])); - - expected.reset(new AutoFillProfile); - autofill_test::SetProfileInfo(expected.get(), NULL, "John", NULL, - "Adams", "second@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); - EXPECT_EQ(0, expected->Compare(*results2[1])); + const std::vector& results1 = personal_data_->profiles(); + ASSERT_EQ(1U, results1.size()); + EXPECT_EQ(0, expected.Compare(*results1[0])); // Submit a form with new data for the first profile. - form.reset(new FormData); + FormData form2; autofill_test::CreateTestFormField( "First name:", "first_name", "George", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "Last name:", "last_name", "Washington", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "Address Line 1:", "address", "190 High Street", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "City:", "city", "Philadelphia", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "State:", "state", "Pennsylvania", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); autofill_test::CreateTestFormField( "Zip:", "zipcode", "19106", "text", &field); - form->fields.push_back(field); + form2.fields.push_back(field); - form_structure.reset(new FormStructure(*form)); - forms.reset(new std::vector); - forms->push_back(form_structure.get()); - personal_data_->ImportFormData(*forms, NULL); + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); - // And wait for the refresh. + // Wait for the refresh. EXPECT_CALL(personal_data_observer_, OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); MessageLoop::current()->Run(); - const std::vector& results3 = personal_data_->profiles(); - ASSERT_EQ(2U, results3.size()); + const std::vector& results2 = personal_data_->profiles(); - expected.reset(new AutoFillProfile); - autofill_test::SetProfileInfo(expected.get(), NULL, "George", NULL, + AutoFillProfile expected2; + autofill_test::SetProfileInfo(&expected2, NULL, "George", NULL, "Washington", "theprez@gmail.com", NULL, "190 High Street", NULL, "Philadelphia", "Pennsylvania", "19106", NULL, NULL, NULL); - EXPECT_EQ(0, expected->Compare(*results3[0])); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); +} - expected.reset(new AutoFillProfile); - autofill_test::SetProfileInfo(expected.get(), NULL, "John", NULL, - "Adams", "second@gmail.com", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); - EXPECT_EQ(0, expected->Compare(*results3[1])); +TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInNew) { + FormData form1; + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Company:", "company", "Government", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + AutoFillProfile expected; + autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, + "Washington", "theprez@gmail.com", "Government", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + const std::vector& results1 = personal_data_->profiles(); + ASSERT_EQ(1U, results1.size()); + EXPECT_EQ(0, expected.Compare(*results1[0])); + + // Submit a form with new data for the first profile. + FormData form2; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form2.fields.push_back(field); + // Note missing Company field. + autofill_test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + const std::vector& results2 = personal_data_->profiles(); + + // Expect no change. + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected.Compare(*results2[0])); +} + +TEST_F(PersonalDataManagerTest, AggregateTwoDifferentCreditCards) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second different valid credit card. + FormData form2; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Jim Johansen", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "5500 0000 0000 0004", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "02", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2012", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected2; + autofill_test::SetCreditCardInfo(&expected2, + "L2", "Jim Johansen", "5500000000000004", "02", "2012"); + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(2U, results2.size()); + EXPECT_EQ(0, expected.Compare(*results2[0])); + EXPECT_EQ(0, expected2.Compare(*results2[1])); +} + +TEST_F(PersonalDataManagerTest, AggregateInvalidCreditCard) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second different invalid credit card. + FormData form2; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Jim Johansen", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "1000000000000000", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "02", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2012", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Note: no refresh here. + + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected.Compare(*results2[0])); +} + +TEST_F(PersonalDataManagerTest, AggregateSameCreditCardWithConflict) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second different valid credit card where the year is different but + // the credit card number matches. + FormData form2; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111 1111 1111 1111", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2012", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + // Expect that the newer information is saved. In this case the year is + // updated to "2012". + CreditCard expected2; + autofill_test::SetCreditCardInfo(&expected2, + "L1", "Biggie Smalls", "4111111111111111", "01", "2012"); + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); } + +TEST_F(PersonalDataManagerTest, AggregateEmptyCreditCardWithConflict) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second credit card with no number. + FormData form2; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2012", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Note: no refresh here. + + // No change is expected. + CreditCard expected2; + autofill_test::SetCreditCardInfo(&expected2, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); +} + +TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInNew) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second different valid credit card where the name is missing but + // the credit card number matches. + FormData form2; + // Note missing name. + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111111111111111", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Note: no refresh here. + + // No change is expected. + CreditCard expected2; + autofill_test::SetCreditCardInfo(&expected2, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); +} + +TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInOld) { + FormData form1; + + // Start with a single valid credit card form. + webkit_glue::FormField field; + // Note missing name. + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form1.fields.push_back(field); + + FormStructure form_structure1(form1); + std::vector forms; + forms.push_back(&form_structure1); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + CreditCard expected; + autofill_test::SetCreditCardInfo(&expected, + "L1", NULL, "4111111111111111", "01", "2011"); + const std::vector& results = personal_data_->credit_cards(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); + + // Add a second different valid credit card where the year is different but + // the credit card number matches. + FormData form2; + autofill_test::CreateTestFormField( + "Name on card:", "name_on_card", "Biggie Smalls", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Month:", "exp_month", "01", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Exp Year:", "exp_year", "2011", "text", &field); + form2.fields.push_back(field); + + FormStructure form_structure2(form2); + forms.clear(); + forms.push_back(&form_structure2); + personal_data_->ImportFormData(forms); + personal_data_->SaveImportedCreditCard(); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + // Expect that the newer information is saved. In this case the year is + // added to the existing credit card. + CreditCard expected2; + autofill_test::SetCreditCardInfo(&expected2, + "L1", "Biggie Smalls", "4111111111111111", "01", "2011"); + const std::vector& results2 = personal_data_->credit_cards(); + ASSERT_EQ(1U, results2.size()); + EXPECT_EQ(0, expected2.Compare(*results2[0])); +} + diff --git a/chrome/browser/automation/automation_browser_tracker.h b/chrome/browser/automation/automation_browser_tracker.h index a58cd1f..147b820 100644 --- a/chrome/browser/automation/automation_browser_tracker.h +++ b/chrome/browser/automation/automation_browser_tracker.h @@ -7,7 +7,7 @@ #pragma once #include "chrome/browser/automation/automation_resource_tracker.h" -#include "chrome/browser/browser.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_source.h" // Tracks Browser objects. diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index cbbc786..ec48e7a 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -85,6 +85,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/translate/translate_infobar_delegate.h" #include "chrome/common/automation_constants.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -95,7 +96,6 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" -#include "chrome/test/automation/automation_messages.h" #include "chrome/test/automation/tab_proxy.h" #include "net/proxy/proxy_service.h" #include "net/proxy/proxy_config_service_fixed.h" @@ -123,7 +123,7 @@ AutomationProvider::AutomationProvider(Profile* profile) autocomplete_edit_tracker_.reset( new AutomationAutocompleteEditTracker(this)); new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this)); - dom_operation_observer_.reset(new DomOperationNotificationObserver(this)); + dom_operation_observer_.reset(new DomOperationMessageSender(this)); metric_event_duration_observer_.reset(new MetricEventDurationObserver()); extension_test_result_observer_.reset( new ExtensionTestResultNotificationObserver(this)); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index 280d916..0da77a1 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -23,9 +23,9 @@ #include "chrome/browser/autofill/field_types.h" #include "chrome/browser/cancelable_request.h" #include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/common/automation_constants.h" #include "chrome/common/content_settings.h" #include "chrome/common/notification_observer.h" -#include "chrome/test/automation/automation_constants.h" #include "ipc/ipc_message.h" #include "ipc/ipc_channel.h" #if defined(OS_WIN) @@ -178,6 +178,10 @@ class AutomationProvider : public base::RefCounted, // Returns the protocol version which typically is the module version. virtual std::string GetProtocolVersion(); + // Returns the associated view for the tab handle passed in. + // Returns NULL on failure. + RenderViewHost* GetViewForTab(int tab_handle); + scoped_ptr autocomplete_edit_tracker_; scoped_ptr browser_tracker_; scoped_ptr initial_load_observer_; @@ -317,10 +321,6 @@ class AutomationProvider : public base::RefCounted, IPC::Message* reply_message); #endif - // Returns the associated view for the tab handle passed in. - // Returns NULL on failure. - RenderViewHost* GetViewForTab(int tab_handle); - // Returns the extension for the given handle. Returns NULL if there is // no extension for the handle. const Extension* GetExtension(int extension_handle); diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc index 37c4fb8..bf6a15c 100644 --- a/chrome/browser/automation/automation_provider_gtk.cc +++ b/chrome/browser/automation/automation_provider_gtk.cc @@ -13,7 +13,7 @@ #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/view_id_util.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "gfx/point.h" #include "gfx/rect.h" diff --git a/chrome/browser/automation/automation_provider_json.cc b/chrome/browser/automation/automation_provider_json.cc index c58b622..16fd8d4 100644 --- a/chrome/browser/automation/automation_provider_json.cc +++ b/chrome/browser/automation/automation_provider_json.cc @@ -8,7 +8,7 @@ #include "base/json/string_escape.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/automation/automation_provider.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" namespace { diff --git a/chrome/browser/automation/automation_provider_mac.mm b/chrome/browser/automation/automation_provider_mac.mm index 99c1bdb..451e7f1 100644 --- a/chrome/browser/automation/automation_provider_mac.mm +++ b/chrome/browser/automation/automation_provider_mac.mm @@ -14,7 +14,7 @@ #include "chrome/browser/cocoa/tab_window_controller.h" #include "chrome/browser/view_ids.h" #import "chrome/browser/cocoa/browser_window_controller.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "gfx/point.h" #include "gfx/rect.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index d5fb64f..46b4470 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -8,16 +8,19 @@ #include "base/basictypes.h" #include "base/callback.h" +#include "base/file_util.h" #include "base/json/json_writer.h" #include "base/scoped_ptr.h" #include "base/string_util.h" +#include "base/stringprintf.h" +#include "base/thread_restrictions.h" #include "base/values.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/automation/automation_provider.h" #include "chrome/browser/automation/automation_provider_json.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/save_package.h" @@ -30,14 +33,18 @@ #include "chrome/browser/notifications/balloon_collection.h" #include "chrome/browser/printing/print_job.h" #include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/thumbnail_generator.h" #include "chrome/browser/translate/page_translated_details.h" #include "chrome/browser/translate/translate_infobar_delegate.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/automation_constants.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" -#include "chrome/test/automation/automation_constants.h" +#include "gfx/codec/png_codec.h" #include "gfx/rect.h" #if defined(OS_CHROMEOS) @@ -897,28 +904,28 @@ void FindInPageNotificationObserver::Observe( // static const int FindInPageNotificationObserver::kFindInPageRequestId = -1; -DomOperationNotificationObserver::DomOperationNotificationObserver( - AutomationProvider* automation) - : automation_(automation) { +DomOperationObserver::DomOperationObserver() { registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, NotificationService::AllSources()); } -DomOperationNotificationObserver::~DomOperationNotificationObserver() { -} - -void DomOperationNotificationObserver::Observe( +void DomOperationObserver::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { if (NotificationType::DOM_OPERATION_RESPONSE == type) { Details dom_op_details(details); + OnDomOperationCompleted(dom_op_details->json()); + } +} - IPC::Message* reply_message = automation_->reply_message_release(); - if (reply_message) { - AutomationMsg_DomOperation::WriteReplyParams(reply_message, - dom_op_details->json()); - automation_->Send(reply_message); - } +void DomOperationMessageSender::OnDomOperationCompleted( + const std::string& json) { + IPC::Message* reply_message = automation_->reply_message_release(); + if (reply_message) { + AutomationMsg_DomOperation::WriteReplyParams(reply_message, json); + automation_->Send(reply_message); + } else { + LOG(ERROR) << "DOM operation completed, but no reply message"; } } @@ -1329,6 +1336,73 @@ void SavePackageNotificationObserver::Observe( } } +PageSnapshotTaker::PageSnapshotTaker(AutomationProvider* automation, + IPC::Message* reply_message, + RenderViewHost* render_view, + const FilePath& path) + : automation_(automation), + reply_message_(reply_message), + render_view_(render_view), + image_path_(path), + received_width_(false) {} + +void PageSnapshotTaker::Start() { + ExecuteScript(L"window.domAutomationController.send(document.width);"); +} + +void PageSnapshotTaker::OnDomOperationCompleted(const std::string& json) { + int dimension; + if (!base::StringToInt(json, &dimension)) { + LOG(ERROR) << "Could not parse received dimensions: " << json; + SendMessage(false); + } else if (!received_width_) { + received_width_ = true; + entire_page_size_.set_width(dimension); + + ExecuteScript(L"window.domAutomationController.send(document.height);"); + } else { + entire_page_size_.set_height(dimension); + + ThumbnailGenerator* generator = + g_browser_process->GetThumbnailGenerator(); + ThumbnailGenerator::ThumbnailReadyCallback* callback = + NewCallback(this, &PageSnapshotTaker::OnSnapshotTaken); + // Don't actually start the thumbnail generator, this leads to crashes on + // Mac, crbug.com/62986. Instead, just hook the generator to the + // RenderViewHost manually. + render_view_->set_painting_observer(generator); + generator->AskForSnapshot(render_view_, false, callback, + entire_page_size_, entire_page_size_); + } +} + +void PageSnapshotTaker::OnSnapshotTaken(const SkBitmap& bitmap) { + base::ThreadRestrictions::ScopedAllowIO allow_io; + std::vector png_data; + gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data); + int bytes_written = file_util::WriteFile(image_path_, + reinterpret_cast(&png_data[0]), png_data.size()); + SendMessage(bytes_written == static_cast(png_data.size())); +} + +void PageSnapshotTaker::ExecuteScript(const std::wstring& javascript) { + std::wstring set_automation_id; + base::SStringPrintf( + &set_automation_id, + L"window.domAutomationController.setAutomationId(%d);", + reply_message_->routing_id()); + + render_view_->ExecuteJavascriptInWebFrame(L"", set_automation_id); + render_view_->ExecuteJavascriptInWebFrame(L"", javascript); +} + +void PageSnapshotTaker::SendMessage(bool success) { + AutomationMsg_CaptureEntirePageAsPNG::WriteReplyParams(reply_message_, + success); + automation_->Send(reply_message_); + delete this; +} + AutocompleteEditFocusedObserver::AutocompleteEditFocusedObserver( AutomationProvider* automation, AutocompleteEditModel* autocomplete_edit, diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 7b76638..cfa6e14 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -21,10 +21,10 @@ #include "chrome/browser/password_manager/password_store.h" #include "chrome/browser/search_engines/template_url_model_observer.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_type.h" -#include "chrome/test/automation/automation_messages.h" class AutocompleteEditModel; class AutomationProvider; @@ -33,6 +33,7 @@ class Browser; class Extension; class ExtensionProcessManager; class NavigationController; +class RenderViewHost; class SavePackage; class TabContents; class TranslateInfoBarDelegate; @@ -472,20 +473,34 @@ class FindInPageNotificationObserver : public NotificationObserver { DISALLOW_COPY_AND_ASSIGN(FindInPageNotificationObserver); }; -class DomOperationNotificationObserver : public NotificationObserver { +class DomOperationObserver : public NotificationObserver { public: - explicit DomOperationNotificationObserver(AutomationProvider* automation); - ~DomOperationNotificationObserver(); + DomOperationObserver(); + virtual ~DomOperationObserver() {} virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); + virtual void OnDomOperationCompleted(const std::string& json) = 0; + private: NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(DomOperationObserver); +}; + +class DomOperationMessageSender : public DomOperationObserver { + public: + explicit DomOperationMessageSender(AutomationProvider* automation) + : automation_(automation) {} + + virtual void OnDomOperationCompleted(const std::string& json); + + private: AutomationProvider* automation_; - DISALLOW_COPY_AND_ASSIGN(DomOperationNotificationObserver); + DISALLOW_COPY_AND_ASSIGN(DomOperationMessageSender); }; class DocumentPrintedNotificationObserver : public NotificationObserver { @@ -869,6 +884,42 @@ class SavePackageNotificationObserver : public NotificationObserver { DISALLOW_COPY_AND_ASSIGN(SavePackageNotificationObserver); }; +// This class manages taking a snapshot of a page. This requires waiting on +// asynchronous callbacks and notifications. +class PageSnapshotTaker : public DomOperationObserver { + public: + PageSnapshotTaker(AutomationProvider* automation, + IPC::Message* reply_message, + RenderViewHost* render_view, + const FilePath& path); + + // Start the process of taking a snapshot of the entire page. + void Start(); + + private: + // Overriden from DomOperationObserver. + virtual void OnDomOperationCompleted(const std::string& json); + + // Called by the ThumbnailGenerator when the requested snapshot has been + // generated. + void OnSnapshotTaken(const SkBitmap& bitmap); + + // Helper method to send arbitrary javascript to the renderer for evaluation. + void ExecuteScript(const std::wstring& javascript); + + // Helper method to send a response back to the client. Deletes this. + void SendMessage(bool success); + + AutomationProvider* automation_; + IPC::Message* reply_message_; + RenderViewHost* render_view_; + FilePath image_path_; + bool received_width_; + gfx::Size entire_page_size_; + + DISALLOW_COPY_AND_ASSIGN(PageSnapshotTaker); +}; + // Allows automation provider to wait until the autocomplete edit // has received focus class AutocompleteEditFocusedObserver : public NotificationObserver { diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc index a988a2f..56fe617 100644 --- a/chrome/browser/automation/automation_provider_win.cc +++ b/chrome/browser/automation/automation_provider_win.cc @@ -22,8 +22,8 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/bookmark_bar_view.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/page_zoom.h" -#include "chrome/test/automation/automation_messages.h" #include "views/focus/accelerator_handler.h" #include "views/widget/root_view.h" #include "views/widget/widget_win.h" diff --git a/chrome/browser/automation/automation_resource_message_filter.cc b/chrome/browser/automation/automation_resource_message_filter.cc index ecbbddc..98461d7 100644 --- a/chrome/browser/automation/automation_resource_message_filter.cc +++ b/chrome/browser/automation/automation_resource_message_filter.cc @@ -15,8 +15,8 @@ #include "chrome/browser/net/url_request_slow_download_job.h" #include "chrome/browser/net/url_request_slow_http_job.h" #include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/chrome_paths.h" -#include "chrome/test/automation/automation_messages.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" #include "net/url_request/url_request_filter.h" diff --git a/chrome/browser/automation/automation_resource_tracker.cc b/chrome/browser/automation/automation_resource_tracker.cc index a82265d..49797c6 100644 --- a/chrome/browser/automation/automation_resource_tracker.cc +++ b/chrome/browser/automation/automation_resource_tracker.cc @@ -4,8 +4,8 @@ #include "chrome/browser/automation/automation_resource_tracker.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/notification_service.h" -#include "chrome/test/automation/automation_messages.h" AutomationResourceTrackerImpl::AutomationResourceTrackerImpl( IPC::Message::Sender* sender) diff --git a/chrome/browser/automation/chrome_frame_automation_provider.cc b/chrome/browser/automation/chrome_frame_automation_provider.cc index b3ea659..4de788a 100644 --- a/chrome/browser/automation/chrome_frame_automation_provider.cc +++ b/chrome/browser/automation/chrome_frame_automation_provider.cc @@ -5,7 +5,7 @@ #include "chrome/browser/automation/chrome_frame_automation_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "ipc/ipc_message.h" #include "ipc/ipc_channel.h" diff --git a/chrome/browser/automation/extension_port_container.cc b/chrome/browser/automation/extension_port_container.cc index f5a1d75..baf6517 100644 --- a/chrome/browser/automation/extension_port_container.cc +++ b/chrome/browser/automation/extension_port_container.cc @@ -15,9 +15,9 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" -#include "chrome/test/automation/automation_messages.h" // TODO(siggi): Find a more structured way to read and write JSON messages. diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 4c2fcce..a0f7269 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -11,6 +11,7 @@ #include "base/json/string_escape.h" #include "base/path_service.h" #include "base/stringprintf.h" +#include "base/thread_restrictions.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" @@ -43,6 +44,11 @@ #include "chrome/browser/location_bar.h" #include "chrome/browser/login_prompt.h" #include "chrome/browser/native_app_modal_dialog.h" +#include "chrome/browser/notifications/balloon.h" +#include "chrome/browser/notifications/balloon_collection.h" +#include "chrome/browser/notifications/balloon_host.h" +#include "chrome/browser/notifications/notification.h" +#include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/profile.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" @@ -62,11 +68,7 @@ #include "chrome/common/net/url_request_context_getter.h" #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" -#include "chrome/browser/notifications/balloon.h" -#include "chrome/browser/notifications/balloon_collection.h" -#include "chrome/browser/notifications/notification.h" -#include "chrome/browser/notifications/notification_ui_manager.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "net/base/cookie_store.h" #include "net/url_request/url_request_context.h" #include "views/event.h" @@ -415,6 +417,8 @@ void TestingAutomationProvider::OnMessageReceived( IPC_MESSAGE_HANDLER(AutomationMsg_WindowTitle, GetWindowTitle) IPC_MESSAGE_HANDLER(AutomationMsg_SetShelfVisibility, SetShelfVisibility) IPC_MESSAGE_HANDLER(AutomationMsg_BlockedPopupCount, GetBlockedPopupCount) + IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CaptureEntirePageAsPNG, + CaptureEntirePageAsPNG) IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest, SendJSONRequest) IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome, @@ -1354,7 +1358,7 @@ void TestingAutomationProvider::GetSecurityState(int handle, void TestingAutomationProvider::GetPageType( int handle, bool* success, - NavigationEntry::PageType* page_type) { + PageType* page_type) { if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); NavigationEntry* entry = tab->GetActiveEntry(); @@ -1362,12 +1366,12 @@ void TestingAutomationProvider::GetPageType( *success = true; // In order to return the proper result when an interstitial is shown and // no navigation entry were created for it we need to ask the TabContents. - if (*page_type == NavigationEntry::NORMAL_PAGE && + if (*page_type == NORMAL_PAGE && tab->tab_contents()->showing_interstitial_page()) - *page_type = NavigationEntry::INTERSTITIAL_PAGE; + *page_type = INTERSTITIAL_PAGE; } else { *success = false; - *page_type = NavigationEntry::NORMAL_PAGE; + *page_type = NORMAL_PAGE; } } @@ -1385,7 +1389,7 @@ void TestingAutomationProvider::ActionOnSSLBlockingPage( if (tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); NavigationEntry* entry = tab->GetActiveEntry(); - if (entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE) { + if (entry->page_type() == INTERSTITIAL_PAGE) { TabContents* tab_contents = tab->tab_contents(); InterstitialPage* ssl_blocking_page = InterstitialPage::GetInterstitialPage(tab_contents); @@ -1981,6 +1985,22 @@ void TestingAutomationProvider::GetBlockedPopupCount(int handle, int* count) { } } +void TestingAutomationProvider::CaptureEntirePageAsPNG( + int tab_handle, const FilePath& path, IPC::Message* reply_message) { + RenderViewHost* render_view = GetViewForTab(tab_handle); + if (render_view) { + // This will delete itself when finished. + PageSnapshotTaker* snapshot_taker = new PageSnapshotTaker( + this, reply_message, render_view, path); + snapshot_taker->Start(); + } else { + LOG(ERROR) << "Could not get render view for tab handle"; + AutomationMsg_CaptureEntirePageAsPNG::WriteReplyParams(reply_message, + false); + Send(reply_message); + } +} + void TestingAutomationProvider::SendJSONRequest(int handle, std::string json_request, IPC::Message* reply_message) { @@ -2319,6 +2339,7 @@ void TestingAutomationProvider::GetBrowserInfo( Browser* browser, DictionaryValue* args, IPC::Message* reply_message) { + base::ThreadRestrictions::ScopedAllowIO allow_io; // needed for PathService DictionaryValue* properties = new DictionaryValue; properties->SetString("ChromeVersion", chrome::kChromeVersion); properties->SetString("BrowserProcessExecutableName", @@ -2469,10 +2490,10 @@ void TestingAutomationProvider::GetNavigationInfo( return_value->Set("ssl", ssl); // Page type. - std::map pagetype_to_string; - pagetype_to_string[NavigationEntry::NORMAL_PAGE] = "NORMAL_PAGE"; - pagetype_to_string[NavigationEntry::ERROR_PAGE] = "ERROR_PAGE"; - pagetype_to_string[NavigationEntry::INTERSTITIAL_PAGE] = "INTERSTITIAL_PAGE"; + std::map pagetype_to_string; + pagetype_to_string[NORMAL_PAGE] = "NORMAL_PAGE"; + pagetype_to_string[ERROR_PAGE] = "ERROR_PAGE"; + pagetype_to_string[INTERSTITIAL_PAGE] = "INTERSTITIAL_PAGE"; return_value->SetString("page_type", pagetype_to_string[nav_entry->page_type()]); @@ -4229,6 +4250,11 @@ void TestingAutomationProvider::GetActiveNotifications( balloon->SetString("content_url", notification.content_url().spec()); balloon->SetString("origin_url", notification.origin_url().spec()); balloon->SetString("display_source", notification.display_source()); + BalloonView* view = (*iter)->view(); + if (view && view->GetHost() && view->GetHost()->render_view_host()) { + balloon->SetInteger("pid", base::GetProcId( + view->GetHost()->render_view_host()->process()->GetHandle())); + } list->Append(balloon); } AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h index 8cd999d..3bc0101 100644 --- a/chrome/browser/automation/testing_automation_provider.h +++ b/chrome/browser/automation/testing_automation_provider.h @@ -13,6 +13,7 @@ #include "chrome/browser/history/history.h" #include "chrome/browser/sync/profile_sync_service_harness.h" #include "chrome/common/notification_registrar.h" +#include "chrome/common/page_type.h" class DictionaryValue; class TemplateURLModel; @@ -199,8 +200,7 @@ class TestingAutomationProvider : public AutomationProvider, int* insecure_content_status); // Gets the page type for the tab associated to the specified |handle|. - void GetPageType(int handle, bool* success, - NavigationEntry::PageType* page_type); + void GetPageType(int handle, bool* success, PageType* page_type); // Gets the duration in ms of the last event matching |event_name|. // |duration_ms| is -1 if the event hasn't occurred yet. @@ -345,6 +345,11 @@ class TestingAutomationProvider : public AutomationProvider, // Returns the number of blocked popups in the tab |handle|. void GetBlockedPopupCount(int handle, int* count); + // Captures the entire page for the given tab and saves it as PNG at the + // given path. + void CaptureEntirePageAsPNG(int tab_handle, const FilePath& path, + IPC::Message* reply_message); + // Generic pattern for pyautolib // Uses the JSON interface for input/output. void SendJSONRequest(int handle, diff --git a/chrome/browser/automation/testing_automation_provider_views.cc b/chrome/browser/automation/testing_automation_provider_views.cc index 6048cd8..f8631cf 100644 --- a/chrome/browser/automation/testing_automation_provider_views.cc +++ b/chrome/browser/automation/testing_automation_provider_views.cc @@ -9,7 +9,7 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/toolbar_view.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "gfx/point.h" #include "views/controls/menu/menu_wrapper.h" #include "views/view.h" diff --git a/chrome/browser/automation/ui_controls_linux.cc b/chrome/browser/automation/ui_controls_linux.cc index a2dd0ae..21cd0dd 100644 --- a/chrome/browser/automation/ui_controls_linux.cc +++ b/chrome/browser/automation/ui_controls_linux.cc @@ -13,7 +13,7 @@ #include "base/message_loop.h" #include "chrome/browser/automation/ui_controls_internal.h" #include "chrome/browser/gtk/gtk_util.h" -#include "chrome/test/automation/automation_constants.h" +#include "chrome/common/automation_constants.h" #if defined(TOOLKIT_VIEWS) #include "views/view.h" diff --git a/chrome/browser/automation/url_request_automation_job.cc b/chrome/browser/automation/url_request_automation_job.cc index fc4bd63..1b73b68 100644 --- a/chrome/browser/automation/url_request_automation_job.cc +++ b/chrome/browser/automation/url_request_automation_job.cc @@ -11,7 +11,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/automation_messages.h" #include "net/base/cookie_monster.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" diff --git a/chrome/browser/back_forward_menu_model.cc b/chrome/browser/back_forward_menu_model.cc index fb18da8..c7ecfd1 100644 --- a/chrome/browser/back_forward_menu_model.cc +++ b/chrome/browser/back_forward_menu_model.cc @@ -9,11 +9,11 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/string_number_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -137,8 +137,7 @@ void BackForwardMenuModel::ActivatedAt(int index) { } void BackForwardMenuModel::ActivatedAtWithDisposition( - int index, - WindowOpenDisposition disposition) { + int index, int disposition) { Profile* profile = browser_->profile(); DCHECK(!IsSeparator(index)); @@ -147,7 +146,7 @@ void BackForwardMenuModel::ActivatedAtWithDisposition( if (index == GetItemCount() - 1) { UserMetrics::RecordComputedAction(BuildActionName("ShowFullHistory", -1), profile); - browser_->ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL)); + browser_->ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL), false); return; } @@ -162,8 +161,8 @@ void BackForwardMenuModel::ActivatedAtWithDisposition( } int controller_index = MenuIndexToNavEntryIndex(index); - if (!browser_->NavigateToIndexWithDisposition(controller_index, - disposition)) { + if (!browser_->NavigateToIndexWithDisposition( + controller_index, static_cast(disposition))) { NOTREACHED(); } } diff --git a/chrome/browser/back_forward_menu_model.h b/chrome/browser/back_forward_menu_model.h index 4f838fd..b97698d 100644 --- a/chrome/browser/back_forward_menu_model.h +++ b/chrome/browser/back_forward_menu_model.h @@ -59,11 +59,7 @@ class BackForwardMenuModel : public menus::MenuModel { virtual MenuModel* GetSubmenuModelAt(int index) const; virtual void HighlightChangedTo(int index); virtual void ActivatedAt(int index); - - // Navigates to the corresponding history item, opening it in a new tab - // if necessary. - void ActivatedAtWithDisposition(int index, - WindowOpenDisposition disposition); + virtual void ActivatedAtWithDisposition(int index, int disposition); virtual void MenuWillShow(); // Is the item at |index| a separator? diff --git a/chrome/browser/background_contents_service.cc b/chrome/browser/background_contents_service.cc index 8517d97..8b5a42d 100644 --- a/chrome/browser/background_contents_service.cc +++ b/chrome/browser/background_contents_service.cc @@ -9,14 +9,14 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" @@ -58,6 +58,16 @@ BackgroundContentsService::~BackgroundContentsService() { DCHECK(contents_map_.empty()); } +std::vector +BackgroundContentsService::GetBackgroundContents() const +{ + std::vector contents; + for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); + it != contents_map_.end(); ++it) + contents.push_back(it->second.contents); + return contents; +} + void BackgroundContentsService::StartObserving(Profile* profile) { // On startup, load our background pages after extension-apps have loaded. registrar_.Add(this, NotificationType::EXTENSIONS_READY, @@ -65,9 +75,8 @@ void BackgroundContentsService::StartObserving(Profile* profile) { // Track the lifecycle of all BackgroundContents in the system to allow us // to store an up-to-date list of the urls. Start tracking contents when they - // have been opened, and stop tracking them when they are closed by script. - registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_OPENED, - Source(profile)); + // have been opened via CreateBackgroundContents(), and stop tracking them + // when they are closed by script. registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_CLOSED, Source(profile)); @@ -87,8 +96,8 @@ void BackgroundContentsService::StartObserving(Profile* profile) { } void BackgroundContentsService::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { + const NotificationSource& source, + const NotificationDetails& details) { switch (type.value) { case NotificationType::EXTENSIONS_READY: LoadBackgroundContentsFromPrefs(Source(source).ptr()); @@ -96,10 +105,6 @@ void BackgroundContentsService::Observe(NotificationType type, case NotificationType::BACKGROUND_CONTENTS_DELETED: BackgroundContentsShutdown(Details(details).ptr()); break; - case NotificationType::BACKGROUND_CONTENTS_OPENED: - BackgroundContentsOpened( - Details(details).ptr()); - break; case NotificationType::BACKGROUND_CONTENTS_CLOSED: DCHECK(IsTracked(Details(details).ptr())); UnregisterBackgroundContents(Details(details).ptr()); @@ -127,6 +132,8 @@ void BackgroundContentsService::LoadBackgroundContentsFromPrefs( prefs_->GetDictionary(prefs::kRegisteredBackgroundContents); if (!contents) return; + ExtensionsService* extensions_service = profile->GetExtensionsService(); + DCHECK(extensions_service); for (DictionaryValue::key_iterator it = contents->begin_keys(); it != contents->end_keys(); ++it) { DictionaryValue* dict; @@ -135,14 +142,28 @@ void BackgroundContentsService::LoadBackgroundContentsFromPrefs( std::string url; dict->GetString(kUrlKey, &url); dict->GetString(kFrameNameKey, &frame_name); - CreateBackgroundContents(profile, - GURL(url), - frame_name, - UTF8ToUTF16(*it)); + + // Check to make sure that the parent extension is still enabled. + const Extension* extension = extensions_service->GetExtensionById( + *it, false); + + if (!extension) { + // We should never reach here - it should not be possible for an app + // to become uninstalled without the associated BackgroundContents being + // unregistered via the EXTENSIONS_UNLOADED notification, unless there's a + // crash before we could save our prefs. + NOTREACHED() << "No extension found for BackgroundContents - id = " + << *it; + return; + } + LoadBackgroundContents(profile, + GURL(url), + frame_name, + UTF8ToUTF16(*it)); } } -void BackgroundContentsService::CreateBackgroundContents( +void BackgroundContentsService::LoadBackgroundContents( Profile* profile, const GURL& url, const string16& frame_name, @@ -155,32 +176,12 @@ void BackgroundContentsService::CreateBackgroundContents( DCHECK(url.is_valid()); DVLOG(1) << "Loading background content url: " << url; - // Check to make sure that the parent extension is still enabled. - ExtensionsService* extensions_service = profile->GetExtensionsService(); - const Extension* extension = extensions_service->GetExtensionById( - UTF16ToASCII(application_id), false); - - if (!extension) { - // We should never reach here - it should not be possible for an application - // to become uninstalled without the associated BackgroundContents being - // unregistered via the EXTENSIONS_UNLOADED notification, unless there's a - // crash before we could save our prefs. - NOTREACHED() << "No extension found for BackgroundContents - id = " - << application_id; - return; - } - - BackgroundContents* contents = new BackgroundContents( + BackgroundContents* contents = CreateBackgroundContents( SiteInstance::CreateSiteInstanceForURL(profile, url), MSG_ROUTING_NONE, - this); - - // TODO(atwilson): Change this to send a BACKGROUND_CONTENTS_CREATED - // notification when we have a listener outside of BackgroundContentsService. - BackgroundContentsOpenedDetails details = {contents, - frame_name, - application_id}; - BackgroundContentsOpened(&details); + profile, + frame_name, + application_id); RenderViewHost* render_view_host = contents->render_view_host(); // TODO(atwilson): Create RenderViews asynchronously to avoid increasing @@ -189,6 +190,27 @@ void BackgroundContentsService::CreateBackgroundContents( render_view_host->NavigateToURL(url); } +BackgroundContents* BackgroundContentsService::CreateBackgroundContents( + SiteInstance* site, + int routing_id, + Profile* profile, + const string16& frame_name, + const string16& application_id) { + BackgroundContents* contents = new BackgroundContents(site, routing_id, this); + + // Register the BackgroundContents internally, then send out a notification + // to external listeners. + BackgroundContentsOpenedDetails details = {contents, + frame_name, + application_id}; + BackgroundContentsOpened(&details); + NotificationService::current()->Notify( + NotificationType::BACKGROUND_CONTENTS_OPENED, + Source(profile), + Details(&details)); + return contents; +} + void BackgroundContentsService::RegisterBackgroundContents( BackgroundContents* background_contents) { DCHECK(IsTracked(background_contents)); diff --git a/chrome/browser/background_contents_service.h b/chrome/browser/background_contents_service.h index 08165d8..7fe16ac 100644 --- a/chrome/browser/background_contents_service.h +++ b/chrome/browser/background_contents_service.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include "base/gtest_prod_util.h" #include "chrome/browser/tab_contents/background_contents.h" @@ -45,6 +46,9 @@ class BackgroundContentsService : private NotificationObserver, // or NULL if none. BackgroundContents* GetAppBackgroundContents(const string16& appid); + // Returns all currently opened BackgroundContents (used by the task manager). + std::vector GetBackgroundContents() const; + static void RegisterUserPrefs(PrefService* prefs); // BackgroundContents::Delegate implementation. @@ -53,12 +57,33 @@ class BackgroundContentsService : private NotificationObserver, const gfx::Rect& initial_pos, bool user_gesture); + // Gets the parent application id for the passed BackgroundContents. Returns + // an empty string if no parent application found (e.g. passed + // BackgroundContents has already shut down). + const string16& GetParentApplicationId(BackgroundContents* contents) const; + + // Creates a new BackgroundContents using the passed |site| and + // the |route_id| and begins tracking the object internally so it can be + // shutdown if the parent application is uninstalled. + // A BACKGROUND_CONTENTS_OPENED notification will be generated with the passed + // |frame_name| and |application_id| values, using the passed |profile| as the + // Source.. + BackgroundContents* CreateBackgroundContents(SiteInstance* site, + int route_id, + Profile* profile, + const string16& frame_name, + const string16& application_id); + private: friend class BackgroundContentsServiceTest; + friend class MockBackgroundContents; + friend class TaskManagerBrowserTest; FRIEND_TEST_ALL_PREFIXES(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy); FRIEND_TEST_ALL_PREFIXES(BackgroundContentsServiceTest, TestApplicationIDLinkage); + FRIEND_TEST_ALL_PREFIXES(TaskManagerBrowserTest, + NoticeBGContentsChanges); // Registers for various notifications. void StartObserving(Profile* profile); @@ -71,13 +96,13 @@ class BackgroundContentsService : private NotificationObserver, // Loads all registered BackgroundContents at startup. void LoadBackgroundContentsFromPrefs(Profile* profile); - // Creates a single BackgroundContents associated with the specified |appid|. - // The BackgroundContents frame will be given the name specified by - // |frame_name| and navigated to the passed URL. - void CreateBackgroundContents(Profile* profile, - const GURL& url, - const string16& frame_name, - const string16& appid); + // Creates a single BackgroundContents associated with the specified |appid|, + // creates an associated RenderView with the name specified by |frame_name|, + // and navigates to the passed |url|. + void LoadBackgroundContents(Profile* profile, + const GURL& url, + const string16& frame_name, + const string16& appid); // Invoked when a new BackgroundContents is opened. void BackgroundContentsOpened(BackgroundContentsOpenedDetails* details); @@ -101,11 +126,6 @@ class BackgroundContentsService : private NotificationObserver, // Returns true if this BackgroundContents is in the contents_list_. bool IsTracked(BackgroundContents* contents) const; - // Gets the parent application id for the passed BackgroundContents. Returns - // an empty string if no parent application found (e.g. passed - // BackgroundContents has already shut down). - const string16& GetParentApplicationId(BackgroundContents* contents) const; - // PrefService used to store list of background pages (or NULL if this is // running under an off-the-record profile). PrefService* prefs_; diff --git a/chrome/browser/background_contents_service_unittest.cc b/chrome/browser/background_contents_service_unittest.cc index 23ba929..566b74b 100644 --- a/chrome/browser/background_contents_service_unittest.cc +++ b/chrome/browser/background_contents_service_unittest.cc @@ -57,14 +57,11 @@ class MockBackgroundContents : public BackgroundContents { profile_(profile) { } - void SendOpenedNotification() { + void SendOpenedNotification(BackgroundContentsService* service) { string16 frame_name = ASCIIToUTF16("background"); BackgroundContentsOpenedDetails details = { this, frame_name, appid_ }; - NotificationService::current()->Notify( - NotificationType::BACKGROUND_CONTENTS_OPENED, - Source(profile_), - Details(&details)); + service->BackgroundContentsOpened(&details); } virtual void Navigate(GURL url) { @@ -114,7 +111,7 @@ TEST_F(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy) { BackgroundContentsService service(&profile, command_line_.get()); MockBackgroundContents* contents = new MockBackgroundContents(&profile); EXPECT_FALSE(service.IsTracked(contents)); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); EXPECT_TRUE(service.IsTracked(contents)); delete contents; EXPECT_FALSE(service.IsTracked(contents)); @@ -131,7 +128,7 @@ TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAdded) { scoped_ptr contents( new MockBackgroundContents(&profile)); EXPECT_EQ(0U, GetPrefs(&profile)->size()); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); contents->Navigate(url); EXPECT_EQ(1U, GetPrefs(&profile)->size()); @@ -154,7 +151,7 @@ TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAddedAndClosed) { GURL url("http://a/"); MockBackgroundContents* contents = new MockBackgroundContents(&profile); EXPECT_EQ(0U, GetPrefs(&profile)->size()); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); contents->Navigate(url); EXPECT_EQ(1U, GetPrefs(&profile)->size()); EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); @@ -174,7 +171,7 @@ TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) { { scoped_ptr contents(new MockBackgroundContents( &profile, "appid")); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); contents->Navigate(url); EXPECT_EQ(1U, GetPrefs(&profile)->size()); EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); @@ -187,7 +184,7 @@ TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) { // URL again. scoped_ptr contents(new MockBackgroundContents( &profile, "appid")); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); contents->Navigate(url); EXPECT_EQ(1U, GetPrefs(&profile)->size()); } @@ -206,9 +203,9 @@ TEST_F(BackgroundContentsServiceTest, TestApplicationIDLinkage) { "appid"); scoped_ptr contents2( new MockBackgroundContents(&profile, "appid2")); - contents->SendOpenedNotification(); + contents->SendOpenedNotification(&service); EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid())); - contents2->SendOpenedNotification(); + contents2->SendOpenedNotification(&service); EXPECT_EQ(contents2.get(), service.GetAppBackgroundContents( contents2->appid())); EXPECT_EQ(0U, GetPrefs(&profile)->size()); diff --git a/chrome/browser/background_mode_manager.cc b/chrome/browser/background_mode_manager.cc index 06e5439..666af19 100644 --- a/chrome/browser/background_mode_manager.cc +++ b/chrome/browser/background_mode_manager.cc @@ -541,7 +541,7 @@ void BackgroundModeManager::RemoveStatusTrayIcon() { } void BackgroundModeManager::ExecuteApplication(int item) { - DCHECK(item > 0 && item < static_cast(applications_.size())); + DCHECK(item >= 0 && item < static_cast(applications_.size())); Browser* browser = BrowserList::GetLastActive(); if (!browser) { Browser::OpenEmptyWindow(profile_); diff --git a/chrome/browser/blocked_plugin_manager.cc b/chrome/browser/blocked_plugin_manager.cc deleted file mode 100644 index 2da3653..0000000 --- a/chrome/browser/blocked_plugin_manager.cc +++ /dev/null @@ -1,91 +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/blocked_plugin_manager.h" - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/command_line.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/host_content_settings_map.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/chrome_switches.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" - -BlockedPluginManager::BlockedPluginManager(TabContents* tab_contents) - : ConfirmInfoBarDelegate(tab_contents), - tab_contents_(tab_contents) { } - -void BlockedPluginManager::OnNonSandboxedPluginBlocked( - const std::string& plugin, - const string16& name) { - plugin_ = plugin; - name_ = name; - UserMetrics::RecordAction(UserMetricsAction("ClickToPlay_InfobarShown")); - tab_contents_->AddInfoBar(this); -} - -void BlockedPluginManager::OnBlockedPluginLoaded() { - tab_contents_->RemoveInfoBar(this); -} - -int BlockedPluginManager::GetButtons() const { - int buttons = BUTTON_OK; - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableResourceContentSettings)) - buttons |= BUTTON_CANCEL; - return buttons; -} - -string16 BlockedPluginManager::GetButtonLabel(InfoBarButton button) const { - if (button == BUTTON_OK) - return l10n_util::GetStringUTF16(IDS_PLUGIN_LOAD_SHORT); - if (button == BUTTON_CANCEL) - return l10n_util::GetStringUTF16(IDS_BLOCKED_PLUGINS_UNBLOCK_SHORT); - return ConfirmInfoBarDelegate::GetButtonLabel(button); -} - -string16 BlockedPluginManager::GetMessageText() const { - return l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED_PROMPT, name_); -} - -string16 BlockedPluginManager::GetLinkText() { - return l10n_util::GetStringUTF16(IDS_LEARN_MORE); -} - -SkBitmap* BlockedPluginManager::GetIcon() const { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_PLUGIN_INSTALL); -} - -bool BlockedPluginManager::Accept() { - UserMetrics::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Infobar")); - tab_contents_->render_view_host()->LoadBlockedPlugins(); - return true; -} - -bool BlockedPluginManager::Cancel() { - DCHECK(CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableResourceContentSettings)); - UserMetrics::RecordAction(UserMetricsAction("ClickToPlay_AllowAlways")); - tab_contents_->profile()->GetHostContentSettingsMap()->AddExceptionForURL( - tab_contents_->GetURL(), CONTENT_SETTINGS_TYPE_PLUGINS, plugin_, - CONTENT_SETTING_ALLOW); - tab_contents_->render_view_host()->LoadBlockedPlugins(); - return true; -} - -void BlockedPluginManager::InfoBarDismissed() { - UserMetrics::RecordAction(UserMetricsAction("ClickToPlay_Dismiss_Infobar")); -} - -bool BlockedPluginManager::LinkClicked(WindowOpenDisposition disposition) { - // TODO(bauerb): Navigate to a help page explaining why we blocked the plugin, - // once we have one. - return false; -} diff --git a/chrome/browser/blocked_plugin_manager.h b/chrome/browser/blocked_plugin_manager.h deleted file mode 100644 index fcabdb2..0000000 --- a/chrome/browser/blocked_plugin_manager.h +++ /dev/null @@ -1,40 +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_BLOCKED_PLUGIN_MANAGER_H_ -#define CHROME_BROWSER_BLOCKED_PLUGIN_MANAGER_H_ - -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" - -class TabContents; - -class BlockedPluginManager : public RenderViewHostDelegate::BlockedPlugin, - public ConfirmInfoBarDelegate { - public: - explicit BlockedPluginManager(TabContents* tab_contents); - - virtual void OnNonSandboxedPluginBlocked(const std::string& plugin, - const string16& name); - virtual void OnBlockedPluginLoaded(); - - // ConfirmInfoBarDelegate methods - virtual int GetButtons() const; - virtual string16 GetButtonLabel(InfoBarButton button) const; - virtual string16 GetMessageText() const; - virtual string16 GetLinkText(); - virtual SkBitmap* GetIcon() const; - virtual bool Accept(); - virtual bool Cancel(); - virtual void InfoBarDismissed(); - virtual bool LinkClicked(WindowOpenDisposition disposition); - - private: - // Owns us. - TabContents* tab_contents_; - string16 name_; - std::string plugin_; -}; - -#endif // CHROME_BROWSER_BLOCKED_PLUGIN_MANAGER_H_ diff --git a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc index e9152a4..a4af97d 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc +++ b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc @@ -10,12 +10,12 @@ #include "chrome/browser/bookmarks/bookmark_folder_editor_controller.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_utils.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc index 1f94e6a..1a2a5bf 100644 --- a/chrome/browser/bookmarks/bookmark_model.cc +++ b/chrome/browser/bookmarks/bookmark_model.cc @@ -232,9 +232,9 @@ void BookmarkModel::Copy(const BookmarkNode* node, SetDateGroupModified(new_parent, Time::Now()); BookmarkDragData drag_data_(node); std::vector elements(drag_data_.elements); - // CloneDragData will use BookmarkModel methods to do the job, so we + // CloneBookmarkNode will use BookmarkModel methods to do the job, so we // don't need to send notifications here. - bookmark_utils::CloneDragData(this, elements, new_parent, index); + bookmark_utils::CloneBookmarkNode(this, elements, new_parent, index); if (store_.get()) store_->ScheduleSave(); diff --git a/chrome/browser/bookmarks/bookmark_model_unittest.cc b/chrome/browser/bookmarks/bookmark_model_unittest.cc index 29605ab..6d6017a 100644 --- a/chrome/browser/bookmarks/bookmark_model_unittest.cc +++ b/chrome/browser/bookmarks/bookmark_model_unittest.cc @@ -12,6 +12,7 @@ #include "base/path_service.h" #include "base/string16.h" #include "base/string_number_conversions.h" +#include "base/string_split.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/bookmarks/bookmark_codec.h" @@ -621,7 +622,7 @@ static void PopulateNodeFromString(const std::string& description, TestNode* parent) { std::vector elements; size_t index = 0; - SplitStringAlongWhitespace(description, &elements); + base::SplitStringAlongWhitespace(description, &elements); PopulateNodeImpl(elements, &index, parent); } diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index 9576721..b89463d 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -18,7 +18,6 @@ #if defined(OS_MACOSX) #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h" #endif -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" @@ -28,6 +27,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/page_navigator.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "grit/app_strings.h" @@ -86,13 +86,10 @@ class NewBrowserPageNavigator : public PageNavigator { DISALLOW_COPY_AND_ASSIGN(NewBrowserPageNavigator); }; -// TODO(mrossetti): Rename CloneDragDataImpl to CloneBookmarkNodeImpl. -// See: http://crbug.com/37891 - -void CloneDragDataImpl(BookmarkModel* model, - const BookmarkDragData::Element& element, - const BookmarkNode* parent, - int index_to_add_at) { +void CloneBookmarkNodeImpl(BookmarkModel* model, + const BookmarkDragData::Element& element, + const BookmarkNode* parent, + int index_to_add_at) { if (element.is_url) { model->AddURL(parent, index_to_add_at, element.title, element.url); } else { @@ -100,7 +97,7 @@ void CloneDragDataImpl(BookmarkModel* model, index_to_add_at, element.title); for (int i = 0; i < static_cast(element.children.size()); ++i) - CloneDragDataImpl(model, element.children[i], new_folder, i); + CloneBookmarkNodeImpl(model, element.children[i], new_folder, i); } } @@ -269,7 +266,7 @@ int PerformBookmarkDrop(Profile* profile, return DragDropTypes::DRAG_NONE; } // Dropping a group from different profile. Always accept. - bookmark_utils::CloneDragData(model, data.elements, parent_node, index); + bookmark_utils::CloneBookmarkNode(model, data.elements, parent_node, index); return DragDropTypes::DRAG_COPY; } @@ -306,16 +303,16 @@ bool IsValidDropLocation(Profile* profile, return true; } -void CloneDragData(BookmarkModel* model, - const std::vector& elements, - const BookmarkNode* parent, - int index_to_add_at) { +void CloneBookmarkNode(BookmarkModel* model, + const std::vector& elements, + const BookmarkNode* parent, + int index_to_add_at) { if (!parent->is_folder() || !model) { NOTREACHED(); return; } for (size_t i = 0; i < elements.size(); ++i) - CloneDragDataImpl(model, elements[i], parent, index_to_add_at + i); + CloneBookmarkNodeImpl(model, elements[i], parent, index_to_add_at + i); } @@ -420,7 +417,8 @@ void PasteFromClipboard(BookmarkModel* model, if (index == -1) index = parent->GetChildCount(); - bookmark_utils::CloneDragData(model, bookmark_data.elements, parent, index); + bookmark_utils::CloneBookmarkNode( + model, bookmark_data.elements, parent, index); } bool CanPasteFromClipboard(const BookmarkNode* node) { diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h index 9fccbad..adbe74e 100644 --- a/chrome/browser/bookmarks/bookmark_utils.h +++ b/chrome/browser/bookmarks/bookmark_utils.h @@ -66,15 +66,12 @@ bool IsValidDropLocation(Profile* profile, const BookmarkNode* drop_parent, int index); -// TODO(mrossetti): Rename CloneDragData to CloneBookmarkNode. -// See: http://crbug.com/37891 - -// Clones drag data, adding newly created nodes to |parent| starting at +// Clones bookmark node, adding newly created nodes to |parent| starting at // |index_to_add_at|. -void CloneDragData(BookmarkModel* model, - const std::vector& elements, - const BookmarkNode* parent, - int index_to_add_at); +void CloneBookmarkNode(BookmarkModel* model, + const std::vector& elements, + const BookmarkNode* parent, + int index_to_add_at); // Begins dragging a group of bookmarks. void DragBookmarks(Profile* profile, diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 79775e6..250eeeb 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -25,7 +25,6 @@ #include "base/tracked_objects.h" #include "base/utf_string_conversions.h" #include "chrome/browser/about_flags.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/defaults.h" @@ -43,6 +42,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_ui_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/about_handler.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_version_info.h" @@ -758,21 +758,27 @@ void DxDiagNodeToHTML(std::string* output, const DxDiagNode& node) { } std::string AboutGpu() { - GPUInfo gpu_info = GpuProcessHost::Get()->gpu_info(); + const GPUInfo& gpu_info = GpuProcessHostUIShim::Get()->gpu_info(); std::string html; - if (!gpu_info.initialized()) { + + html.append("About GPU\n"); + + if (gpu_info.progress() != GPUInfo::kComplete) { GpuProcessHostUIShim::Get()->CollectGraphicsInfoAsynchronously(); - // If it's not initialized yet, let the user know and reload the page - html.append("About GPU\n"); + + // If it's not fully initialized yet, set a timeout to reload the page. html.append("\n"); - html.append("

GPU Information

\n"); + } else { + html.append("\n"); + } + + html.append("

GPU Information

\n"); + + if (gpu_info.progress() == GPUInfo::kUninitialized) { html.append("

Retrieving GPU information . . .

\n"); - html.append(" "); } else { - html.append("About GPU\n"); - html.append("

GPU Information

\n"); html.append(""); html.append("
Initialization time"); html.append(base::Int64ToString( @@ -799,12 +805,17 @@ std::string AboutGpu() { html.append("
"); #if defined(OS_WIN) - html.append("

DirectX Diagnostics

"); - DxDiagNodeToHTML(&html, gpu_info.dx_diagnostics()); + if (gpu_info.progress() != GPUInfo::kComplete) { + html.append("

Retrieving DirectX Diagnostics . . .

\n"); + } else { + html.append("

DirectX Diagnostics

"); + DxDiagNodeToHTML(&html, gpu_info.dx_diagnostics()); + } #endif - - html.append(""); } + + html.append(""); + return html; } diff --git a/chrome/browser/browser_browsertest.cc b/chrome/browser/browser_browsertest.cc index c63d6b8..3386195 100644 --- a/chrome/browser/browser_browsertest.cc +++ b/chrome/browser/browser_browsertest.cc @@ -11,12 +11,7 @@ #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/app_modal_dialog.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_init.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extensions_service.h" @@ -28,6 +23,11 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/pinned_tab_codec.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_init.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/browser_commands_unittest.cc b/chrome/browser/browser_commands_unittest.cc index 667ee35..70beb87 100644 --- a/chrome/browser/browser_commands_unittest.cc +++ b/chrome/browser/browser_commands_unittest.cc @@ -4,12 +4,12 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/url_constants.h" #include "chrome/test/browser_with_test_window_test.h" #include "chrome/test/testing_profile.h" diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc index d9771db..13c6b94 100644 --- a/chrome/browser/browser_focus_uitest.cc +++ b/chrome/browser/browser_focus_uitest.cc @@ -10,7 +10,6 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" @@ -18,6 +17,7 @@ #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/browser/ui/browser.h" #include "chrome/browser/view_ids.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/url_constants.h" @@ -53,9 +53,12 @@ // TODO(suzhe): http://crbug.com/49737 #define MAYBE_TabsRememberFocusFindInPage FAILS_TabsRememberFocusFindInPage #elif defined(OS_WIN) -#define MAYBE_FocusTraversal FocusTraversal -#define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial -#define MAYBE_TabsRememberFocusFindInPage TabsRememberFocusFindInPage +// Disabled, http://crbug.com/62543. +#define MAYBE_FocusTraversal DISABLED_FocusTraversal +// Disabled, http://crbug.com/62544. +#define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial +// Flaky, http://crbug.com/62537. +#define MAYBE_TabsRememberFocusFindInPage FLAKY_TabsRememberFocusFindInPage #endif namespace { @@ -208,7 +211,8 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BrowsersRememberFocus) { } // Tabs remember focus. -IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocus) { +// Disabled, http://crbug.com/62542. +IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabsRememberFocus) { ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_TRUE(test_server()->Start()); @@ -314,7 +318,9 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) { } // Background window does not steal focus. -IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BackgroundBrowserDontStealFocus) { +// Flaky, http://crbug.com/62538. +IN_PROC_BROWSER_TEST_F(BrowserFocusTest, + FLAKY_BackgroundBrowserDontStealFocus) { ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_TRUE(test_server()->Start()); @@ -636,7 +642,8 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) { } // Make sure Find box can request focus, even when it is already open. -IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) { +// Disabled, http://crbug.com/62936. +IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FindFocusTest) { ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_TRUE(test_server()->Start()); @@ -700,7 +707,8 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) { // Makes sure the focus is in the right location when opening the different // types of tabs. -IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) { +// Flaky, http://crbug.com/62539. +IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FLAKY_TabInitialFocus) { ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); // Open the history tab, focus should be on the tab contents. diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc deleted file mode 100644 index f28029f..0000000 --- a/chrome/browser/browser_init.cc +++ /dev/null @@ -1,1035 +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/browser_init.h" - -#include // For max(). - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/environment.h" -#include "base/event_recorder.h" -#include "base/file_path.h" -#include "base/metrics/histogram.h" -#include "base/path_service.h" -#include "base/scoped_ptr.h" -#include "base/string_number_conversions.h" -#include "base/thread_restrictions.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/automation/automation_provider.h" -#include "chrome/browser/automation/automation_provider_list.h" -#include "chrome/browser/automation/chrome_frame_automation_provider.h" -#include "chrome/browser/automation/testing_automation_provider.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/child_process_security_policy.h" -#include "chrome/browser/defaults.h" -#include "chrome/browser/extensions/extension_creator.h" -#include "chrome/browser/extensions/extensions_service.h" -#include "chrome/browser/extensions/pack_extension_job.h" -#include "chrome/browser/first_run/first_run.h" -#include "chrome/browser/net/predictor_api.h" -#include "chrome/browser/net/url_fixer_upper.h" -#include "chrome/browser/notifications/desktop_notification_service.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prefs/session_startup_pref.h" -#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/browser/search_engines/template_url.h" -#include "chrome/browser/search_engines/template_url_model.h" -#include "chrome/browser/sessions/session_restore.h" -#include "chrome/browser/sessions/session_service.h" -#include "chrome/browser/shell_integration.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" -#include "chrome/browser/tabs/pinned_tab_codec.h" -#include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/result_codes.h" -#include "chrome/common/url_constants.h" -#include "chrome/installer/util/browser_distribution.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" -#include "grit/theme_resources.h" -#include "net/base/net_util.h" -#include "net/url_request/url_request.h" -#include "webkit/glue/webkit_glue.h" - -#if defined(OS_MACOSX) -#include "chrome/browser/cocoa/keystone_infobar.h" -#endif - -#if defined(OS_WIN) -#include "app/win_util.h" -#endif - -#if defined(TOOLKIT_GTK) -#include "chrome/browser/gtk/gtk_util.h" -#endif - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/cros/cros_library.h" -#include "chrome/browser/chromeos/cros/mount_library.h" -#include "chrome/browser/chromeos/cros/network_library.h" -#include "chrome/browser/chromeos/customization_document.h" -#include "chrome/browser/chromeos/gview_request_interceptor.h" -#include "chrome/browser/chromeos/low_battery_observer.h" -#include "chrome/browser/chromeos/network_message_observer.h" -#include "chrome/browser/chromeos/network_state_notifier.h" -#include "chrome/browser/chromeos/system_key_event_listener.h" -#include "chrome/browser/chromeos/update_observer.h" -#include "chrome/browser/chromeos/usb_mount_observer.h" -#include "chrome/browser/chromeos/wm_message_listener.h" -#include "chrome/browser/chromeos/wm_overview_controller.h" -#include "chrome/browser/dom_ui/mediaplayer_ui.h" -#endif - -namespace { - -class SetAsDefaultBrowserTask : public Task { - public: - SetAsDefaultBrowserTask() { } - virtual void Run() { - ShellIntegration::SetAsDefaultBrowser(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(SetAsDefaultBrowserTask); -}; - -// The delegate for the infobar shown when Chrome is not the default browser. -class DefaultBrowserInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - explicit DefaultBrowserInfoBarDelegate(TabContents* contents) - : ConfirmInfoBarDelegate(contents), - profile_(contents->profile()), - action_taken_(false), - should_expire_(false), - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { - // We want the info-bar to stick-around for few seconds and then be hidden - // on the next navigation after that. - MessageLoop::current()->PostDelayedTask(FROM_HERE, - method_factory_.NewRunnableMethod( - &DefaultBrowserInfoBarDelegate::Expire), - 8000); // 8 seconds. - } - - virtual bool ShouldExpire( - const NavigationController::LoadCommittedDetails& details) const { - return should_expire_; - } - - // Overridden from ConfirmInfoBarDelegate: - virtual void InfoBarClosed() { - if (!action_taken_) - UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.Ignored", 1); - delete this; - } - - virtual string16 GetMessageText() const { - return l10n_util::GetStringUTF16(IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT); - } - - virtual SkBitmap* GetIcon() const { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_PRODUCT_ICON_32); - } - - virtual int GetButtons() const { - return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT; - } - - virtual string16 GetButtonLabel(InfoBarButton button) const { - return button == BUTTON_OK ? - l10n_util::GetStringUTF16(IDS_SET_AS_DEFAULT_INFOBAR_BUTTON_LABEL) : - l10n_util::GetStringUTF16(IDS_DONT_ASK_AGAIN_INFOBAR_BUTTON_LABEL); - } - - virtual bool NeedElevation(InfoBarButton button) const { - return button == BUTTON_OK; - } - - virtual bool Accept() { - action_taken_ = true; - UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.SetAsDefault", 1); - g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, - new SetAsDefaultBrowserTask()); - return true; - } - - virtual bool Cancel() { - action_taken_ = true; - UMA_HISTOGRAM_COUNTS("DefaultBrowserWarning.DontSetAsDefault", 1); - // User clicked "Don't ask me again", remember that. - profile_->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, false); - return true; - } - - void Expire() { - should_expire_ = true; - } - - private: - // The Profile that we restore sessions from. - Profile* profile_; - - // Whether the user clicked one of the buttons. - bool action_taken_; - - // Whether the info-bar should be dismissed on the next navigation. - bool should_expire_; - - // Used to delay the expiration of the info-bar. - ScopedRunnableMethodFactory method_factory_; - - DISALLOW_COPY_AND_ASSIGN(DefaultBrowserInfoBarDelegate); -}; - -class NotifyNotDefaultBrowserTask : public Task { - public: - NotifyNotDefaultBrowserTask() { } - - virtual void Run() { - Browser* browser = BrowserList::GetLastActive(); - if (!browser) { - // Reached during ui tests. - return; - } - TabContents* tab = browser->GetSelectedTabContents(); - // Don't show the info-bar if there are already info-bars showing. - // In ChromeBot tests, there might be a race. This line appears to get - // called during shutdown and |tab| can be NULL. - if (!tab || tab->infobar_delegate_count() > 0) - return; - tab->AddInfoBar(new DefaultBrowserInfoBarDelegate(tab)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(NotifyNotDefaultBrowserTask); -}; - -class CheckDefaultBrowserTask : public Task { - public: - CheckDefaultBrowserTask() { - } - - virtual void Run() { - if (ShellIntegration::IsDefaultBrowser()) - return; -#if defined(OS_WIN) - if (!BrowserDistribution::GetDistribution()->CanSetAsDefault()) - return; -#endif - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, new NotifyNotDefaultBrowserTask()); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CheckDefaultBrowserTask); -}; - -// A delegate for the InfoBar shown when the previous session has crashed. The -// bar deletes itself automatically after it is closed. -class SessionCrashedInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - explicit SessionCrashedInfoBarDelegate(TabContents* contents) - : ConfirmInfoBarDelegate(contents), - profile_(contents->profile()) { - } - - // Overridden from ConfirmInfoBarDelegate: - virtual void InfoBarClosed() { - delete this; - } - virtual string16 GetMessageText() const { - return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE); - } - virtual SkBitmap* GetIcon() const { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_RESTORE_SESSION); - } - virtual int GetButtons() const { return BUTTON_OK; } - virtual string16 GetButtonLabel(InfoBarButton button) const { - return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON); - } - virtual bool Accept() { - // Restore the session. - SessionRestore::RestoreSession(profile_, NULL, true, false, - std::vector()); - return true; - } - - private: - // The Profile that we restore sessions from. - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(SessionCrashedInfoBarDelegate); -}; - -SessionStartupPref GetSessionStartupPref(const CommandLine& command_line, - Profile* profile) { - SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile); - if (command_line.HasSwitch(switches::kRestoreLastSession)) - pref.type = SessionStartupPref::LAST; - if (command_line.HasSwitch(switches::kIncognito) && - pref.type == SessionStartupPref::LAST) { - // We don't store session information when incognito. If the user has - // chosen to restore last session and launched incognito, fallback to - // default launch behavior. - pref.type = SessionStartupPref::DEFAULT; - } - return pref; -} - -enum LaunchMode { - LM_TO_BE_DECIDED = 0, // Possibly direct launch or via a shortcut. - LM_AS_WEBAPP, // Launched as a installed web application. - LM_WITH_URLS, // Launched with urls in the cmd line. - LM_SHORTCUT_NONE, // Not launched from a shortcut. - LM_SHORTCUT_NONAME, // Launched from shortcut but no name available. - LM_SHORTCUT_UNKNOWN, // Launched from user-defined shortcut. - LM_SHORTCUT_QUICKLAUNCH, // Launched from the quick launch bar. - LM_SHORTCUT_DESKTOP, // Launched from a desktop shortcut. - LM_SHORTCUT_STARTMENU, // Launched from start menu. - LM_LINUX_MAC_BEOS // Other OS buckets start here. -}; - -#if defined(OS_WIN) -// Undocumented flag in the startup info structure tells us what shortcut was -// used to launch the browser. See http://www.catch22.net/tuts/undoc01 for -// more information. Confirmed to work on XP, Vista and Win7. -LaunchMode GetLaunchShortcutKind() { - STARTUPINFOW si = { sizeof(si) }; - GetStartupInfoW(&si); - if (si.dwFlags & 0x800) { - if (!si.lpTitle) - return LM_SHORTCUT_NONAME; - std::wstring shortcut(si.lpTitle); - // The windows quick launch path is not localized. - if (shortcut.find(L"\\Quick Launch\\") != std::wstring::npos) - return LM_SHORTCUT_QUICKLAUNCH; - scoped_ptr env(base::Environment::Create()); - std::string appdata_path; - env->GetVar("USERPROFILE", &appdata_path); - if (!appdata_path.empty() && - shortcut.find(ASCIIToWide(appdata_path)) != std::wstring::npos) - return LM_SHORTCUT_DESKTOP; - return LM_SHORTCUT_UNKNOWN; - } - return LM_SHORTCUT_NONE; -} -#else -// TODO(cpu): Port to other platforms. -LaunchMode GetLaunchShortcutKind() { - return LM_LINUX_MAC_BEOS; -} -#endif - -// Log in a histogram the frequency of launching by the different methods. See -// LaunchMode enum for the actual values of the buckets. -void RecordLaunchModeHistogram(LaunchMode mode) { - int bucket = (mode == LM_TO_BE_DECIDED) ? GetLaunchShortcutKind() : mode; - UMA_HISTOGRAM_COUNTS_100("Launch.Modes", bucket); -} - -static bool in_startup = false; - -GURL GetWelcomePageURL() { - std::string welcome_url = l10n_util::GetStringUTF8(IDS_WELCOME_PAGE_URL); - return GURL(welcome_url); -} - -void UrlsToTabs(const std::vector& urls, - std::vector* tabs) { - for (size_t i = 0; i < urls.size(); ++i) { - BrowserInit::LaunchWithProfile::Tab tab; - tab.is_pinned = false; - tab.url = urls[i]; - tabs->push_back(tab); - } -} - -} // namespace - -BrowserInit::BrowserInit() {} - -BrowserInit::~BrowserInit() {} - -void BrowserInit::AddFirstRunTab(const GURL& url) { - first_run_tabs_.push_back(url); -} - -// static -bool BrowserInit::InProcessStartup() { - return in_startup; -} - -bool BrowserInit::LaunchBrowser(const CommandLine& command_line, - Profile* profile, - const FilePath& cur_dir, - bool process_startup, - int* return_code) { - in_startup = process_startup; - DCHECK(profile); - - // Continue with the off-the-record profile from here on if --incognito - if (command_line.HasSwitch(switches::kIncognito)) - profile = profile->GetOffTheRecordProfile(); - - BrowserInit::LaunchWithProfile lwp(cur_dir, command_line, this); - bool launched = lwp.Launch(profile, process_startup); - in_startup = false; - - if (!launched) { - LOG(ERROR) << "launch error"; - if (return_code) - *return_code = ResultCodes::INVALID_CMDLINE_URL; - return false; - } - -#if defined(OS_CHROMEOS) - // Create the WmMessageListener so that it can listen for messages regardless - // of what window has focus. - chromeos::WmMessageListener::instance(); - - // Create the SystemKeyEventListener so it can listen for system keyboard - // messages regardless of focus. - chromeos::SystemKeyEventListener::instance(); - - // Create the WmOverviewController so it can register with the listener. - chromeos::WmOverviewController::instance(); - - // Install the GView request interceptor that will redirect requests - // of compatible documents (PDF, etc) to the GView document viewer. - const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); - if (parsed_command_line.HasSwitch(switches::kEnableGView)) { - chromeos::GViewRequestInterceptor::GetGViewRequestInterceptor(); - } - if (process_startup) { - // TODO(dhg): Try to make this just USBMountObserver::Get()->set_profile - // and have the constructor take care of everything else. - chromeos::MountLibrary* lib = - chromeos::CrosLibrary::Get()->GetMountLibrary(); - chromeos::USBMountObserver* observe = chromeos::USBMountObserver::Get(); - lib->AddObserver(observe); - observe->ScanForDevices(lib); - // Connect the chromeos notifications - - // This observer is a singleton. It is never deleted but the pointer is kept - // in a global so that it isn't reported as a leak. - static chromeos::LowBatteryObserver* low_battery_observer = - new chromeos::LowBatteryObserver(profile); - chromeos::CrosLibrary::Get()->GetPowerLibrary()->AddObserver( - low_battery_observer); - - static chromeos::UpdateObserver* update_observer = - new chromeos::UpdateObserver(profile); - chromeos::CrosLibrary::Get()->GetUpdateLibrary()->AddObserver( - update_observer); - - static chromeos::NetworkMessageObserver* network_message_observer = - new chromeos::NetworkMessageObserver(profile); - chromeos::CrosLibrary::Get()->GetNetworkLibrary() - ->AddNetworkManagerObserver(network_message_observer); - chromeos::CrosLibrary::Get()->GetNetworkLibrary() - ->AddCellularDataPlanObserver(network_message_observer); - - chromeos::CrosLibrary::Get()->GetNetworkLibrary() - ->AddNetworkManagerObserver(chromeos::NetworkStateNotifier::Get()); - } -#endif - return true; -} - -// Tab ------------------------------------------------------------------------ - -BrowserInit::LaunchWithProfile::Tab::Tab() : is_app(false), is_pinned(true) {} - -BrowserInit::LaunchWithProfile::Tab::~Tab() {} - -// LaunchWithProfile ---------------------------------------------------------- - -BrowserInit::LaunchWithProfile::LaunchWithProfile( - const FilePath& cur_dir, - const CommandLine& command_line) - : cur_dir_(cur_dir), - command_line_(command_line), - profile_(NULL), - browser_init_(NULL) { -} - -BrowserInit::LaunchWithProfile::LaunchWithProfile( - const FilePath& cur_dir, - const CommandLine& command_line, - BrowserInit* browser_init) - : cur_dir_(cur_dir), - command_line_(command_line), - profile_(NULL), - browser_init_(browser_init) { -} - -BrowserInit::LaunchWithProfile::~LaunchWithProfile() { -} - -bool BrowserInit::LaunchWithProfile::Launch(Profile* profile, - bool process_startup) { - DCHECK(profile); - profile_ = profile; - - if (command_line_.HasSwitch(switches::kDnsLogDetails)) - chrome_browser_net::EnablePredictorDetailedLog(true); - if (command_line_.HasSwitch(switches::kDnsPrefetchDisable)) - chrome_browser_net::EnablePredictor(false); - - if (command_line_.HasSwitch(switches::kDumpHistogramsOnExit)) - base::StatisticsRecorder::set_dump_on_exit(true); - - if (command_line_.HasSwitch(switches::kRemoteShellPort)) { - std::string port_str = - command_line_.GetSwitchValueASCII(switches::kRemoteShellPort); - int64 port; - if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) - g_browser_process->InitDebuggerWrapper(static_cast(port), false); - else - DLOG(WARNING) << "Invalid remote shell port number " << port; - } else if (command_line_.HasSwitch(switches::kRemoteDebuggingPort)) { - std::string port_str = - command_line_.GetSwitchValueASCII(switches::kRemoteDebuggingPort); - int64 port; - if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) - g_browser_process->InitDebuggerWrapper(static_cast(port), true); - else - DLOG(WARNING) << "Invalid http debugger port number " << port; - } - - if (command_line_.HasSwitch(switches::kUserAgent)) { - webkit_glue::SetUserAgent(command_line_.GetSwitchValueASCII( - switches::kUserAgent)); - } - - // Open the required browser windows and tabs. - // First, see if we're being run as an application window. - if (!OpenApplicationWindow(profile)) { - std::vector urls_to_open = GetURLsFromCommandLine(profile_); - RecordLaunchModeHistogram(urls_to_open.empty()? - LM_TO_BE_DECIDED : LM_WITH_URLS); - ProcessLaunchURLs(process_startup, urls_to_open); - - // If this is an app launch, but we didn't open an app window, it may - // be an app tab. - std::string app_id; - if (IsAppLaunch(NULL, &app_id) && !app_id.empty()) { - // TODO(erikkay): This could fail if |app_id| is invalid (the app was - // uninstalled). We may want to show some reasonable error here. - Browser::OpenApplication(profile, app_id, NULL); - } - - if (process_startup) { - if (browser_defaults::kOSSupportsOtherBrowsers && - !command_line_.HasSwitch(switches::kNoDefaultBrowserCheck)) { - // Check whether we are the default browser. - CheckDefaultBrowser(profile); - } -#if defined(OS_MACOSX) - // Check whether the auto-update system needs to be promoted from user - // to system. - KeystoneInfoBar::PromotionInfoBar(profile); -#endif - } - } else { - RecordLaunchModeHistogram(LM_AS_WEBAPP); - } - -#if defined(OS_WIN) - // Print the selected page if the command line switch exists. Note that the - // current selected tab would be the page which will be printed. - if (command_line_.HasSwitch(switches::kPrint)) { - Browser* browser = BrowserList::GetLastActive(); - browser->Print(); - } -#endif - - // If we're recording or playing back, startup the EventRecorder now - // unless otherwise specified. - if (!command_line_.HasSwitch(switches::kNoEvents)) { - FilePath script_path; - PathService::Get(chrome::FILE_RECORDED_SCRIPT, &script_path); - - bool record_mode = command_line_.HasSwitch(switches::kRecordMode); - bool playback_mode = command_line_.HasSwitch(switches::kPlaybackMode); - - if (record_mode && chrome::kRecordModeEnabled) - base::EventRecorder::current()->StartRecording(script_path); - if (playback_mode) - base::EventRecorder::current()->StartPlayback(script_path); - } - -#if defined(OS_WIN) - if (process_startup) - ShellIntegration::MigrateChromiumShortcuts(); -#endif // defined(OS_WIN) - - return true; -} - -bool BrowserInit::LaunchWithProfile::IsAppLaunch(std::string* app_url, - std::string* app_id) { - if (command_line_.HasSwitch(switches::kApp)) { - if (app_url) - *app_url = command_line_.GetSwitchValueASCII(switches::kApp); - return true; - } - if (command_line_.HasSwitch(switches::kAppId)) { - if (app_id) - *app_id = command_line_.GetSwitchValueASCII(switches::kAppId); - return true; - } - return false; -} - -bool BrowserInit::LaunchWithProfile::OpenApplicationWindow(Profile* profile) { - std::string url_string, app_id; - if (!IsAppLaunch(&url_string, &app_id)) - return false; - - // http://crbug.com/37548 - // TODO(rafaelw): There are two legitimate cases where the extensions - // service could not be ready at this point which need to be handled: - // 1) The locale has changed and the manifests stored in the preferences - // need to be relocalized. - // 2) An externally installed extension will be found and installed. - // Note that this can also fail if the app_id is simply invalid. - // TODO(rafaelw): Do something reasonable here. Pop up a warning panel? - // Open an URL to the gallery page of the extension id? - if (!app_id.empty()) - return Browser::OpenApplication(profile, app_id, NULL) != NULL; - - if (url_string.empty()) - return false; - -#if defined(OS_WIN) // Fix up Windows shortcuts. - ReplaceSubstringsAfterOffset(&url_string, 0, "\\x", "%"); -#endif - GURL url(url_string); - - // Restrict allowed URLs for --app switch. - if (!url.is_empty() && url.is_valid()) { - ChildProcessSecurityPolicy *policy = - ChildProcessSecurityPolicy::GetInstance(); - if (policy->IsWebSafeScheme(url.scheme()) || - url.SchemeIs(chrome::kFileScheme)) { - Browser::OpenApplicationWindow(profile, url); - return true; - } - } - return false; -} - -void BrowserInit::LaunchWithProfile::ProcessLaunchURLs( - bool process_startup, - const std::vector& urls_to_open) { - // If we're starting up in "background mode" (no open browser window) then - // don't open any browser windows. - if (process_startup && command_line_.HasSwitch(switches::kNoStartupWindow)) - return; - - if (process_startup && ProcessStartupURLs(urls_to_open)) { - // ProcessStartupURLs processed the urls, nothing else to do. - return; - } - - if (!process_startup && - (profile_->GetSessionService() && - profile_->GetSessionService()->RestoreIfNecessary(urls_to_open))) { - // We're already running and session restore wanted to run. This can happen - // at various points, such as if there is only an app window running and the - // user double clicked the chrome icon. Return so we don't open the urls. - return; - } - - // Session restore didn't occur, open the urls. - - Browser* browser = NULL; - std::vector adjust_urls = urls_to_open; - if (adjust_urls.empty()) - AddStartupURLs(&adjust_urls); - else if (!command_line_.HasSwitch(switches::kOpenInNewWindow)) - browser = BrowserList::GetLastActive(); - - OpenURLsInBrowser(browser, process_startup, adjust_urls); -} - -bool BrowserInit::LaunchWithProfile::ProcessStartupURLs( - const std::vector& urls_to_open) { - SessionStartupPref pref = GetSessionStartupPref(command_line_, profile_); - if (command_line_.HasSwitch(switches::kTestingChannelID) && - !command_line_.HasSwitch(switches::kRestoreLastSession) && - browser_defaults::kDefaultSessionStartupType != - SessionStartupPref::DEFAULT) { - // When we have non DEFAULT session start type, then we won't open up a - // fresh session. But none of the tests are written with this in mind, so - // we explicitly ignore it during testing. - return false; - } - - if (pref.type == SessionStartupPref::LAST) { - if (!profile_->DidLastSessionExitCleanly() && - !command_line_.HasSwitch(switches::kRestoreLastSession)) { - // The last session crashed. It's possible automatically loading the - // page will trigger another crash, locking the user out of chrome. - // To avoid this, don't restore on startup but instead show the crashed - // infobar. - return false; - } - SessionRestore::RestoreSessionSynchronously(profile_, urls_to_open); - return true; - } - - std::vector tabs = PinnedTabCodec::ReadPinnedTabs(profile_); - - if (!urls_to_open.empty()) { - // If urls were specified on the command line, use them. - UrlsToTabs(urls_to_open, &tabs); - } else if (pref.type == SessionStartupPref::URLS && !pref.urls.empty()) { - // Only use the set of urls specified in preferences if nothing was - // specified on the command line. - UrlsToTabs(pref.urls, &tabs); - } - - if (tabs.empty()) - return false; - - OpenTabsInBrowser(NULL, true, tabs); - return true; -} - -Browser* BrowserInit::LaunchWithProfile::OpenURLsInBrowser( - Browser* browser, - bool process_startup, - const std::vector& urls) { - std::vector tabs; - UrlsToTabs(urls, &tabs); - return OpenTabsInBrowser(browser, process_startup, tabs); -} - -Browser* BrowserInit::LaunchWithProfile::OpenTabsInBrowser( - Browser* browser, - bool process_startup, - const std::vector& tabs) { - DCHECK(!tabs.empty()); - // If we don't yet have a profile, try to use the one we're given from - // |browser|. While we may not end up actually using |browser| (since it - // could be a popup window), we can at least use the profile. - if (!profile_ && browser) - profile_ = browser->profile(); - - if (!browser || browser->type() != Browser::TYPE_NORMAL) { - browser = Browser::Create(profile_); - } else { -#if defined(TOOLKIT_GTK) - // Setting the time of the last action on the window here allows us to steal - // focus, which is what the user wants when opening a new tab in an existing - // browser window. - gtk_util::SetWMLastUserActionTime(browser->window()->GetNativeHandle()); -#endif - } - -#if !defined(OS_MACOSX) - // In kiosk mode, we want to always be fullscreen, so switch to that now. - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) - browser->ToggleFullscreenMode(); -#endif - - bool first_tab = true; - for (size_t i = 0; i < tabs.size(); ++i) { - // We skip URLs that we'd have to launch an external protocol handler for. - // This avoids us getting into an infinite loop asking ourselves to open - // a URL, should the handler be (incorrectly) configured to be us. Anyone - // asking us to open such a URL should really ask the handler directly. - if (!process_startup && !URLRequest::IsHandledURL(tabs[i].url)) - continue; - - int add_types = first_tab ? TabStripModel::ADD_SELECTED : - TabStripModel::ADD_NONE; - add_types |= TabStripModel::ADD_FORCE_INDEX; - if (tabs[i].is_pinned) - add_types |= TabStripModel::ADD_PINNED; - int index = browser->GetIndexForInsertionDuringRestore(i); - - browser::NavigateParams params(browser, tabs[i].url, - PageTransition::START_PAGE); - params.disposition = first_tab ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; - params.tabstrip_index = index; - params.tabstrip_add_types = add_types; - params.extension_app_id = tabs[i].app_id; - browser::Navigate(¶ms); - - if (profile_ && first_tab && process_startup) { - AddCrashedInfoBarIfNecessary(params.target_contents); - AddBadFlagsInfoBarIfNecessary(params.target_contents); - } - - first_tab = false; - } - browser->window()->Show(); - // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial - // focus explicitly. - browser->GetSelectedTabContents()->view()->SetInitialFocus(); - - return browser; -} - -void BrowserInit::LaunchWithProfile::AddCrashedInfoBarIfNecessary( - TabContents* tab) { - // Assume that if the user is launching incognito they were previously - // running incognito so that we have nothing to restore from. - if (!profile_->DidLastSessionExitCleanly() && - !profile_->IsOffTheRecord()) { - // The last session didn't exit cleanly. Show an infobar to the user - // so that they can restore if they want. The delegate deletes itself when - // it is closed. - tab->AddInfoBar(new SessionCrashedInfoBarDelegate(tab)); - } -} - -void BrowserInit::LaunchWithProfile::AddBadFlagsInfoBarIfNecessary( - TabContents* tab) { - // Unsupported flags for which to display a warning that "stability and - // security will suffer". - static const char* kBadFlags[] = { - // All imply disabling the sandbox. - switches::kSingleProcess, - switches::kNoSandbox, - switches::kInProcessWebGL, - NULL - }; - - const char* bad_flag = NULL; - for (const char** flag = kBadFlags; *flag; ++flag) { - if (command_line_.HasSwitch(*flag)) { - bad_flag = *flag; - break; - } - } - - if (bad_flag) { - tab->AddInfoBar(new SimpleAlertInfoBarDelegate(tab, - l10n_util::GetStringFUTF16(IDS_BAD_FLAGS_WARNING_MESSAGE, - UTF8ToUTF16(std::string("--") + bad_flag)), - NULL, false)); - } -} - -std::vector BrowserInit::LaunchWithProfile::GetURLsFromCommandLine( - Profile* profile) { - std::vector urls; - const std::vector& params = command_line_.args(); - - for (size_t i = 0; i < params.size(); ++i) { - FilePath param = FilePath(params[i]); - // Handle Vista way of searching - "? " - if (param.value().find(FILE_PATH_LITERAL("? ")) == 0) { - const TemplateURL* default_provider = - profile->GetTemplateURLModel()->GetDefaultSearchProvider(); - if (!default_provider || !default_provider->url()) { - // No search provider available. Just treat this as regular URL. - urls.push_back(URLFixerUpper::FixupRelativeFile(cur_dir_, param)); - continue; - } - const TemplateURLRef* search_url = default_provider->url(); - DCHECK(search_url->SupportsReplacement()); - std::wstring search_term = param.ToWStringHack().substr(2); - urls.push_back(GURL(search_url->ReplaceSearchTerms( - *default_provider, search_term, - TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()))); - } else { - // This will create a file URL or a regular URL. - // This call can (in rare circumstances) block the UI thread. - // Allow it until this bug is fixed. - // http://code.google.com/p/chromium/issues/detail?id=60641 - GURL url; - { - base::ThreadRestrictions::ScopedAllowIO allow_io; - url = URLFixerUpper::FixupRelativeFile(cur_dir_, param); - } - // Exclude dangerous schemes. - if (url.is_valid()) { - ChildProcessSecurityPolicy *policy = - ChildProcessSecurityPolicy::GetInstance(); - if (policy->IsWebSafeScheme(url.scheme()) || - url.SchemeIs(chrome::kFileScheme) || - !url.spec().compare(chrome::kAboutBlankURL)) { - urls.push_back(url); - } - } - } - } - return urls; -} - -void BrowserInit::LaunchWithProfile::AddStartupURLs( - std::vector* startup_urls) const { - // If we have urls specified beforehand (i.e. from command line) use them - // and nothing else. - if (!startup_urls->empty()) - return; - // If we have urls specified by the first run master preferences use them - // and nothing else. - if (browser_init_) { - if (!browser_init_->first_run_tabs_.empty()) { - std::vector::iterator it = browser_init_->first_run_tabs_.begin(); - while (it != browser_init_->first_run_tabs_.end()) { - // Replace magic names for the actual urls. - if (it->host() == "new_tab_page") { - startup_urls->push_back(GURL()); - } else if (it->host() == "welcome_page") { - startup_urls->push_back(GetWelcomePageURL()); - } else { - startup_urls->push_back(*it); - } - ++it; - } - browser_init_->first_run_tabs_.clear(); - return; - } - } - - // Otherwise open at least the new tab page (and the welcome page, if this - // is the first time the browser is being started), or the set of URLs - // specified on the command line. - startup_urls->push_back(GURL()); // New tab page. - PrefService* prefs = g_browser_process->local_state(); - if (prefs->FindPreference(prefs::kShouldShowWelcomePage) && - prefs->GetBoolean(prefs::kShouldShowWelcomePage)) { - // Reset the preference so we don't show the welcome page next time. - prefs->ClearPref(prefs::kShouldShowWelcomePage); - startup_urls->push_back(GetWelcomePageURL()); - } -} - -void BrowserInit::LaunchWithProfile::CheckDefaultBrowser(Profile* profile) { - // We do not check if we are the default browser if: - // - the user said "don't ask me again" on the infobar earlier. - // - this is the first launch after the first run flow. - if (!profile->GetPrefs()->GetBoolean(prefs::kCheckDefaultBrowser) || - FirstRun::IsChromeFirstRun()) { - return; - } - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, new CheckDefaultBrowserTask()); -} - -bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line, - const FilePath& cur_dir, - bool process_startup, - Profile* profile, - int* return_code, - BrowserInit* browser_init) { - DCHECK(profile); - if (process_startup) { - if (command_line.HasSwitch(switches::kDisablePromptOnRepost)) - NavigationController::DisablePromptOnRepost(); - - // Look for the testing channel ID ONLY during process startup - if (command_line.HasSwitch(switches::kTestingChannelID)) { - std::string testing_channel_id = command_line.GetSwitchValueASCII( - switches::kTestingChannelID); - // TODO(sanjeevr) Check if we need to make this a singleton for - // compatibility with the old testing code - // If there are any extra parameters, we expect each one to generate a - // new tab; if there are none then we get one homepage tab. - int expected_tab_count = 1; - if (command_line.HasSwitch(switches::kNoStartupWindow)) { - expected_tab_count = 0; - } else if (command_line.HasSwitch(switches::kRestoreLastSession)) { - std::string restore_session_value( - command_line.GetSwitchValueASCII(switches::kRestoreLastSession)); - base::StringToInt(restore_session_value, &expected_tab_count); - } else { - expected_tab_count = - std::max(1, static_cast(command_line.args().size())); - } - CreateAutomationProvider( - testing_channel_id, - profile, - static_cast(expected_tab_count)); - } - } - - bool silent_launch = false; - - if (command_line.HasSwitch(switches::kAutomationClientChannelID)) { - std::string automation_channel_id = command_line.GetSwitchValueASCII( - switches::kAutomationClientChannelID); - // If there are any extra parameters, we expect each one to generate a - // new tab; if there are none then we have no tabs - size_t expected_tabs = - std::max(static_cast(command_line.args().size()), 0); - if (expected_tabs == 0) - silent_launch = true; - - if (command_line.HasSwitch(switches::kChromeFrame)) { - CreateAutomationProvider( - automation_channel_id, profile, expected_tabs); - } else { - CreateAutomationProvider(automation_channel_id, - profile, expected_tabs); - } - } - - // If we have been invoked to display a desktop notification on behalf of - // the service process, we do not want to open any browser windows. - if (command_line.HasSwitch(switches::kNotifyCloudPrintTokenExpired)) { - silent_launch = true; - profile->GetCloudPrintProxyService()->ShowTokenExpiredNotification(); - } - - if (command_line.HasSwitch(switches::kExplicitlyAllowedPorts)) { - std::string allowed_ports = - command_line.GetSwitchValueASCII(switches::kExplicitlyAllowedPorts); - net::SetExplicitlyAllowedPorts(allowed_ports); - } - -#if defined(OS_CHROMEOS) - // The browser will be launched after the user logs in. - if (command_line.HasSwitch(switches::kLoginManager) || - command_line.HasSwitch(switches::kLoginPassword)) { - silent_launch = true; - } -#endif - - // If we don't want to launch a new browser window or tab (in the case - // of an automation request), we are done here. - if (!silent_launch) { - return browser_init->LaunchBrowser( - command_line, profile, cur_dir, process_startup, return_code); - } - return true; -} - -template -void BrowserInit::CreateAutomationProvider(const std::string& channel_id, - Profile* profile, - size_t expected_tabs) { - scoped_refptr automation = - new AutomationProviderClass(profile); - automation->ConnectToChannel(channel_id); - automation->SetExpectedTabCount(expected_tabs); - - AutomationProviderList* list = - g_browser_process->InitAutomationProviderList(); - DCHECK(list); - list->AddProvider(automation); -} diff --git a/chrome/browser/browser_init.h b/chrome/browser/browser_init.h deleted file mode 100644 index 28ede89..0000000 --- a/chrome/browser/browser_init.h +++ /dev/null @@ -1,13 +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_BROWSER_INIT_H_ -#define CHROME_BROWSER_BROWSER_INIT_H_ -#pragma once - -#include "chrome/browser/ui/browser_init.h" -// TODO(beng): remove this file once all includes have been updated. - -#endif // CHROME_BROWSER_BROWSER_INIT_H_ - diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc index e992cea..021104b 100644 --- a/chrome/browser/browser_keyevents_browsertest.cc +++ b/chrome/browser/browser_keyevents_browsertest.cc @@ -11,12 +11,12 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 90f7ce3..5fa4a2a 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -33,9 +33,7 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_main_win.h" -#include "chrome/browser/browser_init.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_impl.h" @@ -70,6 +68,8 @@ #include "chrome/browser/service/service_process_control_manager.h" #include "chrome/browser/shell_integration.h" #include "chrome/browser/translate/translate_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_init.h" #include "chrome/common/child_process.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" @@ -97,6 +97,7 @@ #include "net/socket/tcp_client_socket.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_pool.h" +#include "net/url_request/url_request.h" #if defined(USE_LINUX_BREAKPAD) #include "base/linux_util.h" @@ -104,6 +105,7 @@ #endif #if defined(OS_POSIX) && !defined(OS_MACOSX) +#include #include "chrome/browser/browser_main_gtk.h" #include "chrome/browser/gtk/gtk_util.h" #endif @@ -154,16 +156,20 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/screen_lock_library.h" -#include "chrome/browser/chromeos/cros_settings_provider_stats.h" #include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/external_metrics.h" #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/screen_locker.h" #include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/chromeos/metrics_cros_settings_provider.h" #include "chrome/browser/views/browser_dialogs.h" #endif +#if defined(TOOLKIT_USES_GTK) +#include "gfx/gtk_util.h" +#endif + // BrowserMainParts ------------------------------------------------------------ BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) @@ -759,18 +765,104 @@ void MaybeChangeUIFont() { } #endif +#if defined(TOOLKIT_USES_GTK) +static void GLibLogHandler(const gchar* log_domain, + GLogLevelFlags log_level, + const gchar* message, + gpointer userdata) { + if (!log_domain) + log_domain = ""; + if (!message) + message = ""; + + if (strstr(message, "Loading IM context type") || + strstr(message, "wrong ELF class: ELFCLASS64")) { + // http://crbug.com/9643 + // Until we have a real 64-bit build or all of these 32-bit package issues + // are sorted out, don't fatal on ELF 32/64-bit mismatch warnings and don't + // spam the user with more than one of them. + static bool alerted = false; + if (!alerted) { + LOG(ERROR) << "Bug 9643: " << log_domain << ": " << message; + alerted = true; + } + } else if (strstr(message, "gtk_widget_size_allocate(): attempt to " + "allocate widget with width") && + !GTK_CHECK_VERSION(2, 16, 1)) { + // This warning only occurs in obsolete versions of GTK and is harmless. + // http://crbug.com/11133 + } else if (strstr(message, "Theme file for default has no") || + strstr(message, "Theme directory") || + strstr(message, "theme pixmap")) { + LOG(ERROR) << "GTK theme error: " << message; + } else if (strstr(message, "gtk_drag_dest_leave: assertion")) { + LOG(ERROR) << "Drag destination deleted: http://crbug.com/18557"; + } else { +#ifdef NDEBUG + LOG(ERROR) << log_domain << ": " << message; +#else + LOG(FATAL) << log_domain << ": " << message; +#endif + } +} + +static void SetUpGLibLogHandler() { + // Register GLib-handled assertions to go through our logging system. + const char* kLogDomains[] = { NULL, "Gtk", "Gdk", "GLib", "GLib-GObject" }; + for (size_t i = 0; i < arraysize(kLogDomains); i++) { + g_log_set_handler(kLogDomains[i], + static_cast(G_LOG_FLAG_RECURSION | + G_LOG_FLAG_FATAL | + G_LOG_LEVEL_ERROR | + G_LOG_LEVEL_CRITICAL | + G_LOG_LEVEL_WARNING), + GLibLogHandler, + NULL); + } +} +#endif + +void InitializeToolkit(const MainFunctionParams& parameters) { + // TODO(evan): this function is rather subtle, due to the variety + // of intersecting ifdefs we have. To keep it easy to follow, there + // are no #else branches on any #ifs. + +#if defined(TOOLKIT_USES_GTK) + // We want to call g_thread_init(), but in some codepaths (tests) it + // is possible it has already been called. In older versions of + // GTK, it is an error to call g_thread_init twice; unfortunately, + // the API to tell whether it has been called already was also only + // added in a newer version of GTK! Thankfully, this non-intuitive + // check is actually equivalent and sufficient to work around the + // error. + if (!g_thread_supported()) + g_thread_init(NULL); + // Glib type system initialization. Needed at least for gconf, + // used in net/proxy/proxy_config_service_linux.cc. Most likely + // this is superfluous as gtk_init() ought to do this. It's + // definitely harmless, so retained as a reminder of this + // requirement for gconf. + g_type_init(); + // We use glib-dbus for geolocation and it's possible other libraries + // (e.g. gnome-keyring) will use it, so initialize its threading here + // as well. + dbus_g_thread_init(); + gfx::GtkInitFromCommandLine(parameters.command_line_); + SetUpGLibLogHandler(); +#endif + #if defined(TOOLKIT_GTK) -void InitializeToolkit() { // It is important for this to happen before the first run dialog, as it // styles the dialog as well. gtk_util::InitRCStyles(); -} -#elif defined(TOOLKIT_VIEWS) -void InitializeToolkit() { +#endif + +#if defined(TOOLKIT_VIEWS) // The delegate needs to be set before any UI is created so that windows // display the correct icon. if (!views::ViewsDelegate::views_delegate) views::ViewsDelegate::views_delegate = new ChromeViewsDelegate; +#endif #if defined(OS_WIN) gfx::PlatformFontWin::adjust_font_callback = &AdjustUIFont; @@ -783,10 +875,6 @@ void InitializeToolkit() { InitCommonControlsEx(&config); #endif } -#else -void InitializeToolkit() { -} -#endif #if defined(OS_CHROMEOS) @@ -920,6 +1008,10 @@ int BrowserMain(const MainFunctionParams& parameters) { parts(BrowserMainParts::CreateBrowserMainParts(parameters)); parts->EarlyInitialization(); + + // Must happen before we try to use a message loop or display any UI. + InitializeToolkit(parameters); + parts->MainMessageLoopStart(); // WARNING: If we get a WM_ENDSESSION, objects created on the stack here @@ -1009,8 +1101,6 @@ int BrowserMain(const MainFunctionParams& parameters) { InitCrashReporter(); #endif - InitializeToolkit(); // Must happen before we try to display any UI. - // If we're running tests (ui_task is non-null), then the ResourceBundle // has already been initialized. if (parameters.ui_task) { @@ -1215,6 +1305,11 @@ int BrowserMain(const MainFunctionParams& parameters) { // notification it needs to track the logged in user. g_browser_process->profile_manager()->GetDefaultProfile(); + // Allow access to file:// on ChromeOS for tests. + if (parsed_command_line.HasSwitch(switches::kAllowFileAccess)) { + URLRequest::AllowFileAccess(); + } + // There are two use cases for kLoginUser: // 1) if passed in tandem with kLoginPassword, to drive a "StubLogin" // 2) if passed alone, to signal that the indicated user has already diff --git a/chrome/browser/browser_main_gtk.cc b/chrome/browser/browser_main_gtk.cc index 8790726..e86cf72 100644 --- a/chrome/browser/browser_main_gtk.cc +++ b/chrome/browser/browser_main_gtk.cc @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser_main.h" +#include "chrome/browser/browser_main_gtk.h" + +#include +#include +#include #include "app/x11_util.h" #include "app/x11_util_internal.h" @@ -12,8 +16,15 @@ #include "chrome/browser/browser_main_gtk.h" #include "chrome/browser/browser_main_win.h" #include "chrome/browser/metrics/metrics_service.h" +#include "chrome/browser/renderer_host/render_sandbox_host_linux.h" +#include "chrome/browser/zygote_host_linux.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/result_codes.h" +#if defined(USE_NSS) +#include "base/nss_util.h" +#endif + #if defined(USE_LINUX_BREAKPAD) #include "chrome/app/breakpad_linux.h" #endif @@ -34,7 +45,7 @@ int BrowserX11IOErrorHandler(Display* d) { if (!g_in_x11_io_error_handler) { g_in_x11_io_error_handler = true; LOG(ERROR) << "X IO Error detected"; - BrowserList::WindowsSessionEnding(); + BrowserList::SessionEnding(); } return 0; @@ -42,6 +53,45 @@ int BrowserX11IOErrorHandler(Display* d) { } // namespace +void BrowserMainPartsGtk::PreEarlyInitialization() { + BrowserMainPartsPosix::PreEarlyInitialization(); + + SetupSandbox(); + +#if defined(USE_NSS) + // We want to be sure to init NSPR on the main thread. + base::EnsureNSPRInit(); +#endif +} + +void BrowserMainPartsGtk::SetupSandbox() { + // TODO(evanm): move this into SandboxWrapper; I'm just trying to move this + // code en masse out of chrome_dll_main for now. + const char* sandbox_binary = NULL; + struct stat st; + + // In Chromium branded builds, developers can set an environment variable to + // use the development sandbox. See + // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment + if (stat("/proc/self/exe", &st) == 0 && st.st_uid == getuid()) + sandbox_binary = getenv("CHROME_DEVEL_SANDBOX"); + +#if defined(LINUX_SANDBOX_PATH) + if (!sandbox_binary) + sandbox_binary = LINUX_SANDBOX_PATH; +#endif + + std::string sandbox_cmd; + if (sandbox_binary && !parsed_command_line().HasSwitch(switches::kNoSandbox)) + sandbox_cmd = sandbox_binary; + + // Tickle the sandbox host and zygote host so they fork now. + RenderSandboxHostLinux* shost = Singleton::get(); + shost->Init(sandbox_cmd); + ZygoteHost* zhost = Singleton::get(); + zhost->Init(sandbox_cmd); +} + void DidEndMainMessageLoop() { } @@ -82,3 +132,11 @@ void SetBrowserX11ErrorHandlers() { BrowserX11ErrorHandler, BrowserX11IOErrorHandler); } + +#if !defined(OS_CHROMEOS) +// static +BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( + const MainFunctionParams& parameters) { + return new BrowserMainPartsGtk(parameters); +} +#endif diff --git a/chrome/browser/browser_main_gtk.h b/chrome/browser/browser_main_gtk.h index 234ff7a..0be39e7 100644 --- a/chrome/browser/browser_main_gtk.h +++ b/chrome/browser/browser_main_gtk.h @@ -8,6 +8,20 @@ #define CHROME_BROWSER_BROWSER_MAIN_GTK_H_ #pragma once +#include "base/compiler_specific.h" +#include "chrome/browser/browser_main_posix.h" + +class BrowserMainPartsGtk : public BrowserMainPartsPosix { + public: + explicit BrowserMainPartsGtk(const MainFunctionParams& parameters) + : BrowserMainPartsPosix(parameters) {} + + virtual void PreEarlyInitialization() OVERRIDE; + + private: + void SetupSandbox(); +}; + // Installs the X11 error handlers for the browser process. This will // allow us to exit cleanly if X exits before us. void SetBrowserX11ErrorHandlers(); diff --git a/chrome/browser/browser_main_posix.cc b/chrome/browser/browser_main_posix.cc index 8081ef0..9736c66 100644 --- a/chrome/browser/browser_main_posix.cc +++ b/chrome/browser/browser_main_posix.cc @@ -218,12 +218,3 @@ void BrowserMainPartsPosix::PostMainMessageLoopStart() { } } } - -// Mac and Chromeos further subclass BrowserMainPartsPosix. -#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) -// static -BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( - const MainFunctionParams& parameters) { - return new BrowserMainPartsPosix(parameters); -} -#endif // !defined(OS_MACOSX) diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc index 65a991f..de6f2f1 100644 --- a/chrome/browser/browser_main_win.cc +++ b/chrome/browser/browser_main_win.cc @@ -11,6 +11,7 @@ #include #include "app/l10n_util.h" +#include "app/l10n_util_win.h" #include "app/win_util.h" #include "base/command_line.h" #include "base/environment.h" @@ -26,6 +27,7 @@ #include "chrome/browser/views/uninstall_view.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/env_vars.h" +#include "chrome/common/main_function_params.h" #include "chrome/common/result_codes.h" #include "chrome/installer/util/helper.h" #include "chrome/installer/util/install_util.h" @@ -188,12 +190,12 @@ bool CheckMachineLevelInstall() { const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME); const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST; win_util::MessageBox(NULL, text, caption, flags); - std::wstring uninstall_cmd = InstallUtil::GetChromeUninstallCmd(false); - if (!uninstall_cmd.empty()) { - uninstall_cmd.append(L" --"); - uninstall_cmd.append(installer_util::switches::kForceUninstall); - uninstall_cmd.append(L" --"); - uninstall_cmd.append(installer_util::switches::kDoNotRemoveSharedItems); + FilePath uninstall_path(InstallUtil::GetChromeUninstallCmd(false)); + CommandLine uninstall_cmd(uninstall_path); + if (!uninstall_cmd.GetProgram().value().empty()) { + uninstall_cmd.AppendSwitch(installer_util::switches::kForceUninstall); + uninstall_cmd.AppendSwitch( + installer_util::switches::kDoNotRemoveSharedItems); base::LaunchApp(uninstall_cmd, false, false, NULL); } return true; @@ -217,6 +219,13 @@ class BrowserMainPartsWin : public BrowserMainParts { virtual void PreMainMessageLoopStart() { OleInitialize(NULL); + + // If we're running tests (ui_task is non-null), then the ResourceBundle + // has already been initialized. + if (!parameters().ui_task) { + // Override the configured locale with the user's preferred UI language. + l10n_util::OverrideLocaleWithUILanguageList(); + } } private: diff --git a/chrome/browser/browser_navigator.cc b/chrome/browser/browser_navigator.cc deleted file mode 100644 index 54edd14..0000000 --- a/chrome/browser/browser_navigator.cc +++ /dev/null @@ -1,382 +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/browser_navigator.h" - -#include "base/command_line.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_url_handler.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/location_bar.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/status_bubble.h" -#include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/chrome_switches.h" - -namespace { - -// Returns the SiteInstance for |source_contents| if it represents the same -// website as |url|, or NULL otherwise. |source_contents| cannot be NULL. -SiteInstance* GetSiteInstance(TabContents* source_contents, const GURL& url) { - if (!source_contents) - return NULL; - - // Don't use this logic when "--process-per-tab" is specified. - if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab) && - SiteInstance::IsSameWebSite(source_contents->profile(), - source_contents->GetURL(), - url)) { - return source_contents->GetSiteInstance(); - } - return NULL; -} - -// Returns true if the specified Browser can open tabs. Not all Browsers support -// multiple tabs, such as app frames and popups. This function returns false for -// those types of Browser. -bool WindowCanOpenTabs(Browser* browser) { - return browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP) || - browser->tabstrip_model()->empty(); -} - -// Finds an existing Browser compatible with |profile|, making a new one if no -// such Browser is located. -Browser* GetOrCreateBrowser(Profile* profile) { - Browser* browser = BrowserList::FindBrowserWithType(profile, - Browser::TYPE_NORMAL, - false); - return browser ? browser : Browser::Create(profile); -} - -// Returns true if two URLs are equal ignoring their ref (hash fragment). -bool CompareURLsIgnoreRef(const GURL& url, const GURL& other) { - if (url == other) - return true; - // If neither has a ref than there is no point in stripping the refs and - // the URLs are different since the comparison failed in the previous if - // statement. - if (!url.has_ref() && !other.has_ref()) - return false; - url_canon::Replacements replacements; - replacements.ClearRef(); - GURL url_no_ref = url.ReplaceComponents(replacements); - GURL other_no_ref = other.ReplaceComponents(replacements); - return url_no_ref == other_no_ref; -} - -// Returns the index of an existing singleton tab in |params->browser| matching -// the URL specified in |params|. -int GetIndexOfSingletonTab(browser::NavigateParams* params) { - if (params->disposition != SINGLETON_TAB) - return -1; - - // In case the URL was rewritten by the BrowserURLHandler we need to ensure - // that we do not open another URL that will get redirected to the rewritten - // URL. - GURL rewritten_url(params->url); - bool reverse_on_redirect = false; - BrowserURLHandler::RewriteURLIfNecessary(&rewritten_url, - params->browser->profile(), - &reverse_on_redirect); - - for (int i = 0; i < params->browser->tab_count(); ++i) { - TabContents* tab = params->browser->GetTabContentsAt(i); - if (CompareURLsIgnoreRef(tab->GetURL(), params->url) || - CompareURLsIgnoreRef(tab->GetURL(), rewritten_url)) { - params->target_contents = tab; - return i; - } - } - return -1; -} - -// Returns a Browser that can host the navigation or tab addition specified in -// |params|. This might just return the same Browser specified in |params|, or -// some other if that Browser is deemed incompatible. -Browser* GetBrowserForDisposition(browser::NavigateParams* params) { - // If no source TabContents was specified, we use the selected one from the - // target browser. This must happen first, before GetBrowserForDisposition() - // has a chance to replace |params->browser| with another one. - if (!params->source_contents && params->browser) - params->source_contents = params->browser->GetSelectedTabContents(); - - Profile* profile = - params->browser ? params->browser->profile() : params->profile; - - switch (params->disposition) { - case CURRENT_TAB: - if (!params->browser && profile) { - // We specified a profile instead of a browser; find or create one. - params->browser = Browser::GetOrCreateTabbedBrowser(profile); - } - return params->browser; - case SINGLETON_TAB: - case NEW_FOREGROUND_TAB: - case NEW_BACKGROUND_TAB: - // See if we can open the tab in the window this navigator is bound to. - if (params->browser && WindowCanOpenTabs(params->browser)) - return params->browser; - // Find a compatible window and re-execute this command in it. Otherwise - // re-run with NEW_WINDOW. - if (profile) - return GetOrCreateBrowser(profile); - return NULL; - case NEW_POPUP: { - // Make a new popup window. Coerce app-style if |params->browser| or the - // |source| represents an app. - Browser::Type type = Browser::TYPE_POPUP; - if ((params->browser && params->browser->type() == Browser::TYPE_APP) || - (params->source_contents && params->source_contents->is_app())) { - type = Browser::TYPE_APP_POPUP; - } - if (profile) { - Browser* browser = new Browser(type, profile); - browser->set_override_bounds(params->window_bounds); - browser->CreateBrowserWindow(); - return browser; - } - return NULL; - } - case NEW_WINDOW: - // Make a new normal browser window. - if (profile) { - Browser* browser = new Browser(Browser::TYPE_NORMAL, profile); - browser->CreateBrowserWindow(); - return browser; - } - return NULL; - case OFF_THE_RECORD: - // Make or find an incognito window. - if (profile) - return GetOrCreateBrowser(profile->GetOffTheRecordProfile()); - return NULL; - // The following types all result in no navigation. - case SUPPRESS_OPEN: - case SAVE_TO_DISK: - case IGNORE_ACTION: - return NULL; - default: - NOTREACHED(); - } - return NULL; -} - -// Fix disposition and other parameter values depending on prevailing -// conditions. -void NormalizeDisposition(browser::NavigateParams* params) { - // Calculate the WindowOpenDisposition if necessary. - if (params->browser->tabstrip_model()->empty() && - (params->disposition == NEW_BACKGROUND_TAB || - params->disposition == CURRENT_TAB || - params->disposition == SINGLETON_TAB)) { - params->disposition = NEW_FOREGROUND_TAB; - } - if (params->browser->profile()->IsOffTheRecord() && - params->disposition == OFF_THE_RECORD) { - params->disposition = NEW_FOREGROUND_TAB; - } - - // Disposition trumps add types. ADD_SELECTED is a default, so we need to - // remove it if disposition implies the tab is going to open in the - // background. - if (params->disposition == NEW_BACKGROUND_TAB) - params->tabstrip_add_types &= ~TabStripModel::ADD_SELECTED; - - // Code that wants to open a new window typically expects it to be shown - // automatically. - if (params->disposition == NEW_WINDOW || params->disposition == NEW_POPUP) { - params->show_window = true; - params->tabstrip_add_types |= TabStripModel::ADD_SELECTED; - } -} - -// This class makes sure the Browser object held in |params| is made visible -// by the time it goes out of scope, provided |params| wants it to be shown. -class ScopedBrowserDisplayer { - public: - explicit ScopedBrowserDisplayer(browser::NavigateParams* params) - : params_(params) { - } - ~ScopedBrowserDisplayer() { - if (params_->show_window) - params_->browser->window()->Show(); - } - private: - browser::NavigateParams* params_; - DISALLOW_COPY_AND_ASSIGN(ScopedBrowserDisplayer); -}; - -// This class manages the lifetime of a TabContents created by the Navigate() -// function. When Navigate() creates a TabContents for a URL, an instance of -// this class takes ownership of it via TakeOwnership() until the TabContents -// is added to a tab strip at which time ownership is relinquished via -// ReleaseOwnership(). If this object goes out of scope without being added -// to a tab strip, the created TabContents is deleted to avoid a leak and the -// params->target_contents field is set to NULL. -class ScopedTargetContentsOwner { - public: - explicit ScopedTargetContentsOwner(browser::NavigateParams* params) - : params_(params) { - } - ~ScopedTargetContentsOwner() { - if (target_contents_owner_.get()) - params_->target_contents = NULL; - } - - // Assumes ownership of |params_|' target_contents until ReleaseOwnership - // is called. - void TakeOwnership() { - target_contents_owner_.reset(params_->target_contents); - } - - // Relinquishes ownership of |params_|' target_contents. - TabContents* ReleaseOwnership() { - return target_contents_owner_.release(); - } - - private: - browser::NavigateParams* params_; - scoped_ptr target_contents_owner_; - DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner); -}; - -} // namespace - -namespace browser { - -NavigateParams::NavigateParams( - Browser* a_browser, - const GURL& a_url, - PageTransition::Type a_transition) - : url(a_url), - target_contents(NULL), - source_contents(NULL), - disposition(CURRENT_TAB), - transition(a_transition), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_SELECTED), - show_window(false), - browser(a_browser), - profile(NULL) { -} - -NavigateParams::NavigateParams(Browser* a_browser, - TabContents* a_target_contents) - : target_contents(a_target_contents), - source_contents(NULL), - disposition(CURRENT_TAB), - transition(PageTransition::LINK), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_SELECTED), - show_window(false), - browser(a_browser), - profile(NULL) { -} - -NavigateParams::~NavigateParams() { -} - -void Navigate(NavigateParams* params) { - params->browser = GetBrowserForDisposition(params); - if (!params->browser) - return; - // Navigate() must not return early after this point. - - // Make sure the Browser is shown if params call for it. - ScopedBrowserDisplayer displayer(params); - - // Makes sure any TabContents created by this function is destroyed if - // not properly added to a tab strip. - ScopedTargetContentsOwner target_contents_owner(params); - - // Some dispositions need coercion to base types. - NormalizeDisposition(params); - - // Determine if the navigation was user initiated. If it was, we need to - // inform the target TabContents, and we may need to update the UI. - PageTransition::Type base_transition = - PageTransition::StripQualifier(params->transition); - bool user_initiated = base_transition == PageTransition::TYPED || - base_transition == PageTransition::AUTO_BOOKMARK; - - // If no target TabContents was specified, we need to construct one if we are - // supposed to target a new tab. - if (!params->target_contents) { - if (params->disposition != CURRENT_TAB) { - params->target_contents = - new TabContents(params->browser->profile(), - GetSiteInstance(params->source_contents, params->url), - MSG_ROUTING_NONE, - params->source_contents, - NULL); - // This function takes ownership of |params->target_contents| until it - // is added to a TabStripModel. - target_contents_owner.TakeOwnership(); - params->target_contents->SetExtensionAppById(params->extension_app_id); - // TODO(sky): figure out why this is needed. Without it we seem to get - // failures in startup tests. - // By default, content believes it is not hidden. When adding contents - // in the background, tell it that it's hidden. - if ((params->tabstrip_add_types & TabStripModel::ADD_SELECTED) == 0) { - // TabStripModel::AddTabContents invokes HideContents if not foreground. - params->target_contents->WasHidden(); - } - } else { - // ... otherwise if we're loading in the current tab, the target is the - // same as the source. - params->target_contents = params->source_contents; - DCHECK(params->target_contents); - } - - if (user_initiated) { - RenderViewHostDelegate::BrowserIntegration* integration = - params->target_contents; - integration->OnUserGesture(); - } - - // Perform the actual navigation. - GURL url = params->url.is_empty() ? params->browser->GetHomePage() - : params->url; - params->target_contents->controller().LoadURL(url, params->referrer, - params->transition); - } else { - // |target_contents| was specified non-NULL, and so we assume it has already - // been navigated appropriately. We need to do nothing more other than - // add it to the appropriate tabstrip. - } - - if (params->source_contents == params->target_contents) { - // The navigation occurred in the source tab, so update the UI. - params->browser->UpdateUIForNavigationInTab(params->target_contents, - params->transition, - user_initiated); - } else { - // The navigation occurred in some other tab. - int singleton_index = GetIndexOfSingletonTab(params); - if (params->disposition == SINGLETON_TAB && singleton_index >= 0) { - // The navigation should re-select an existing tab in the target Browser. - params->browser->SelectTabContentsAt(singleton_index, user_initiated); - } else { - // If some non-default value is set for the index, we should tell the - // TabStripModel to respect it. - if (params->tabstrip_index != -1) - params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX; - - // The navigation should insert a new tab into the target Browser. - params->browser->tabstrip_model()->AddTabContents( - params->target_contents, - params->tabstrip_index, - params->transition, - params->tabstrip_add_types); - // Now that the |params->target_contents| is safely owned by the target - // Browser's TabStripModel, we can release ownership. - target_contents_owner.ReleaseOwnership(); - } - } -} - -} // namespace browser diff --git a/chrome/browser/browser_navigator.h b/chrome/browser/browser_navigator.h deleted file mode 100644 index eaeabbe..0000000 --- a/chrome/browser/browser_navigator.h +++ /dev/null @@ -1,13 +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_BROWSER_NAVIGATOR_H_ -#define CHROME_BROWSER_BROWSER_NAVIGATOR_H_ -#pragma once - -#include "chrome/browser/ui/browser_navigator.h" -// TODO(beng): remove this file once all includes have been updated. - -#endif // CHROME_BROWSER_BROWSER_NAVIGATOR_H_ - diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 5497932..7c2e307 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h @@ -41,6 +41,7 @@ class WaitableEvent; namespace printing { class PrintJobManager; +class PrintPreviewTabController; } class IOThread; @@ -116,6 +117,8 @@ class BrowserProcess { virtual bool IsShuttingDown() = 0; virtual printing::PrintJobManager* print_job_manager() = 0; + virtual printing::PrintPreviewTabController* + print_preview_tab_controller() = 0; virtual GoogleURLTracker* google_url_tracker() = 0; virtual IntranetRedirectDetector* intranet_redirect_detector() = 0; diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 6c384d8..bf1a52f 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -41,6 +41,7 @@ #include "chrome/browser/plugin_updater.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/printing/print_job_manager.h" +#include "chrome/browser/printing/print_preview_tab_controller.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" @@ -434,6 +435,14 @@ printing::PrintJobManager* BrowserProcessImpl::print_job_manager() { return print_job_manager_.get(); } +printing::PrintPreviewTabController* + BrowserProcessImpl::print_preview_tab_controller() { + DCHECK(CalledOnValidThread()); + if (!print_preview_tab_controller_.get()) + CreatePrintPreviewTabController(); + return print_preview_tab_controller_.get(); +} + GoogleURLTracker* BrowserProcessImpl::google_url_tracker() { DCHECK(CalledOnValidThread()); if (!google_url_tracker_.get()) @@ -555,7 +564,7 @@ void BrowserProcessImpl::CreateIOThread() { background_x11_thread_.swap(background_x11_thread); #endif - scoped_ptr thread(new IOThread); + scoped_ptr thread(new IOThread(local_state())); base::Thread::Options options; options.message_loop_type = MessageLoop::TYPE_IO; if (!thread->StartWithOptions(options)) @@ -580,12 +589,6 @@ void BrowserProcessImpl::CreateFileThread() { if (!thread->StartWithOptions(options)) return; file_thread_.swap(thread); - - // ExtensionResource is in chrome/common, so it cannot depend on - // chrome/browser, which means it cannot lookup what the File thread is. - // We therefore store the thread ID from here so we can validate the proper - // thread usage in the ExtensionResource class. - ExtensionResource::set_file_thread_id(file_thread_->thread_id()); } void BrowserProcessImpl::CreateDBThread() { @@ -705,6 +708,11 @@ void BrowserProcessImpl::CreateTabCloseableStateWatcher() { tab_closeable_state_watcher_.reset(TabCloseableStateWatcher::Create()); } +void BrowserProcessImpl::CreatePrintPreviewTabController() { + DCHECK(print_preview_tab_controller_.get() == NULL); + print_preview_tab_controller_ = new printing::PrintPreviewTabController(); +} + // The BrowserProcess object must outlive the file thread so we use traits // which don't do any management. DISABLE_RUNNABLE_METHOD_REFCOUNT(BrowserProcessImpl); diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 727cfb2..0aeb976 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -62,6 +62,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { virtual unsigned int ReleaseModule(); virtual bool IsShuttingDown(); virtual printing::PrintJobManager* print_job_manager(); + virtual printing::PrintPreviewTabController* print_preview_tab_controller(); virtual GoogleURLTracker* google_url_tracker(); virtual IntranetRedirectDetector* intranet_redirect_detector(); virtual const std::string& GetApplicationLocale(); @@ -110,6 +111,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { void CreateNotificationUIManager(); void CreateStatusTrayManager(); void CreateTabCloseableStateWatcher(); + void CreatePrintPreviewTabController(); #if defined(IPC_MESSAGE_LOG_ENABLED) void SetIPCLoggingEnabledForChildProcesses(bool enabled); @@ -158,6 +160,9 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { bool created_sidebar_manager_; scoped_refptr sidebar_manager_; + scoped_refptr + print_preview_tab_controller_; + scoped_ptr clipboard_; // Manager for desktop notification UI. diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index da04f3a..b01358a 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -71,6 +71,7 @@ without changes to the corresponding grd file. etaa --> + diff --git a/chrome/browser/browser_uitest.cc b/chrome/browser/browser_uitest.cc index 5d2c448..d0566fe 100644 --- a/chrome/browser/browser_uitest.cc +++ b/chrome/browser/browser_uitest.cc @@ -11,8 +11,8 @@ #include "base/test/test_file_util.h" #include "base/values.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/platform_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" @@ -278,7 +278,7 @@ public: void SetUp() { PathService::Get(base::DIR_TEMP, &tmp_profile_); tmp_profile_ = tmp_profile_.AppendASCII("tmp_profile"); - tmp_profile_ = tmp_profile_.Append(L"Test Chrome Géraldine"); + tmp_profile_ = tmp_profile_.Append(L"Test Chrome G�raldine"); // Create a fresh, empty copy of this directory. file_util::Delete(tmp_profile_, true); diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc index ced833d..b532f30 100644 --- a/chrome/browser/browsing_data_remover.cc +++ b/chrome/browser/browsing_data_remover.cc @@ -228,7 +228,10 @@ void BrowsingDataRemover::Remove(int remove_mask) { delete_end_); web_data_service->RemoveAutoFillProfilesAndCreditCardsModifiedBetween( delete_begin_, delete_end_); - profile_->GetPersonalDataManager()->Refresh(); + PersonalDataManager* data_manager = profile_->GetPersonalDataManager(); + if (data_manager) { + data_manager->Refresh(); + } } } diff --git a/chrome/browser/bug_report_data.cc b/chrome/browser/bug_report_data.cc index 9219e52..c277d88 100644 --- a/chrome/browser/bug_report_data.cc +++ b/chrome/browser/bug_report_data.cc @@ -4,7 +4,7 @@ #include "chrome/browser/bug_report_data.h" -#include "chrome/browser/browser.h" +#include "chrome/browser/ui/browser.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/notifications/system_notification.h" diff --git a/chrome/browser/child_process_security_policy_browsertest.cc b/chrome/browser/child_process_security_policy_browsertest.cc index 336ba24..bedac81 100644 --- a/chrome/browser/child_process_security_policy_browsertest.cc +++ b/chrome/browser/child_process_security_policy_browsertest.cc @@ -7,10 +7,10 @@ #include "base/basictypes.h" #include "base/file_path.h" #include "base/process_util.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/child_process_security_policy.h" #include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index b4bb7cb..997221d 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm @@ -54,15 +54,38 @@ static IMP gOriginalInitIMP = NULL; } if (!found) { - // Dear reader: something you just did provoked an NSException. - // Please check your backtrace and see if you can't file a bug with - // a repro case. You should be able to safely continue past the - // NOTREACHED(), but feel free to comment it out locally if it is - // making your job hard. - DLOG(ERROR) << "Someone is preparing to raise an exception! " - << base::SysNSStringToUTF8(aName) << " *** " - << base::SysNSStringToUTF8(aReason); - NOTREACHED(); + // Update breakpad with the exception info. + static NSString* const kNSExceptionKey = @"nsexception"; + NSString* value = + [NSString stringWithFormat:@"%@ reason %@", aName, aReason]; + SetCrashKeyValue(kNSExceptionKey, value); + + // Force crash for selected exceptions to generate crash dumps. + BOOL fatal = NO; + if (aName == NSInternalInconsistencyException) { + NSString* const kNSMenuItemArrayBoundsCheck = + @"Invalid parameter not satisfying: (index >= 0) && (index < [_itemArray count])"; + if ([aReason isEqualToString:kNSMenuItemArrayBoundsCheck]) { + fatal = YES; + } + } + + // Dear reader: Something you just did provoked an NSException. + // NSException is implemented in terms of setjmp()/longjmp(), + // which does poor things when combined with C++ scoping + // (destructors are skipped). Chrome should be NSException-free, + // please check your backtrace and see if you can't file a bug + // with a repro case. + if (fatal) { + LOG(FATAL) << "Someone is trying to raise an exception! " + << base::SysNSStringToUTF8(value); + } else { + // Make sure that developers see when their code throws + // exceptions. + DLOG(ERROR) << "Someone is trying to raise an exception! " + << base::SysNSStringToUTF8(value); + NOTREACHED(); + } } // Forward to the original version. @@ -171,7 +194,7 @@ BOOL SwizzleNSExceptionInit() { } - init { - DCHECK(SwizzleNSExceptionInit()); + CHECK(SwizzleNSExceptionInit()); return [super init]; } diff --git a/chrome/browser/chromeos/browser_main_chromeos.h b/chrome/browser/chromeos/browser_main_chromeos.h index de8deb4..b2fb924 100644 --- a/chrome/browser/chromeos/browser_main_chromeos.h +++ b/chrome/browser/chromeos/browser_main_chromeos.h @@ -5,12 +5,12 @@ #ifndef CHROME_BROWSER_CHROMEOS_BROWSER_MAIN_CHROMEOS_H_ #define CHROME_BROWSER_CHROMEOS_BROWSER_MAIN_CHROMEOS_H_ -#include "chrome/browser/browser_main_posix.h" +#include "chrome/browser/browser_main_gtk.h" -class BrowserMainPartsChromeos : public BrowserMainPartsPosix { +class BrowserMainPartsChromeos : public BrowserMainPartsGtk { public: explicit BrowserMainPartsChromeos(const MainFunctionParams& parameters) - : BrowserMainPartsPosix(parameters) {} + : BrowserMainPartsGtk(parameters) {} protected: virtual void PostMainMessageLoopStart(); diff --git a/chrome/browser/chromeos/cros/cros_mock.cc b/chrome/browser/chromeos/cros/cros_mock.cc index 5e66df0..8b0b596 100644 --- a/chrome/browser/chromeos/cros/cros_mock.cc +++ b/chrome/browser/chromeos/cros/cros_mock.cc @@ -7,7 +7,6 @@ #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_input_method_library.h" @@ -21,6 +20,7 @@ #include "chrome/browser/chromeos/cros/mock_touchpad_library.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/login/wizard_screen.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" @@ -279,7 +279,7 @@ void CrosMock::SetNetworkLibraryStatusAreaExpectations() { // NetworkMenuButton::OnNetworkManagerChanged() calls: EXPECT_CALL(*mock_network_library_, active_network()) - .Times(1) + .Times(AnyNumber()) .WillRepeatedly((Return((const Network*)(NULL)))) .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, wifi_connecting()) @@ -304,6 +304,10 @@ void CrosMock::SetNetworkLibraryStatusAreaExpectations() { .Times(1) .WillRepeatedly((Return(true))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, ethernet_enabled()) + .Times(1) + .WillRepeatedly((Return(true))) + .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, ethernet_connected()) .Times(1) .WillRepeatedly((Return(false))) @@ -316,10 +320,18 @@ void CrosMock::SetNetworkLibraryStatusAreaExpectations() { .Times(1) .WillRepeatedly((Return(false))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, wifi_enabled()) + .Times(1) + .WillRepeatedly((Return(false))) + .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, cellular_available()) .Times(1) .WillRepeatedly((Return(false))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, cellular_enabled()) + .Times(1) + .WillRepeatedly((Return(false))) + .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, Connected()) .Times(1) .WillRepeatedly((Return(false))) diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chrome/browser/chromeos/cros/cryptohome_library.cc index cd9a31d..bfc8ef1 100644 --- a/chrome/browser/chromeos/cros/cryptohome_library.cc +++ b/chrome/browser/chromeos/cros/cryptohome_library.cc @@ -4,10 +4,12 @@ #include "chrome/browser/chromeos/cros/cryptohome_library.h" +#include "base/command_line.h" #include "base/hash_tables.h" #include "base/message_loop.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/common/chrome_switches.h" namespace chromeos { @@ -213,6 +215,14 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary { bool Mount(const std::string& user_email, const std::string& passhash, int* error_code) { + // For testing password change. + if (user_email == + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kLoginUserWithNewPassword)) { + *error_code = kCryptohomeMountErrorKeyFailure; + return false; + } + return true; } diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc index 7e878dd..75ccbc4 100644 --- a/chrome/browser/chromeos/cros/network_library.cc +++ b/chrome/browser/chromeos/cros/network_library.cc @@ -8,6 +8,7 @@ #include #include "app/l10n_util.h" +#include "base/i18n/time_formatting.h" #include "base/stl_util-inl.h" #include "base/string_number_conversions.h" #include "base/string_util.h" @@ -15,6 +16,7 @@ #include "base/values.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/common/time_format.h" #include "grit/generated_resources.h" namespace { @@ -33,6 +35,7 @@ namespace { // straight out of libcros:chromeos_network.cc. Fix this by moving // all handling of properties into libcros. // Network service properties we are interested in monitoring +static const char* kConnectableProperty = "Connectable"; static const char* kIsActiveProperty = "IsActive"; static const char* kStateProperty = "State"; static const char* kSignalStrengthProperty = "Strength"; @@ -157,9 +160,11 @@ static std::string WrapWithTD(std::string text) { // Helper function to create an Html table header for a Network. static std::string ToHtmlTableHeader(Network* network) { std::string str; - if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) { - str += WrapWithTH("Name") + WrapWithTH("Auto-Connect") + - WrapWithTH("Strength"); + if (network->type() == TYPE_ETHERNET) { + str += WrapWithTH("Active"); + } else if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) { + str += WrapWithTH("Name") + WrapWithTH("Active") + + WrapWithTH("Auto-Connect") + WrapWithTH("Strength"); if (network->type() == TYPE_WIFI) str += WrapWithTH("Encryption") + WrapWithTH("Passphrase") + WrapWithTH("Identity") + WrapWithTH("Certificate"); @@ -171,9 +176,12 @@ static std::string ToHtmlTableHeader(Network* network) { // Helper function to create an Html table row for a Network. static std::string ToHtmlTableRow(Network* network) { std::string str; - if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) { + if (network->type() == TYPE_ETHERNET) { + str += WrapWithTD(base::IntToString(network->is_active())); + } else if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) { WirelessNetwork* wireless = static_cast(network); str += WrapWithTD(wireless->name()) + + WrapWithTD(base::IntToString(network->is_active())) + WrapWithTD(base::IntToString(wireless->auto_connect())) + WrapWithTD(base::IntToString(wireless->strength())); if (network->type() == TYPE_WIFI) { @@ -217,14 +225,18 @@ Network::Network(const Network& network) { type_ = network.type(); state_ = network.state(); error_ = network.error(); + connectable_ = network.connectable(); + is_active_ = network.is_active(); } void Network::Clear() { - state_ = STATE_UNKNOWN; - error_ = ERROR_UNKNOWN; service_path_.clear(); device_path_.clear(); ip_address_.clear(); + type_ = TYPE_UNKNOWN; + state_ = STATE_UNKNOWN; + error_ = ERROR_UNKNOWN; + connectable_ = true; is_active_ = false; } @@ -234,20 +246,9 @@ Network::Network(const ServiceInfo* service) { error_ = service->error; service_path_ = SafeString(service->service_path); device_path_ = SafeString(service->device_path); + connectable_ = service->connectable; is_active_ = service->is_active; - ip_address_.clear(); - // If connected, get ip config. - if (EnsureCrosLoaded() && connected() && service->device_path) { - IPConfigStatus* ipconfig_status = ListIPConfigs(service->device_path); - if (ipconfig_status) { - for (int i = 0; i < ipconfig_status->size; i++) { - IPConfig ipconfig = ipconfig_status->ips[i]; - if (strlen(ipconfig.address) > 0) - ip_address_ = ipconfig.address; - } - FreeIPConfigStatus(ipconfig_status); - } - } + InitIPAddress(); } // Used by GetHtmlInfo() which is called from the about:network handler. @@ -316,6 +317,24 @@ std::string Network::GetErrorString() const { return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED); } +void Network::InitIPAddress() { + ip_address_.clear(); + // If connected, get ip config. + if (EnsureCrosLoaded() && connected()) { + 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]; + if (strlen(ipconfig.address) > 0) { + ip_address_ = ipconfig.address; + break; + } + } + FreeIPConfigStatus(ipconfig_status); + } + } +} + //////////////////////////////////////////////////////////////////////////////// // WirelessNetwork WirelessNetwork::WirelessNetwork(const WirelessNetwork& network) @@ -342,6 +361,124 @@ void WirelessNetwork::Clear() { favorite_ = false; } +//////////////////////////////////////////////////////////////////////////////// +// CellularDataPlan + +string16 CellularDataPlan::GetPlanDesciption() const { + switch (plan_type) { + case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: { + return l10n_util::GetStringFUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_UNLIMITED_DATA, + WideToUTF16(base::TimeFormatFriendlyDate(plan_start_time))); + break; + } + case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: { + return l10n_util::GetStringFUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_DATA, + FormatBytes(plan_data_bytes, + GetByteDisplayUnits(plan_data_bytes), + true), + WideToUTF16(base::TimeFormatFriendlyDate( + plan_start_time))); + } + case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: { + return l10n_util::GetStringFUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_RECEIVED_FREE_DATA, + FormatBytes(plan_data_bytes, + GetByteDisplayUnits(plan_data_bytes), + true), + WideToUTF16(base::TimeFormatFriendlyDate( + plan_start_time))); + default: + break; + } + } + return string16(); +} + +string16 CellularDataPlan::GetRemainingWarning() const { + if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) { + // Time based plan. Show nearing expiration and data expiration. + int64 time_left = base::TimeDelta( + plan_end_time - update_time).InSeconds(); + if (time_left <= 0) { + return l10n_util::GetStringFUTF16( + IDS_NETWORK_MINUTES_REMAINING_MESSAGE, ASCIIToUTF16("0")); + } else if (time_left <= chromeos::kCellularDataVeryLowSecs) { + return l10n_util::GetStringFUTF16( + IDS_NETWORK_MINUTES_UNTIL_EXPIRATION_MESSAGE, + UTF8ToUTF16(base::Int64ToString(time_left/60))); + } + } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID || + plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) { + // Metered plan. Show low data and out of data. + int64 bytes_remaining = plan_data_bytes - data_bytes_used; + if (bytes_remaining <= 0) { + return l10n_util::GetStringFUTF16( + IDS_NETWORK_DATA_REMAINING_MESSAGE, ASCIIToUTF16("0")); + } else if (bytes_remaining <= chromeos::kCellularDataVeryLowBytes) { + return l10n_util::GetStringFUTF16( + IDS_NETWORK_DATA_REMAINING_MESSAGE, + UTF8ToUTF16(base::Int64ToString(bytes_remaining/(1024*1024)))); + } + } + return string16(); +} + +string16 CellularDataPlan::GetDataRemainingDesciption() const { + switch (plan_type) { + case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: { + return l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_UNLIMITED); + } + case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: { + return FormatBytes(plan_data_bytes - data_bytes_used, + GetByteDisplayUnits(plan_data_bytes - data_bytes_used), + true); + } + case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: { + return FormatBytes(plan_data_bytes - data_bytes_used, + GetByteDisplayUnits(plan_data_bytes - data_bytes_used), + true); + } + default: + break; + } + return string16(); +} + +string16 CellularDataPlan::GetUsageInfo() const { + if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) { + // Time based plan. Show nearing expiration and data expiration. + int64 time_left = base::TimeDelta( + plan_end_time - update_time).InSeconds(); + return l10n_util::GetStringFUTF16( + IDS_NETWORK_MINUTES_UNTIL_EXPIRATION_MESSAGE, + UTF8ToUTF16(base::Int64ToString(time_left/60))); + } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID || + plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) { + // Metered plan. Show low data and out of data. + int64 bytes_remaining = plan_data_bytes - data_bytes_used; + if (bytes_remaining <= 0) + bytes_remaining = 0; + return l10n_util::GetStringFUTF16( + IDS_NETWORK_DATA_AVAILABLE_MESSAGE, + UTF8ToUTF16(base::Int64ToString(bytes_remaining/(1024*1024)))); + } + return string16(); +} + +int64 CellularDataPlan::remaining_minutes() const { + return base::TimeDelta(plan_end_time - update_time).InMinutes(); +} + +int64 CellularDataPlan::remaining_mbytes() const { + return (plan_data_bytes - data_bytes_used) / (1024 * 1024); +} + +string16 CellularDataPlan::GetPlanExpiration() const { + return TimeFormat::TimeRemaining(plan_end_time - base::Time::Now()); +} //////////////////////////////////////////////////////////////////////////////// // CellularNetwork @@ -1048,6 +1185,23 @@ class NetworkLibraryImpl : public NetworkLibrary { return wifi_; if (cellular_ && cellular_->is_active()) return cellular_; + // Due to bug chromium-os:9310, if no active network is found, + // use the first connected. + // TODO(chocobo): Remove when bug 9310 is fixed. + // START BUG 9310 WORKAROUND + if (ethernet_ && ethernet_->connected()) { + ethernet_->set_active(true); + return ethernet_; + } + if (wifi_ && wifi_->connected()) { + wifi_->set_active(true); + return wifi_; + } + if (cellular_ && cellular_->connected()) { + cellular_->set_active(true); + return cellular_; + } + // END BUG 9310 WORKAROUND return NULL; } @@ -1119,25 +1273,32 @@ class NetworkLibraryImpl : public NetworkLibrary { output.append("(To auto-refresh this page: about:network/<secs>)"); } - output.append("

Ethernet:

"); - if (ethernet_ && ethernet_enabled()) { - output.append("" + ToHtmlTableHeader(ethernet_) + ""); - output.append("" + ToHtmlTableRow(ethernet_) + ""); + if (ethernet_enabled()) { + output.append("

Ethernet:

"); + if (ethernet_) { + output.append("" + ToHtmlTableHeader(ethernet_) + ""); + output.append("" + ToHtmlTableRow(ethernet_) + ""); + } } - output.append("

Wifi:

"); - for (size_t i = 0; i < wifi_networks_.size(); ++i) { - if (i == 0) - output.append("" + ToHtmlTableHeader(wifi_networks_[i]) + ""); - output.append("" + ToHtmlTableRow(wifi_networks_[i]) + ""); + if (wifi_enabled()) { + output.append("

Wifi:

"); + for (size_t i = 0; i < wifi_networks_.size(); ++i) { + if (i == 0) + output.append("" + ToHtmlTableHeader(wifi_networks_[i]) + + ""); + output.append("" + ToHtmlTableRow(wifi_networks_[i]) + ""); + } } - output.append("

Cellular:

"); - for (size_t i = 0; i < cellular_networks_.size(); ++i) { - if (i == 0) - output.append("" + ToHtmlTableHeader(cellular_networks_[i]) + - ""); - output.append("" + ToHtmlTableRow(cellular_networks_[i]) + ""); + if (cellular_enabled()) { + output.append("

Cellular:

"); + for (size_t i = 0; i < cellular_networks_.size(); ++i) { + if (i == 0) + output.append("" + ToHtmlTableHeader(cellular_networks_[i]) + + ""); + output.append("" + ToHtmlTableRow(cellular_networks_[i]) + ""); + } } output.append("

Remembered Wifi:

"); @@ -1251,16 +1412,16 @@ class NetworkLibraryImpl : public NetworkLibrary { DVLOG(1) << "Remembered networks:"; for (int i = 0; i < system->remembered_service_size; i++) { const ServiceInfo* service = system->GetRememberedServiceInfo(i); - // Only services marked as auto_connect are considered remembered - // networks. + // Only services marked as favorite are considered remembered networks. // TODO(chocobo): Don't add to remembered service if currently available. - if (service->auto_connect) { + if (service->favorite) { DVLOG(1) << " (" << service->type << ") " << service->name << " mode=" << service->mode << " sec=" << service->security << " pass=" << service->passphrase << " id=" << service->identity << " certpath=" << service->cert_path + << " fav=" << service->favorite << " auto=" << service->auto_connect; if (service->type == TYPE_WIFI) { remembered_wifi_networks->push_back(new WifiNetwork(service)); @@ -1304,7 +1465,9 @@ class NetworkLibraryImpl : public NetworkLibrary { wifi3->set_name("Fake Wifi 3"); wifi3->set_strength(50); wifi3->set_connected(false); - wifi3->set_encryption(SECURITY_WEP); + wifi3->set_encryption(SECURITY_8021X); + wifi3->set_identity("nobody@google.com"); + wifi3->set_cert_path("SETTINGS:key_id=3,cert_id=3,pin=111111"); wifi_networks_.push_back(wifi3); wifi_ = wifi2; @@ -1424,6 +1587,8 @@ class NetworkLibraryImpl : public NetworkLibrary { std::string prev_cellular_service_path = cellular_ ? cellular_->service_path() : std::string(); + bool prev_cellular_connected = cellular_ ? + cellular_->connected() : false; ClearNetworks(); @@ -1442,8 +1607,9 @@ class NetworkLibraryImpl : public NetworkLibrary { if (cellular_networks_[i]->connecting_or_connected()) { cellular_ = cellular_networks_[i]; // If new cellular, then request update of the data plan list. - if (cellular_networks_[i]->service_path() != - prev_cellular_service_path) { + if ((cellular_networks_[i]->service_path() != + prev_cellular_service_path) || + (!prev_cellular_connected && cellular_networks_[i]->connected())) { RefreshCellularDataPlans(cellular_); } break; // There is only one connected or connecting cellular network. @@ -1518,12 +1684,18 @@ class NetworkLibraryImpl : public NetworkLibrary { } network = wireless; } - if (strcmp(key, kIsActiveProperty) == 0) { + if (strcmp(key, kConnectableProperty) == 0) { + if (value->GetAsBoolean(&boolval)) + network->set_connectable(boolval); + } else if (strcmp(key, kIsActiveProperty) == 0) { if (value->GetAsBoolean(&boolval)) network->set_active(boolval); } else if (strcmp(key, kStateProperty) == 0) { - if (value->GetAsString(&stringval)) + if (value->GetAsString(&stringval)) { network->set_state(ParseState(stringval)); + // State changed, so refresh IP address. + network->InitIPAddress(); + } } NotifyNetworkChanged(network); } diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h index 8296660..4d52f88 100644 --- a/chrome/browser/chromeos/cros/network_library.h +++ b/chrome/browser/chromeos/cros/network_library.h @@ -9,9 +9,11 @@ #include #include +#include "base/gtest_prod_util.h" #include "base/observer_list.h" #include "base/platform_thread.h" #include "base/singleton.h" +#include "base/string16.h" #include "base/timer.h" #include "cros/chromeos_network.h" @@ -48,6 +50,9 @@ class Network { state_ == STATE_IDLE; } ConnectionError error() const { return error_; } ConnectionState state() const { return state_; } + // Is this network connectable. Some networks are not yet ready to be + // connected. For example, an 8021X network without certificates. + bool connectable() const { return connectable_; } // Is this the active network, i.e, the one through which // network traffic is being routed? A network can be connected, // but not be carrying traffic. @@ -67,6 +72,7 @@ class Network { : type_(TYPE_UNKNOWN), state_(STATE_UNKNOWN), error_(ERROR_UNKNOWN), + connectable_(true), is_active_(false) {} explicit Network(const Network& network); explicit Network(const ServiceInfo* service); @@ -78,6 +84,7 @@ class Network { ConnectionType type_; ConnectionState state_; ConnectionError error_; + bool connectable_; bool is_active_; private: @@ -88,8 +95,12 @@ class Network { void set_connected(bool connected) { state_ = (connected ? STATE_READY : STATE_IDLE); } void set_state(ConnectionState state) { state_ = state; } + void set_connectable(bool connectable) { connectable_ = connectable; } void set_active(bool is_active) { is_active_ = is_active; } + // Initialize the IP address field + void InitIPAddress(); + friend class NetworkLibraryImpl; }; @@ -131,7 +142,9 @@ class WirelessNetwork : public Network { bool favorite() const { return favorite_; } void set_auto_connect(bool auto_connect) { auto_connect_ = auto_connect; } - void set_favorite(bool favorite) { favorite_ = favorite; } + // We don't have a setter for |favorite_| because to unfavorite a network is + // equivalent to forget a network, so we call forget network on cros for + // that. See ForgetWifiNetwork(). // Network overrides. virtual void Clear(); @@ -151,6 +164,9 @@ class WirelessNetwork : public Network { bool favorite_; private: + // ChangeAutoConnectSaveTest accesses |favorite_|. + FRIEND_TEST_ALL_PREFIXES(WifiConfigViewTest, ChangeAutoConnectSaveTest); + void set_name(const std::string& name) { name_ = name; } void set_strength(int strength) { strength_ = strength; } @@ -172,7 +188,19 @@ class CellularDataPlan { plan_end_time(base::Time::FromInternalValue(plan.plan_end_time)), plan_data_bytes(plan.plan_data_bytes), data_bytes_used(plan.data_bytes_used) { } - + // Formats cellular plan description. + string16 GetPlanDesciption() const; + // Evaluates cellular plans status and returns warning string if it is near + // expiration. + string16 GetRemainingWarning() const; + // Formats remaining plan data description. + string16 GetDataRemainingDesciption() const; + // Formats plan expiration description. + string16 GetPlanExpiration() const; + // Formats plan usage info. + string16 GetUsageInfo() const; + int64 remaining_minutes() const; + int64 remaining_mbytes() const; std::string plan_name; CellularDataPlanType plan_type; base::Time update_time; @@ -206,6 +234,10 @@ class CellularNetwork : public WirelessNetwork { } const NetworkRoamingState roaming_state() const { return roaming_state_; } bool restricted_pool() const { return restricted_pool_; } + bool needs_new_plan() const { + return restricted_pool() && connected() && + activation_state() == ACTIVATION_STATE_ACTIVATED; + } const std::string& service_name() const { return service_name_; } const std::string& operator_name() const { return operator_name_; } const std::string& operator_code() const { return operator_code_; } diff --git a/chrome/browser/chromeos/cros_settings.cc b/chrome/browser/chromeos/cros_settings.cc index a0e1297..0c86226 100644 --- a/chrome/browser/chromeos/cros_settings.cc +++ b/chrome/browser/chromeos/cros_settings.cc @@ -8,7 +8,7 @@ #include "base/string_util.h" #include "base/values.h" #include "chrome/browser/chromeos/cros_settings_provider.h" -#include "chrome/browser/chromeos/cros_settings_provider_user.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/common/notification_service.h" namespace chromeos { @@ -39,6 +39,15 @@ void CrosSettings::FireObservers(const char* path) { } } +void CrosSettings::Set(const std::string& path, Value* in_value) { + DCHECK(CalledOnValidThread()); + CrosSettingsProvider* provider; + provider = GetProvider(path); + if (provider) { + provider->Set(path, in_value); + } +} + void CrosSettings::SetBoolean(const std::string& path, bool in_value) { DCHECK(CalledOnValidThread()); Set(path, Value::CreateBooleanValue(in_value)); @@ -60,16 +69,6 @@ void CrosSettings::SetString(const std::string& path, Set(path, Value::CreateStringValue(in_value)); } -bool CrosSettings::GetBoolean(const std::string& path, - bool* bool_value) const { - DCHECK(CalledOnValidThread()); - Value* value; - if (!Get(path, &value)) - return false; - - return value->GetAsBoolean(bool_value); -} - bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) { DCHECK(CalledOnValidThread()); providers_.push_back(provider); @@ -147,15 +146,6 @@ CrosSettingsProvider* CrosSettings::GetProvider( 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; @@ -166,6 +156,16 @@ bool CrosSettings::Get(const std::string& path, Value** out_value) const { return false; } +bool CrosSettings::GetBoolean(const std::string& path, + bool* bool_value) const { + DCHECK(CalledOnValidThread()); + Value* value; + if (!Get(path, &value)) + return false; + + return value->GetAsBoolean(bool_value); +} + bool CrosSettings::GetInteger(const std::string& path, int* out_value) const { DCHECK(CalledOnValidThread()); @@ -200,7 +200,7 @@ CrosSettings::CrosSettings() { } CrosSettings::~CrosSettings() { - DCHECK(!providers_.size()); + DCHECK(providers_.empty()); } } // namespace chromeos diff --git a/chrome/browser/chromeos/cros_settings_provider_proxy.cc b/chrome/browser/chromeos/cros_settings_provider_proxy.cc deleted file mode 100644 index 5f113ee..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_proxy.cc +++ /dev/null @@ -1,328 +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/cros_settings_provider_proxy.h" - -#include "base/string_util.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/profile_manager.h" - -namespace chromeos { - -static const char kProxyPacUrl[] = "cros.proxy.pacurl"; -static const char kProxySingleHttp[] = "cros.proxy.singlehttp"; -static const char kProxySingleHttpPort[] = "cros.proxy.singlehttpport"; -static const char kProxyHttpUrl[] = "cros.proxy.httpurl"; -static const char kProxyHttpPort[] = "cros.proxy.httpport"; -static const char kProxyHttpsUrl[] = "cros.proxy.httpsurl"; -static const char kProxyHttpsPort[] = "cros.proxy.httpsport"; -static const char kProxyType[] = "cros.proxy.type"; -static const char kProxySingle[] = "cros.proxy.single"; -static const char kProxyFtpUrl[] = "cros.proxy.ftpurl"; -static const char kProxyFtpPort[] = "cros.proxy.ftpport"; -static const char kProxySocks[] = "cros.proxy.socks"; -static const char kProxySocksPort[] = "cros.proxy.socksport"; -static const char kProxyIgnoreList[] = "cros.proxy.ignorelist"; - -//------------------ CrosSettingsProviderProxy: public methods ----------------- - -CrosSettingsProviderProxy::CrosSettingsProviderProxy() { } - -void CrosSettingsProviderProxy::DoSet(const std::string& path, - Value* in_value) { - if (!in_value) { - return; - } - - // Keep whatever user inputs so that we could use it later. - SetCache(path, in_value); - - chromeos::ProxyConfigServiceImpl* config_service = GetConfigService(); - chromeos::ProxyConfigServiceImpl::ProxyConfig config; - config_service->UIGetProxyConfig(&config); - - if (path == kProxyPacUrl) { - std::string val; - if (in_value->GetAsString(&val)) { - GURL url(val); - config_service->UISetProxyConfigToPACScript(url); - } - } else if (path == kProxySingleHttp) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri = val; - AppendPortIfValid(kProxySingleHttpPort, &uri); - config_service->UISetProxyConfigToSingleProxy( - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxySingleHttpPort) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri; - FormServerUriIfValid(kProxySingleHttp, val, &uri); - config_service->UISetProxyConfigToSingleProxy( - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxyHttpUrl) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri = val; - AppendPortIfValid(kProxyHttpPort, &uri); - config_service->UISetProxyConfigToProxyPerScheme("http", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxyHttpPort) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri; - FormServerUriIfValid(kProxyHttpUrl, val, &uri); - config_service->UISetProxyConfigToProxyPerScheme("http", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxyHttpsUrl) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri = val; - AppendPortIfValid(kProxyHttpsPort, &uri); - config_service->UISetProxyConfigToProxyPerScheme("https", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTPS)); - } - } else if (path == kProxyHttpsPort) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri; - FormServerUriIfValid(kProxyHttpsUrl, val, &uri); - config_service->UISetProxyConfigToProxyPerScheme("https", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTPS)); - } - } else if (path == kProxyType) { - int val; - if (in_value->GetAsInteger(&val)) { - if (val == 3) { - if (config.automatic_proxy.pac_url.is_valid()) - config_service->UISetProxyConfigToPACScript( - config.automatic_proxy.pac_url); - else - config_service->UISetProxyConfigToAutoDetect(); - } else if (val == 2) { - if (config.single_proxy.server.is_valid()) { - config_service->UISetProxyConfigToSingleProxy( - config.single_proxy.server); - } else { - bool set_config = false; - if (config.http_proxy.server.is_valid()) { - config_service->UISetProxyConfigToProxyPerScheme("http", - config.http_proxy.server); - set_config = true; - } - if (config.https_proxy.server.is_valid()) { - config_service->UISetProxyConfigToProxyPerScheme("https", - config.https_proxy.server); - set_config = true; - } - if (config.ftp_proxy.server.is_valid()) { - config_service->UISetProxyConfigToProxyPerScheme("ftp", - config.ftp_proxy.server); - set_config = true; - } - if (config.socks_proxy.server.is_valid()) { - config_service->UISetProxyConfigToProxyPerScheme("socks", - config.socks_proxy.server); - set_config = true; - } - if (!set_config) { - config_service->UISetProxyConfigToProxyPerScheme("http", - net::ProxyServer()); - } - } - } else { - config_service->UISetProxyConfigToDirect(); - } - } - } else if (path == kProxySingle) { - bool val; - if (in_value->GetAsBoolean(&val)) { - if (val) - config_service->UISetProxyConfigToSingleProxy( - config.single_proxy.server); - else - config_service->UISetProxyConfigToProxyPerScheme("http", - config.http_proxy.server); - } - } else if (path == kProxyFtpUrl) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri = val; - AppendPortIfValid(kProxyFtpPort, &uri); - config_service->UISetProxyConfigToProxyPerScheme("ftp", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxyFtpPort) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri; - FormServerUriIfValid(kProxyFtpUrl, val, &uri); - config_service->UISetProxyConfigToProxyPerScheme("ftp", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); - } - } else if (path == kProxySocks) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri = val; - AppendPortIfValid(kProxySocksPort, &uri); - config_service->UISetProxyConfigToProxyPerScheme("socks", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_SOCKS4)); - } - } else if (path == kProxySocksPort) { - std::string val; - if (in_value->GetAsString(&val)) { - std::string uri; - FormServerUriIfValid(kProxySocks, val, &uri); - config_service->UISetProxyConfigToProxyPerScheme("socks", - net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_SOCKS4)); - } - } else if (path == kProxyIgnoreList) { - net::ProxyBypassRules bypass_rules; - if (in_value->GetType() == Value::TYPE_LIST) { - const ListValue* list_value = static_cast(in_value); - for (size_t x = 0; x < list_value->GetSize(); x++) { - std::string val; - if (list_value->GetString(x, &val)) { - bypass_rules.AddRuleFromString(val); - } - } - config_service->UISetProxyConfigBypassRules(bypass_rules); - } - } -} - -bool CrosSettingsProviderProxy::Get(const std::string& path, - Value** out_value) const { - bool found = false; - bool managed = false; - Value* data; - chromeos::ProxyConfigServiceImpl* config_service = GetConfigService(); - chromeos::ProxyConfigServiceImpl::ProxyConfig config; - config_service->UIGetProxyConfig(&config); - - if (path == kProxyPacUrl) { - if (config.automatic_proxy.pac_url.is_valid()) { - data = Value::CreateStringValue(config.automatic_proxy.pac_url.spec()); - found = true; - } - } else if (path == kProxySingleHttp) { - found = (data = CreateServerHostValue(config.single_proxy)); - } else if (path == kProxySingleHttpPort) { - found = (data = CreateServerPortValue(config.single_proxy)); - } else if (path == kProxyHttpUrl) { - found = (data = CreateServerHostValue(config.http_proxy)); - } else if (path == kProxyHttpsUrl) { - found = (data = CreateServerHostValue(config.https_proxy)); - } else if (path == kProxyType) { - if (config.mode == - chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT || - config.mode == - chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT) { - data = Value::CreateIntegerValue(3); - } else if (config.mode == - chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY || - config.mode == - chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) { - data = Value::CreateIntegerValue(2); - } else { - data = Value::CreateIntegerValue(1); - } - found = true; - } else if (path == kProxySingle) { - data = Value::CreateBooleanValue(config.mode == - chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY); - found = true; - } else if (path == kProxyFtpUrl) { - found = (data = CreateServerHostValue(config.ftp_proxy)); - } else if (path == kProxySocks) { - found = (data = CreateServerHostValue(config.socks_proxy)); - } else if (path == kProxyHttpPort) { - found = (data = CreateServerPortValue(config.http_proxy)); - } else if (path == kProxyHttpsPort) { - found = (data = CreateServerPortValue(config.https_proxy)); - } else if (path == kProxyFtpPort) { - found = (data = CreateServerPortValue(config.ftp_proxy)); - } else if (path == kProxySocksPort) { - found = (data = CreateServerPortValue(config.socks_proxy)); - } else if (path == kProxyIgnoreList) { - ListValue* list = new ListValue(); - net::ProxyBypassRules::RuleList bypass_rules = config.bypass_rules.rules(); - for (size_t x = 0; x < bypass_rules.size(); x++) { - list->Append(Value::CreateStringValue(bypass_rules[x]->ToString())); - } - *out_value = list; - return true; - } - if (found) { - DictionaryValue* dict = new DictionaryValue; - dict->Set("value", data); - dict->SetBoolean("managed", managed); - *out_value = dict; - return true; - } else { - *out_value = NULL; - return false; - } -} - -bool CrosSettingsProviderProxy::HandlesSetting(const std::string& path) { - return ::StartsWithASCII(path, "cros.proxy", true); -} - -//----------------- CrosSettingsProviderProxy: private methods ----------------- - -chromeos::ProxyConfigServiceImpl* - CrosSettingsProviderProxy::GetConfigService() const { - Browser* browser = BrowserList::GetLastActive(); - // browser is NULL at OOBE/login stage. - Profile* profile = browser ? - browser->profile() : - ProfileManager::GetDefaultProfile(); - return profile->GetChromeOSProxyConfigServiceImpl(); -} - -void CrosSettingsProviderProxy::AppendPortIfValid( - const char* port_cache_key, - std::string* server_uri) { - std::string port; - if (!server_uri->empty() && cache_.GetString(port_cache_key, &port) && - !port.empty()) { - *server_uri += ":" + port; - } -} - -void CrosSettingsProviderProxy::FormServerUriIfValid( - const char* host_cache_key, - const std::string& port_num, std::string* server_uri) { - if (cache_.GetString(host_cache_key, server_uri) && !server_uri->empty() && - !port_num.empty()) - *server_uri += ":" + port_num; -} - -Value* CrosSettingsProviderProxy::CreateServerHostValue( - const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const { - return proxy.server.is_valid() ? - Value::CreateStringValue(proxy.server.host_port_pair().host()) : - NULL; -} - -Value* CrosSettingsProviderProxy::CreateServerPortValue( - const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const { - return proxy.server.is_valid() ? - Value::CreateIntegerValue(proxy.server.host_port_pair().port()) : - NULL; -} - -void CrosSettingsProviderProxy::SetCache(const std::string& key, - const Value* value) { - cache_.Set(key, value->DeepCopy()); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/cros_settings_provider_proxy.h b/chrome/browser/chromeos/cros_settings_provider_proxy.h deleted file mode 100644 index 1b1672b..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_proxy.h +++ /dev/null @@ -1,50 +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_SETTINGS_PROVIDER_PROXY_H_ -#define CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_PROXY_H_ -#pragma once - -#include "base/singleton.h" -#include "base/values.h" -#include "chrome/browser/chromeos/cros_settings_provider.h" -#include "chrome/browser/chromeos/proxy_config_service_impl.h" - -namespace chromeos { - -class CrosSettingsProviderProxy : public CrosSettingsProvider { - public: - CrosSettingsProviderProxy(); - // CrosSettingsProvider implementation. - virtual bool Get(const std::string& path, Value** out_value) const; - virtual bool HandlesSetting(const std::string& path); - - private: - // CrosSettingsProvider implementation. - virtual void DoSet(const std::string& path, Value* value); - - chromeos::ProxyConfigServiceImpl* GetConfigService() const; - - void AppendPortIfValid(const char* port_cache_key, std::string* server_uri); - - void FormServerUriIfValid(const char* host_cache_key, - const std::string& port_num, std::string* server_uri); - - Value* CreateServerHostValue( - const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const; - - Value* CreateServerPortValue( - const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const; - - void SetCache(const std::string& key, const Value* value); - - // A cache to keep whatever user typed. - DictionaryValue cache_; - - DISALLOW_COPY_AND_ASSIGN(CrosSettingsProviderProxy); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_PROXY_H_ diff --git a/chrome/browser/chromeos/cros_settings_provider_stats.cc b/chrome/browser/chromeos/cros_settings_provider_stats.cc deleted file mode 100644 index 6a78f61..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_stats.cc +++ /dev/null @@ -1,66 +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/cros_settings_provider_stats.h" - -#include "base/string_util.h" -#include "base/values.h" -#include "chrome/browser/chromeos/cros_settings.h" -#include "chrome/browser/chromeos/cros_settings_names.h" -#include "chrome/browser/options_util.h" -#include "chrome/installer/util/google_update_settings.h" - -#if defined(USE_LINUX_BREAKPAD) -#include "chrome/app/breakpad_linux.h" -#endif - -namespace chromeos { - -void MetricsCrosSettingsProvider::DoSet(const std::string& path, - Value* value) { - DCHECK(path == kStatsReportingPref); - bool enabled = false; - CHECK(value->GetAsBoolean(&enabled)); - if (SetMetricsStatus(enabled)) { - CrosSettings::Get()->FireObservers(path.c_str()); - } -} - -bool MetricsCrosSettingsProvider::Get(const std::string& path, - Value** value) const { - DCHECK(path == kStatsReportingPref); - *value = Value::CreateBooleanValue(GetMetricsStatus()); - return true; -} - -// static -bool MetricsCrosSettingsProvider::SetMetricsStatus(bool enabled) { - VLOG(1) << "Setting cros stats/crash metric reporting to " << enabled; - if (enabled != GoogleUpdateSettings::GetCollectStatsConsent()) { - bool new_enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled); -#if defined(USE_LINUX_BREAKPAD) - if (new_enabled) - InitCrashReporter(); - // Else, if (!new_enabled), we should have turned crash reporting off - // here, but there is no API for that currently (while we use - // BreakPad). But this is not a big deal: crash reporting will be off - // after reboot for the current process while other Chrome processes - // will start when the setting is already set up. Other ChromeOS - // processes does not use BreakPad. -#endif - return new_enabled == enabled; - } - return false; -} - -// static -bool MetricsCrosSettingsProvider::GetMetricsStatus() { - return GoogleUpdateSettings::GetCollectStatsConsent(); -} - -bool MetricsCrosSettingsProvider::HandlesSetting(const std::string& path) { - return ::StartsWithASCII(path, kStatsReportingPref, true); -} - -}; // namespace chromeos diff --git a/chrome/browser/chromeos/cros_settings_provider_stats.h b/chrome/browser/chromeos/cros_settings_provider_stats.h deleted file mode 100644 index ff30f25..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_stats.h +++ /dev/null @@ -1,41 +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_SETTINGS_PROVIDER_STATS_H_ -#define CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_STATS_H_ -#pragma once - -#include - -#include "base/basictypes.h" -#include "chrome/browser/chromeos/cros_settings_provider.h" - -namespace chromeos { - -// CrosSettingsProvider that abstracts switching of stats/crash -// reporting to Google. -class MetricsCrosSettingsProvider : public CrosSettingsProvider { - public: - MetricsCrosSettingsProvider() {} - - // CrosSettingsProvider implementation. - virtual bool Get(const std::string& path, Value** value) const; - virtual bool HandlesSetting(const std::string& path); - - // Actual methods to control stats/crash reporting. Currently these - // methods are public and static so they are accessible directly - // from cros code. But this will change soon: crosbug.com/7359 - static bool SetMetricsStatus(bool enabled); - static bool GetMetricsStatus(); - - private: - // CrosSettingsProvider implementation. - virtual void DoSet(const std::string& path, Value* value); - - DISALLOW_COPY_AND_ASSIGN(MetricsCrosSettingsProvider); -}; - -}; // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_STATS_H_ diff --git a/chrome/browser/chromeos/cros_settings_provider_user.cc b/chrome/browser/chromeos/cros_settings_provider_user.cc deleted file mode 100644 index 7b9c0c3..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_user.cc +++ /dev/null @@ -1,298 +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/cros_settings_provider_user.h" - -#include "base/logging.h" -#include "base/string_util.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/cros/cros_library.h" -#include "chrome/browser/chromeos/cros/login_library.h" -#include "chrome/browser/chromeos/cros_settings.h" -#include "chrome/browser/chromeos/cros_settings_names.h" -#include "chrome/browser/chromeos/login/user_manager.h" -#include "chrome/browser/prefs/pref_service.h" - -namespace chromeos { - -namespace { - -Value* CreateSettingsBooleanValue(bool value, bool managed) { - DictionaryValue* dict = new DictionaryValue; - dict->Set("value", Value::CreateBooleanValue(value)); - dict->Set("managed", Value::CreateBooleanValue(managed)); - return dict; -} - -// static -void UpdateCacheBool(const char* name, bool value) { - PrefService* prefs = g_browser_process->local_state(); - prefs->SetBoolean(name, value); - prefs->ScheduleSavePersistentPrefs(); -} - -void UpdateCacheString(const char* name, const std::string& value) { - PrefService* prefs = g_browser_process->local_state(); - prefs->SetString(name, value); - prefs->ScheduleSavePersistentPrefs(); -} - -bool GetUserWhitelist(ListValue* user_list) { - std::vector whitelist; - if (!CrosLibrary::Get()->EnsureLoaded() || - !CrosLibrary::Get()->GetLoginLibrary()->EnumerateWhitelisted( - &whitelist)) { - LOG(WARNING) << "Failed to retrieve user whitelist."; - return false; - } - - PrefService* prefs = g_browser_process->local_state(); - ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); - cached_whitelist->Clear(); - - const UserManager::User& self = UserManager::Get()->logged_in_user(); - bool is_owner = UserManager::Get()->current_user_is_owner(); - - for (size_t i = 0; i < whitelist.size(); ++i) { - const std::string& email = whitelist[i]; - - if (user_list) { - DictionaryValue* user = new DictionaryValue; - user->SetString("email", email); - user->SetString("name", ""); - user->SetBoolean("owner", is_owner && email == self.email()); - user_list->Append(user); - } - - cached_whitelist->Append(Value::CreateStringValue(email)); - } - - prefs->ScheduleSavePersistentPrefs(); - - return true; -} - -} // namespace - -UserCrosSettingsProvider::UserCrosSettingsProvider() { - StartFetchingBoolSetting(kAccountsPrefAllowGuest); - StartFetchingBoolSetting(kAccountsPrefAllowNewUser); - StartFetchingBoolSetting(kAccountsPrefShowUserNamesOnSignIn); - StartFetchingStringSetting(kDeviceOwner); -} - -UserCrosSettingsProvider::~UserCrosSettingsProvider() { - // Cancels all pending callbacks from us. - SignedSettingsHelper::Get()->CancelCallback(this); -} - -// static -void UserCrosSettingsProvider::RegisterPrefs(PrefService* local_state) { - // Cached signed settings values - local_state->RegisterBooleanPref(kAccountsPrefAllowGuest, true); - local_state->RegisterBooleanPref(kAccountsPrefAllowNewUser, true); - local_state->RegisterBooleanPref(kAccountsPrefShowUserNamesOnSignIn, true); - local_state->RegisterListPref(kAccountsPrefUsers); - local_state->RegisterStringPref(kDeviceOwner, ""); -} - -// static -bool UserCrosSettingsProvider::cached_allow_guest() { - return g_browser_process->local_state()->GetBoolean(kAccountsPrefAllowGuest); -} - -// static -bool UserCrosSettingsProvider::cached_allow_new_user() { - return g_browser_process->local_state()->GetBoolean( - kAccountsPrefAllowNewUser); -} - -// static -bool UserCrosSettingsProvider::cached_show_users_on_signin() { - return g_browser_process->local_state()->GetBoolean( - kAccountsPrefShowUserNamesOnSignIn); -} - -// static -const ListValue* UserCrosSettingsProvider::cached_whitelist() { - PrefService* prefs = g_browser_process->local_state(); - const ListValue* cached_users = prefs->GetList(kAccountsPrefUsers); - - if (!cached_users) { - // Update whitelist cache. - GetUserWhitelist(NULL); - - cached_users = prefs->GetList(kAccountsPrefUsers); - } - - return cached_users; -} - -// static -std::string UserCrosSettingsProvider::cached_owner() { - return g_browser_process->local_state()->GetString(kDeviceOwner); -} - -// static -bool UserCrosSettingsProvider::IsEmailInCachedWhitelist( - const std::string& email) { - const ListValue* whitelist = cached_whitelist(); - if (whitelist) { - StringValue email_value(email); - for (ListValue::const_iterator i(whitelist->begin()); - i != whitelist->end(); ++i) { - if ((*i)->Equals(&email_value)) - return true; - } - } - return false; -} - -void UserCrosSettingsProvider::DoSet(const std::string& path, - Value* in_value) { - if (!UserManager::Get()->current_user_is_owner()) { - LOG(WARNING) << "Changing settings from non-owner, setting=" << path; - - // Revert UI change. - CrosSettings::Get()->FireObservers(path.c_str()); - return; - } - - if (path == kAccountsPrefAllowGuest || - path == kAccountsPrefAllowNewUser || - path == kAccountsPrefShowUserNamesOnSignIn) { - bool bool_value = false; - if (in_value->GetAsBoolean(&bool_value)) { - std::string value = bool_value ? "true" : "false"; - SignedSettingsHelper::Get()->StartStorePropertyOp(path, value, this); - UpdateCacheBool(path.c_str(), bool_value); - - VLOG(1) << "Set cros setting " << path << "=" << value; - } - } else if (path == kDeviceOwner) { - VLOG(1) << "Setting owner is not supported. Please use 'UpdateCachedOwner' " - "instead."; - } else if (path == kAccountsPrefUsers) { - VLOG(1) << "Setting user whitelist is not implemented. Please use " - "whitelist/unwhitelist instead."; - } else { - LOG(WARNING) << "Try to set unhandled cros setting " << path; - } -} - -bool UserCrosSettingsProvider::Get(const std::string& path, - Value** out_value) const { - if (path == kAccountsPrefAllowGuest || - path == kAccountsPrefAllowNewUser || - path == kAccountsPrefShowUserNamesOnSignIn) { - *out_value = CreateSettingsBooleanValue( - g_browser_process->local_state()->GetBoolean(path.c_str()), - !UserManager::Get()->current_user_is_owner()); - return true; - } else if (path == kAccountsPrefUsers) { - ListValue* user_list = new ListValue; - GetUserWhitelist(user_list); - *out_value = user_list; - return true; - } - - return false; -} - -bool UserCrosSettingsProvider::HandlesSetting(const std::string& path) { - return ::StartsWithASCII(path, "cros.accounts.", true); -} - -void UserCrosSettingsProvider::OnWhitelistCompleted(bool success, - const std::string& email) { - VLOG(1) << "Add " << email << " to whitelist, success=" << success; - - // Reload the whitelist on settings op failure. - if (!success) - CrosSettings::Get()->FireObservers(kAccountsPrefUsers); -} - -void UserCrosSettingsProvider::OnUnwhitelistCompleted(bool success, - const std::string& email) { - VLOG(1) << "Remove " << email << " from whitelist, success=" << success; - - // Reload the whitelist on settings op failure. - if (!success) - CrosSettings::Get()->FireObservers(kAccountsPrefUsers); -} - -void UserCrosSettingsProvider::OnStorePropertyCompleted( - bool success, const std::string& name, const std::string& value) { - VLOG(1) << "Store cros setting " << name << "=" << value << ", success=" - << success; - - // Reload the setting if store op fails. - if (!success) - SignedSettingsHelper::Get()->StartRetrieveProperty(name, this); -} - -void UserCrosSettingsProvider::OnRetrievePropertyCompleted( - bool success, const std::string& name, const std::string& value) { - if (!success) { - LOG(WARNING) << "Failed to retrieve cros setting, name=" << name; - return; - } - - VLOG(1) << "Retrieved cros setting " << name << "=" << value; - - if (bool_settings_.count(name)) { - UpdateCacheBool(name.c_str(), value == "true" ? true : false); - } - - if (string_settings_.count(name)) { - UpdateCacheString(name.c_str(), value); - } - - CrosSettings::Get()->FireObservers(name.c_str()); -} - -void UserCrosSettingsProvider::WhitelistUser(const std::string& email) { - SignedSettingsHelper::Get()->StartWhitelistOp(email, true, this); - - PrefService* prefs = g_browser_process->local_state(); - ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); - cached_whitelist->Append(Value::CreateStringValue(email)); - prefs->ScheduleSavePersistentPrefs(); -} - -void UserCrosSettingsProvider::UnwhitelistUser(const std::string& email) { - SignedSettingsHelper::Get()->StartWhitelistOp(email, false, this); - - PrefService* prefs = g_browser_process->local_state(); - ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); - StringValue email_value(email); - if (cached_whitelist->Remove(email_value) != -1) - prefs->ScheduleSavePersistentPrefs(); -} - -// static -void UserCrosSettingsProvider::UpdateCachedOwner(const std::string& email) { - UpdateCacheString(kDeviceOwner, email); -} - -void UserCrosSettingsProvider::StartFetchingBoolSetting( - const std::string& name) { - bool_settings_.insert(name); - StartFetchingSetting(name); -} - -void UserCrosSettingsProvider::StartFetchingStringSetting( - const std::string& name) { - string_settings_.insert(name); - StartFetchingSetting(name); -} - -void UserCrosSettingsProvider::StartFetchingSetting( - const std::string& name) { - if (CrosLibrary::Get()->EnsureLoaded()) - SignedSettingsHelper::Get()->StartRetrieveProperty(name, this); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/cros_settings_provider_user.h b/chrome/browser/chromeos/cros_settings_provider_user.h deleted file mode 100644 index 3fafa41..0000000 --- a/chrome/browser/chromeos/cros_settings_provider_user.h +++ /dev/null @@ -1,76 +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_SETTINGS_PROVIDER_USER_H_ -#define CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_USER_H_ -#pragma once - -#include - -#include "base/basictypes.h" -#include "base/hash_tables.h" -#include "chrome/browser/chromeos/cros_settings_provider.h" -#include "chrome/browser/chromeos/login/signed_settings_helper.h" - -class ListValue; -class PrefService; - -namespace chromeos { - -class UserCrosSettingsProvider : public CrosSettingsProvider, - public SignedSettingsHelper::Callback { - public: - UserCrosSettingsProvider(); - virtual ~UserCrosSettingsProvider(); - - // Registers cached users settings in preferences. - static void RegisterPrefs(PrefService* local_state); - - // Helper functions to access cached settings. - static bool cached_allow_guest(); - static bool cached_allow_new_user(); - static bool cached_show_users_on_signin(); - static const ListValue* cached_whitelist(); - static std::string cached_owner(); - - // 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. - static bool IsEmailInCachedWhitelist(const std::string& email); - - // CrosSettingsProvider implementation. - virtual bool Get(const std::string& path, Value** out_value) const; - virtual bool HandlesSetting(const std::string& path); - - // SignedSettingsHelper::Callback overrides. - virtual void OnWhitelistCompleted(bool success, const std::string& email); - virtual void OnUnwhitelistCompleted(bool success, const std::string& email); - virtual void OnStorePropertyCompleted( - bool success, const std::string& name, const std::string& value); - virtual void OnRetrievePropertyCompleted( - bool success, const std::string& name, const std::string& value); - - void WhitelistUser(const std::string& email); - void UnwhitelistUser(const std::string& email); - - // Updates cached value of the owner. - static void UpdateCachedOwner(const std::string& email); - - private: - // CrosSettingsProvider implementation. - virtual void DoSet(const std::string& path, Value* value); - - void StartFetchingBoolSetting(const std::string& name); - void StartFetchingStringSetting(const std::string& name); - void StartFetchingSetting(const std::string& name); - - base::hash_set bool_settings_; - base::hash_set string_settings_; - - DISALLOW_COPY_AND_ASSIGN(UserCrosSettingsProvider); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_CROS_SETTINGS_PROVIDER_USER_H_ diff --git a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc index 93361c6..e461989 100644 --- a/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc +++ b/chrome/browser/chromeos/dom_ui/accounts_options_handler.cc @@ -9,8 +9,8 @@ #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 "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/dom_ui/dom_ui_util.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/chromeos/dom_ui/internet_options_handler.cc b/chrome/browser/chromeos/dom_ui/internet_options_handler.cc index fa0245f..4b32ffd 100644 --- a/chrome/browser/chromeos/dom_ui/internet_options_handler.cc +++ b/chrome/browser/chromeos/dom_ui/internet_options_handler.cc @@ -20,7 +20,6 @@ #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/cros/cros_library.h" @@ -29,6 +28,7 @@ #include "chrome/browser/dom_ui/dom_ui_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "chrome/common/time_format.h" #include "grit/browser_resources.h" @@ -158,7 +158,7 @@ void InternetOptionsHandler::GetLocalizedValues( localized_strings->SetString("inetPassProtected", l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NET_PROTECTED)); - localized_strings->SetString("inetRememberNetwork", + localized_strings->SetString("inetAutoConnectNetwork", l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT)); localized_strings->SetString("inetCertPkcs", @@ -449,97 +449,21 @@ DictionaryValue* InternetOptionsHandler::CellularDataPlanToDictionary( DictionaryValue* plan_dict = new DictionaryValue(); plan_dict->SetInteger("plan_type", plan.plan_type); - // Format plan details into readable text. - string16 description; - string16 remaining; - switch (plan.plan_type) { - case chromeos::CELLULAR_DATA_PLAN_UNKNOWN: { - return NULL; - break; - } - case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: { - description = l10n_util::GetStringFUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_UNLIMITED_DATA, - WideToUTF16(base::TimeFormatFriendlyDate(plan.plan_start_time))); - - remaining = l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_UNLIMITED); - break; - } - case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: { - description = l10n_util::GetStringFUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_DATA, - FormatBytes(plan.plan_data_bytes, - GetByteDisplayUnits(plan.plan_data_bytes), - true), - WideToUTF16(base::TimeFormatFriendlyDate( - plan.plan_start_time))); - remaining = FormatBytes(plan.plan_data_bytes - plan.data_bytes_used, - GetByteDisplayUnits(plan.plan_data_bytes - plan.data_bytes_used), - true); - break; - } - case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: { - description = l10n_util::GetStringFUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_RECEIVED_FREE_DATA, - FormatBytes(plan.plan_data_bytes, - GetByteDisplayUnits(plan.plan_data_bytes), - true), - WideToUTF16(base::TimeFormatFriendlyDate( - plan.plan_start_time))); - remaining = FormatBytes(plan.plan_data_bytes - plan.data_bytes_used, - GetByteDisplayUnits(plan.plan_data_bytes - plan.data_bytes_used), - true); - break; - } - } - string16 expiration = TimeFormat::TimeRemaining( - plan.plan_end_time - base::Time::Now()); plan_dict->SetString("name", plan.plan_name); - plan_dict->SetString("planSummary", description); - plan_dict->SetString("dataRemaining", remaining); - plan_dict->SetString("planExpires", expiration); - plan_dict->SetString("warning", GetPlanWarning(plan)); + plan_dict->SetString("planSummary", plan.GetPlanDesciption()); + plan_dict->SetString("dataRemaining", plan.GetDataRemainingDesciption()); + plan_dict->SetString("planExpires", plan.GetPlanExpiration()); + plan_dict->SetString("warning", plan.GetRemainingWarning()); return plan_dict; } -string16 InternetOptionsHandler::GetPlanWarning( - const chromeos::CellularDataPlan& plan) { - if (plan.plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) { - // Time based plan. Show nearing expiration and data expiration. - int64 time_left = base::TimeDelta( - plan.plan_end_time - plan.update_time).InSeconds(); - if (time_left <= 0) { - return l10n_util::GetStringFUTF16( - IDS_NETWORK_MINUTES_REMAINING_MESSAGE, ASCIIToUTF16("0")); - } else if (time_left <= chromeos::kCellularDataVeryLowSecs) { - return l10n_util::GetStringFUTF16( - IDS_NETWORK_MINUTES_UNTIL_EXPIRATION_MESSAGE, - UTF8ToUTF16(base::Int64ToString(time_left/60))); - } - } else if (plan.plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID || - plan.plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) { - // Metered plan. Show low data and out of data. - int64 bytes_remaining = plan.plan_data_bytes - plan.data_bytes_used; - if (bytes_remaining <= 0) { - return l10n_util::GetStringFUTF16( - IDS_NETWORK_DATA_REMAINING_MESSAGE, ASCIIToUTF16("0")); - } else if (bytes_remaining <= chromeos::kCellularDataVeryLowBytes) { - return l10n_util::GetStringFUTF16( - IDS_NETWORK_DATA_REMAINING_MESSAGE, - UTF8ToUTF16(base::Int64ToString(bytes_remaining/(1024*1024)))); - } - } - return string16(); -} - void InternetOptionsHandler::SetDetailsCallback(const ListValue* args) { std::string service_path; - std::string remember; + std::string auto_connect_str; if (args->GetSize() < 2 || !args->GetString(0, &service_path) || - !args->GetString(1, &remember)) { + !args->GetString(1, &auto_connect_str)) { NOTREACHED(); return; } @@ -559,10 +483,7 @@ void InternetOptionsHandler::SetDetailsCallback(const ListValue* args) { if (network->encrypted() && network->encryption() == chromeos::SECURITY_8021X) { std::string ident; - std::string certpath; - - if (!args->GetString(2, &ident) || - !args->GetString(3, &certpath)) { + if (!args->GetString(2, &ident)) { NOTREACHED(); return; } @@ -570,14 +491,21 @@ void InternetOptionsHandler::SetDetailsCallback(const ListValue* args) { network->set_identity(ident); changed = true; } - if (certpath != network->cert_path()) { - network->set_cert_path(certpath); - changed = true; + if (!is_certificate_in_pkcs11(network->cert_path())) { + std::string certpath; + if (!args->GetString(3, &certpath)) { + NOTREACHED(); + return; + } + if (certpath != network->cert_path()) { + network->set_cert_path(certpath); + changed = true; + } } } } - bool auto_connect = remember == "true"; + bool auto_connect = auto_connect_str == "true"; if (auto_connect != network->auto_connect()) { network->set_auto_connect(auto_connect); changed = true; @@ -880,13 +808,15 @@ void InternetOptionsHandler::RefreshCellularPlanCallback( ListValue* InternetOptionsHandler::GetNetwork(const std::string& service_path, const SkBitmap& icon, const std::string& name, bool connecting, - bool connected, chromeos::ConnectionType connection_type, bool remembered, - chromeos::ActivationState activation_state, bool restricted_ip) { - + bool connected, bool connectable, chromeos::ConnectionType connection_type, + bool remembered, chromeos::ActivationState activation_state, + bool restricted_ip) { ListValue* network = new ListValue(); int connection_state = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED; - if (connecting) + if (!connectable) + connection_state = IDS_STATUSBAR_NETWORK_DEVICE_NOT_CONFIGURED; + else if (connecting) connection_state = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING; else if (connected) connection_state = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED; @@ -923,6 +853,8 @@ ListValue* InternetOptionsHandler::GetNetwork(const std::string& service_path, static_cast(activation_state))); // restricted network->Append(Value::CreateBooleanValue(restricted_ip)); + // connectable + network->Append(Value::CreateBooleanValue(connectable)); return network; } @@ -949,6 +881,7 @@ ListValue* InternetOptionsHandler::GetWiredList() { l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET), ethernet_network->connecting(), ethernet_network->connected(), + ethernet_network->connectable(), chromeos::TYPE_ETHERNET, false, chromeos::ACTIVATION_STATE_UNKNOWN, @@ -979,6 +912,7 @@ ListValue* InternetOptionsHandler::GetWirelessList() { (*it)->name(), (*it)->connecting(), (*it)->connected(), + (*it)->connectable(), chromeos::TYPE_WIFI, false, chromeos::ACTIVATION_STATE_UNKNOWN, @@ -999,6 +933,7 @@ ListValue* InternetOptionsHandler::GetWirelessList() { (*it)->name(), (*it)->connecting(), (*it)->connected(), + (*it)->connectable(), chromeos::TYPE_CELLULAR, false, (*it)->activation_state(), @@ -1013,6 +948,7 @@ ListValue* InternetOptionsHandler::GetWirelessList() { l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS), false, false, + true, chromeos::TYPE_WIFI, false, chromeos::ACTIVATION_STATE_UNKNOWN, @@ -1043,6 +979,7 @@ ListValue* InternetOptionsHandler::GetRememberedList() { (*it)->name(), (*it)->connecting(), (*it)->connected(), + true, chromeos::TYPE_WIFI, true, chromeos::ACTIVATION_STATE_UNKNOWN, diff --git a/chrome/browser/chromeos/dom_ui/internet_options_handler.h b/chrome/browser/chromeos/dom_ui/internet_options_handler.h index bce82ad..5456391 100644 --- a/chrome/browser/chromeos/dom_ui/internet_options_handler.h +++ b/chrome/browser/chromeos/dom_ui/internet_options_handler.h @@ -70,15 +70,12 @@ class InternetOptionsHandler // plan settings into human readable texts. DictionaryValue* CellularDataPlanToDictionary( const chromeos::CellularDataPlan& plan); - // Evaluates cellular plans status and returns warning string if it is near - // expiration. - string16 GetPlanWarning( - const chromeos::CellularDataPlan& plan); // Creates the map of a network ListValue* GetNetwork(const std::string& service_path, const SkBitmap& icon, const std::string& name, bool connecting, bool connected, - chromeos::ConnectionType connection_type, bool remembered, - chromeos::ActivationState activation_state, bool restricted_ip); + bool connectable, chromeos::ConnectionType connection_type, + bool remembered, chromeos::ActivationState activation_state, + bool restricted_ip); // Creates the map of wired networks ListValue* GetWiredList(); diff --git a/chrome/browser/chromeos/dom_ui/labs_handler.cc b/chrome/browser/chromeos/dom_ui/labs_handler.cc deleted file mode 100644 index da605aa..0000000 --- a/chrome/browser/chromeos/dom_ui/labs_handler.cc +++ /dev/null @@ -1,38 +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/labs_handler.h" - -#include "app/l10n_util.h" -#include "base/values.h" -#include "grit/generated_resources.h" - -LabsHandler::LabsHandler() { -} - -LabsHandler::~LabsHandler() { -} - -void LabsHandler::GetLocalizedValues( - DictionaryValue* localized_strings) { - DCHECK(localized_strings); - // Labs page - ChromeOS - 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("side_tabs_title", - l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SECTION_TITLE_SIDE_TABS)); - localized_strings->SetString("side_tabs", - l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_SIDE_TABS_DESCRIPTION)); -} diff --git a/chrome/browser/chromeos/dom_ui/labs_handler.h b/chrome/browser/chromeos/dom_ui/labs_handler.h deleted file mode 100644 index 015a347..0000000 --- a/chrome/browser/chromeos/dom_ui/labs_handler.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_DOM_UI_LABS_HANDLER_H_ -#define CHROME_BROWSER_CHROMEOS_DOM_UI_LABS_HANDLER_H_ -#pragma once - -#include "chrome/browser/dom_ui/options/options_ui.h" - -// ChromeOS labs options page UI handler. -class LabsHandler : public OptionsPageUIHandler { - public: - LabsHandler(); - virtual ~LabsHandler(); - - // OptionsUIHandler implementation. - virtual void GetLocalizedValues(DictionaryValue* localized_strings); - - private: - DISALLOW_COPY_AND_ASSIGN(LabsHandler); -}; - -#endif // CHROME_BROWSER_CHROMEOS_DOM_UI_LABS_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 05570bc..413eecc 100644 --- a/chrome/browser/chromeos/dom_ui/language_options_handler.cc +++ b/chrome/browser/chromeos/dom_ui/language_options_handler.cc @@ -10,17 +10,19 @@ #include #include "app/l10n_util.h" +#include "base/basictypes.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/app/chrome_command_ids.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/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "chrome/common/spellcheck_common.h" #include "grit/chromium_strings.h" @@ -57,7 +59,8 @@ void LanguageOptionsHandler::GetLocalizedValues( localized_strings->SetString("remove_button", l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_REMOVE_BUTTON)); localized_strings->SetString("sign_out_button", - l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON)); + l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_LANGUAGES_SIGN_OUT_BUTTON)); localized_strings->SetString("add_language_instructions", l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_INSTRUCTIONS)); @@ -287,9 +290,17 @@ void LanguageOptionsHandler::UiLanguageChangeCallback( "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(); + // We maintain kApplicationLocale property in both a global storage + // and user's profile. Global property determines locale of login screen, + // while user's profile determines his personal locale preference. + PrefService* prefs[] = { + g_browser_process->local_state(), + dom_ui_->GetProfile()->GetPrefs() + }; + for (size_t i = 0; i < arraysize(prefs); ++i) { + prefs[i]->SetString(prefs::kApplicationLocale, language_code); + prefs[i]->SavePersistentPrefs(); + } dom_ui_->CallJavascriptFunction( L"options.LanguageOptions.uiLanguageSaved"); } diff --git a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc index d021ab3..a409aa4 100644 --- a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc +++ b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc @@ -15,12 +15,12 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" +#include "base/metrics/histogram.h" #include "base/string_piece.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "base/weak_ptr.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" @@ -31,6 +31,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -44,7 +45,6 @@ namespace { // Host page JS API function names. const char kJsApiStartActivation[] = "startActivation"; -const char kJsApiCloseTab[] = "closeTab"; const char kJsApiSetTransactionStatus[] = "setTransactionStatus"; const wchar_t kJsDeviceStatusChangedHandler[] = @@ -69,6 +69,11 @@ const char kCellularConfigPath[] = const char kVersionField[] = "version"; const char kErrorsField[] = "errors"; +// Number of times we will retry to reconnect if connection fails. +const int kMaxConnectionRetry = 10; +// Connection timeout in seconds. +const int kConnectionTimeoutSeconds = 30; + chromeos::CellularNetwork* GetCellularNetwork() { chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()-> GetNetworkLibrary(); @@ -182,7 +187,6 @@ class MobileSetupHandler }; // Handlers for JS DOMUI messages. - void HandleCloseTab(const ListValue* args); void HandleSetTransactionStatus(const ListValue* args); void HandleStartActivation(const ListValue* args); void SetTransactionStatus(const std::string& status); @@ -191,11 +195,19 @@ class MobileSetupHandler // Sends message to host registration page with system/user info data. void SendDeviceInfo(); + // Connects to cellular network, resets connection timer. + void ConnectToNetwork(chromeos::CellularNetwork* network); + // Reports connection timeout. + bool ConnectionTimeout(); // Verify the state of cellular network and modify internal state. void EvaluateCellularNetwork(chromeos::CellularNetwork* network); // Check the current cellular network for error conditions. bool GotActivationError(const chromeos::CellularNetwork* network, std::string* error); + // Sends status updates to DOMUI page. + void UpdatePage(chromeos::CellularNetwork* network, + const std::string& error_description); + // Changes internal state. void ChangeState(chromeos::CellularNetwork* network, PlanActivationState new_state, const std::string& error_description); @@ -238,6 +250,12 @@ class MobileSetupHandler bool reenable_ethernet_; bool reenable_cert_check_; bool transaction_complete_signalled_; + bool activation_status_test_; + bool evaluating_; + // Connection retry counter. + int connection_retry_count_; + // Connection start time. + base::Time connection_start_time_; DISALLOW_COPY_AND_ASSIGN(MobileSetupHandler); }; @@ -323,6 +341,8 @@ void MobileSetupUIHTMLSource::StartDataRequest(const std::string& path, l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_HEADER)); strings.SetString("completed_text", l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_TEXT)); + strings.SetString("close_button", + l10n_util::GetStringUTF16(IDS_CLOSE)); SetFontAndTextDirection(&strings); static const base::StringPiece html( @@ -350,7 +370,10 @@ MobileSetupHandler::MobileSetupHandler(const std::string& service_path) reenable_wifi_(false), reenable_ethernet_(false), reenable_cert_check_(false), - transaction_complete_signalled_(false) { + transaction_complete_signalled_(false), + activation_status_test_(false), + evaluating_(false), + connection_retry_count_(0) { } MobileSetupHandler::~MobileSetupHandler() { @@ -374,8 +397,6 @@ void MobileSetupHandler::Init(TabContents* contents) { void MobileSetupHandler::RegisterMessages() { dom_ui_->RegisterMessageCallback(kJsApiStartActivation, NewCallback(this, &MobileSetupHandler::HandleStartActivation)); - dom_ui_->RegisterMessageCallback(kJsApiCloseTab, - NewCallback(this, &MobileSetupHandler::HandleCloseTab)); dom_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus, NewCallback(this, &MobileSetupHandler::HandleSetTransactionStatus)); } @@ -401,19 +422,11 @@ void MobileSetupHandler::OnNetworkChanged(chromeos::NetworkLibrary* cros, const_cast(network))); } -void MobileSetupHandler::HandleCloseTab(const ListValue* args) { - if (!dom_ui_) - return; - Browser* browser = BrowserList::FindBrowserWithFeature( - dom_ui_->GetProfile(), Browser::FEATURE_TABSTRIP); - if (browser) - browser->CloseTabContents(tab_contents_); -} - void MobileSetupHandler::HandleStartActivation(const ListValue* args) { scoped_refptr task = new TaskProxy(AsWeakPtr()); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(task.get(), &TaskProxy::HandleStartActivation)); + UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupStart", 1); } void MobileSetupHandler::HandleSetTransactionStatus(const ListValue* args) { @@ -452,11 +465,13 @@ void MobileSetupHandler::SetTransactionStatus(const std::string& status) { // again. if (LowerCaseEqualsASCII(status, "ok") && state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) { + UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1); if (transaction_complete_signalled_) { LOG(WARNING) << "Transaction completion signaled more than once!?"; return; } transaction_complete_signalled_ = true; + activation_status_test_ = false; state_ = PLAN_ACTIVATION_START; chromeos::CellularNetwork* network = GetCellularNetwork(); if (network && @@ -466,44 +481,66 @@ void MobileSetupHandler::SetTransactionStatus(const std::string& status) { } else { EvaluateCellularNetwork(network); } + } else { + UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1); } } + +void MobileSetupHandler::ConnectToNetwork(chromeos::CellularNetwork* network) { + connection_retry_count_++; + connection_start_time_ = base::Time::Now(); + chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> + ConnectToCellularNetwork(network); +} + +bool MobileSetupHandler::ConnectionTimeout() { + return (base::Time::Now() - + connection_start_time_).InSeconds() > kConnectionTimeoutSeconds; +} + void MobileSetupHandler::EvaluateCellularNetwork( chromeos::CellularNetwork* network) { if (!dom_ui_) return; PlanActivationState new_state = state_; - if (network) { - LOG(INFO) << "Cellular:\n service=" << network->GetStateString().c_str() - << "\n ui=" << GetStateDescription(state_) - << "\n activation=" << network->GetActivationStateString().c_str() - << "\n restricted=" << (network->restricted_pool() ? "yes" : "no") - << "\n error=" << network->GetErrorString().c_str() - << "\n setvice_path=" << network->service_path().c_str(); - } else { + if (!network) { LOG(WARNING) << "Cellular service lost"; + return; } + + // Prevent this method from being called if it is already on the stack. + // This might happen on some state transitions (ie. connect, disconnect). + if (evaluating_) + return; + evaluating_ = true; + + LOG(INFO) << "Cellular:\n service=" << network->GetStateString().c_str() + << "\n ui=" << GetStateDescription(state_) + << "\n activation=" << network->GetActivationStateString().c_str() + << "\n restricted=" << (network->restricted_pool() ? "yes" : "no") + << "\n error=" << network->GetErrorString().c_str() + << "\n setvice_path=" << network->service_path().c_str(); switch (state_) { - case PLAN_ACTIVATION_START: - if (network) { - switch (network->activation_state()) { - case chromeos::ACTIVATION_STATE_ACTIVATED: - if (network->failed_or_disconnected()) { - new_state = PLAN_ACTIVATION_RECONNECTING; - } else if (network->connection_state() == chromeos::STATE_READY) { - if (network->restricted_pool()) { - new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; - } else { - new_state = PLAN_ACTIVATION_DONE; - } + case PLAN_ACTIVATION_START: { + switch (network->activation_state()) { + case chromeos::ACTIVATION_STATE_ACTIVATED: { + if (network->failed_or_disconnected()) { + new_state = PLAN_ACTIVATION_RECONNECTING; + } else if (network->connected()) { + if (network->restricted_pool()) { + new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; + } else { + new_state = PLAN_ACTIVATION_DONE; } - break; - case chromeos::ACTIVATION_STATE_UNKNOWN: - case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: - case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: + } + break; + } + case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: { + if (!activation_status_test_) { if (network->failed_or_disconnected()) { + activation_status_test_ = true; new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION; } else if (network->connected()) { LOG(INFO) << "Disconnecting from " << @@ -512,69 +549,105 @@ void MobileSetupHandler::EvaluateCellularNetwork( DisconnectFromWirelessNetwork(network); // Disconnect will force networks to be reevaluated, so // we don't want to continue processing on this path anymore. + evaluating_ = false; return; } + } else { + if (network->connected()) { + if (network->restricted_pool()) + new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; + } else { + new_state = PLAN_ACTIVATION_RECONNECTING; + } break; - default: + } + break; + } + case chromeos::ACTIVATION_STATE_UNKNOWN: + case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: { + if (network->failed_or_disconnected()) { new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION; - break; + } else if (network->connected()) { + LOG(INFO) << "Disconnecting from " << + network->service_path().c_str(); + chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> + DisconnectFromWirelessNetwork(network); + // Disconnect will force networks to be reevaluated, so + // we don't want to continue processing on this path anymore. + evaluating_ = false; + return; + } + break; } + default: + break; } break; - case PLAN_ACTIVATION_INITIATING_ACTIVATION: - if (network) { - switch (network->activation_state()) { - case chromeos::ACTIVATION_STATE_ACTIVATED: - if (network->failed_or_disconnected()) { - new_state = PLAN_ACTIVATION_RECONNECTING; - } else if (network->connection_state() == chromeos::STATE_READY) { - if (network->restricted_pool()) { - new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; - } else { - new_state = PLAN_ACTIVATION_DONE; - } + } + case PLAN_ACTIVATION_INITIATING_ACTIVATION: { + switch (network->activation_state()) { + case chromeos::ACTIVATION_STATE_ACTIVATED: + if (network->failed_or_disconnected()) { + new_state = PLAN_ACTIVATION_RECONNECTING; + } else if (network->connected()) { + if (network->restricted_pool()) { + new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; + } else { + new_state = PLAN_ACTIVATION_DONE; } - break; - case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: - if (network->connected()) + } + break; + case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: + if (network->connected()) { + if (network->restricted_pool()) new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; - else - new_state = PLAN_ACTIVATION_RECONNECTING; - break; - case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: - // Wait in this state until activation state changes. - break; - case chromeos::ACTIVATION_STATE_ACTIVATING: - break; - default: - break; - } + } else { + new_state = PLAN_ACTIVATION_RECONNECTING; + } + break; + case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: + // Wait in this state until activation state changes. + break; + case chromeos::ACTIVATION_STATE_ACTIVATING: + break; + default: + break; } break; - case PLAN_ACTIVATION_RECONNECTING: - // Wait until the service shows up and gets activated. - if (network) { + } + case PLAN_ACTIVATION_RECONNECTING: { + if (network->connected()) { + // Wait until the service shows up and gets activated. switch (network->activation_state()) { case chromeos::ACTIVATION_STATE_ACTIVATED: - if (network->connection_state() == chromeos::STATE_READY) { - if (network->restricted_pool()) { - new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; - } else { - new_state = PLAN_ACTIVATION_DONE; - } - } + if (network->restricted_pool()) + new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; + else + new_state = PLAN_ACTIVATION_DONE; break; case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: - if (network->connected()) { - if (network->restricted_pool()) - new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; - } + if (network->restricted_pool()) + new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; break; default: break; } + } else if (network->failed() || ConnectionTimeout()) { + // Try to reconnect again if reconnect failed, or if for some + // reasons we are still not connected after 30 seconds. + if (connection_retry_count_ < kMaxConnectionRetry) { + UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1); + ConnectToNetwork(network); + evaluating_ = false; + return; + } else { + // We simply can't connect anymore after all these tries. + UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1); + new_state = PLAN_ACTIVATION_ERROR; + } } break; + } case PLAN_ACTIVATION_PAGE_LOADING: break; // Just ignore all signals until the site confirms payment. @@ -586,10 +659,27 @@ void MobileSetupHandler::EvaluateCellularNetwork( } std::string error_description; - if (GotActivationError(network, &error_description)) { - new_state = PLAN_ACTIVATION_ERROR; + if (new_state != PLAN_ACTIVATION_ERROR && + GotActivationError(network, &error_description)) { + // Check for this special case when we try to do activate partially + // activated device. If that attempt failed, try to disconnect to clear the + // state and reconnect again. + if ((network->activation_state() == + chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED || + network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATING) && + (network->error() == chromeos::ERROR_UNKNOWN || + network->error() == chromeos::ERROR_OTASP_FAILED)&& + (state_ == PLAN_ACTIVATION_INITIATING_ACTIVATION || + state_ == PLAN_ACTIVATION_RECONNECTING) && + activation_status_test_ && + network->connection_state() == chromeos::STATE_ACTIVATION_FAILURE) { + new_state = PLAN_ACTIVATION_RECONNECTING; + } else { + new_state = PLAN_ACTIVATION_ERROR; + } } ChangeState(network, new_state, error_description); + evaluating_ = false; } // Debugging helper function, will take it out at the end. @@ -632,6 +722,17 @@ void MobileSetupHandler::CompleteActivation( ReEnableOtherConnections(); } +void MobileSetupHandler::UpdatePage(chromeos::CellularNetwork* network, + const std::string& error_description) { + DictionaryValue device_dict; + if (network) + GetDeviceInfo(network, &device_dict); + device_dict.SetInteger("state", state_); + if (error_description.length()) + device_dict.SetString("error", error_description); + dom_ui_->CallJavascriptFunction( + kJsDeviceStatusChangedHandler, device_dict); +} void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network, PlanActivationState new_state, @@ -644,16 +745,9 @@ void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network, GetStateDescription(new_state); first_time = false; state_ = new_state; - DictionaryValue device_dict; // Signal to JS layer that the state is changing. - if (network) - GetDeviceInfo(network, &device_dict); - device_dict.SetInteger("state", new_state); - if (error_description.length()) - device_dict.SetString("error", error_description); - dom_ui_->CallJavascriptFunction( - kJsDeviceStatusChangedHandler, device_dict); + UpdatePage(network, error_description); // Decide what to do with network object as a result of the new state. switch (new_state) { @@ -662,15 +756,17 @@ void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network, case PLAN_ACTIVATION_INITIATING_ACTIVATION: DCHECK(network); LOG(INFO) << "Activating service " << network->service_path().c_str(); - if (!network->StartActivation()) - new_state = PLAN_ACTIVATION_ERROR; + UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1); + if (!network->StartActivation()) { + UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1); + ChangeState(network, PLAN_ACTIVATION_ERROR, std::string()); + } break; case PLAN_ACTIVATION_RECONNECTING: { - DCHECK(network); - if (network) { - chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> - ConnectToCellularNetwork(network); - } + // Reset connection metrics and try to connect. + connection_retry_count_ = 0; + connection_start_time_ = base::Time::Now(); + ConnectToNetwork(network); break; } case PLAN_ACTIVATION_PAGE_LOADING: @@ -682,9 +778,11 @@ void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network, case PLAN_ACTIVATION_DONE: DCHECK(network); CompleteActivation(network); + UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1); break; case PLAN_ACTIVATION_ERROR: { CompleteActivation(NULL); + UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1); break; } default: @@ -748,8 +846,7 @@ void MobileSetupHandler::SetupActivationProcess( bool MobileSetupHandler::GotActivationError( const chromeos::CellularNetwork* network, std::string* error) { - if (!network) - return false; + DCHECK(network); bool got_error = false; const char* error_code = kErrorDefault; diff --git a/chrome/browser/chromeos/dom_ui/network_menu_ui.cc b/chrome/browser/chromeos/dom_ui/network_menu_ui.cc index 30df58f..a9aa9c4 100644 --- a/chrome/browser/chromeos/dom_ui/network_menu_ui.cc +++ b/chrome/browser/chromeos/dom_ui/network_menu_ui.cc @@ -30,8 +30,9 @@ class NetworkMenuSourceDelegate : public chromeos::MenuSourceDelegate { localized_strings->SetString("reconnect", l10n_util::GetStringUTF16( IDS_NETWORK_RECONNECT_TITLE)); - localized_strings->SetString("remeber_this_network", - l10n_util::GetStringUTF16(IDS_NETWORK_REMEMBER_THIS_NETWORK_TITLE)); + localized_strings->SetString("auto_connect_this_network", + l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT)); localized_strings->SetString("ssid_prompt", l10n_util::GetStringUTF16(IDS_NETWORK_SSID_HINT)); localized_strings->SetString("pass_prompt", @@ -149,14 +150,14 @@ bool NetworkMenuUI::ModelAction(const menus::MenuModel* model, values->GetString(2, &passphrase); // Optional std::string ssid; values->GetString(3, &ssid); // Optional - int remember = -1; // -1 indicates not set - std::string remember_str; - if (values->GetString(4, &remember_str)) // Optional - base::StringToInt(remember_str, &remember); + int auto_connect = -1; // -1 indicates default action (auto connect) + std::string auto_connect_str; + if (values->GetString(4, &auto_connect_str)) // Optional + base::StringToInt(auto_connect_str, &auto_connect); if (action == "connect" || action == "reconnect") { close_menu = network_menu->ConnectToNetworkAt(index, passphrase, ssid, - remember); + auto_connect); } else { LOG(WARNING) << "Unrecognized action: " << action << " from: " << chrome::kChromeUINetworkMenu; diff --git a/chrome/browser/chromeos/dom_ui/proxy_handler.cc b/chrome/browser/chromeos/dom_ui/proxy_handler.cc index 2ca89be..ffe3040 100644 --- a/chrome/browser/chromeos/dom_ui/proxy_handler.cc +++ b/chrome/browser/chromeos/dom_ui/proxy_handler.cc @@ -12,7 +12,7 @@ #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/chromeos/cros_settings_provider_proxy.h" +#include "chrome/browser/chromeos/proxy_cros_settings_provider.h" #include "chrome/common/notification_service.h" #include "grit/browser_resources.h" #include "grit/chromium_strings.h" @@ -23,7 +23,7 @@ namespace chromeos { ProxyHandler::ProxyHandler() - : CrosOptionsPageUIHandler(new CrosSettingsProviderProxy()) { + : CrosOptionsPageUIHandler(new ProxyCrosSettingsProvider()) { } ProxyHandler::~ProxyHandler() { diff --git a/chrome/browser/chromeos/dom_ui/stats_options_handler.cc b/chrome/browser/chromeos/dom_ui/stats_options_handler.cc index 2372a29..c228946 100644 --- a/chrome/browser/chromeos/dom_ui/stats_options_handler.cc +++ b/chrome/browser/chromeos/dom_ui/stats_options_handler.cc @@ -9,7 +9,7 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chromeos/cros_settings_names.h" -#include "chrome/browser/chromeos/cros_settings_provider_stats.h" +#include "chrome/browser/chromeos/metrics_cros_settings_provider.h" #include "chrome/browser/metrics/user_metrics.h" namespace chromeos { diff --git a/chrome/browser/chromeos/dom_ui/system_settings_provider.cc b/chrome/browser/chromeos/dom_ui/system_settings_provider.cc index a376cf0..cbf54a2 100644 --- a/chrome/browser/chromeos/dom_ui/system_settings_provider.cc +++ b/chrome/browser/chromeos/dom_ui/system_settings_provider.cc @@ -6,57 +6,183 @@ #include +#include "app/l10n_util.h" +#include "base/i18n/rtl.h" +#include "base/lock.h" +#include "base/scoped_ptr.h" #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/stringprintf.h" #include "base/time.h" -#include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros_settings.h" #include "chrome/browser/chromeos/cros_settings_names.h" +#include "grit/generated_resources.h" +#include "unicode/calendar.h" +#include "unicode/timezone.h" +#include "unicode/ures.h" -namespace chromeos { +namespace { -static const char* kTimeZonesUtf8[] = { - "Pacific/Samoa", - "US/Hawaii", - "US/Alaska", - "US/Pacific", - "US/Mountain", - "US/Central", - "US/Eastern", +// TODO(jungshik): Using Enumerate method in ICU gives 600+ timezones. +// Even after filtering out duplicate entries with a strict identity check, +// we still have 400+ zones. Relaxing the criteria for the timezone +// identity is likely to cut down the number to < 100. Until we +// come up with a better list, we hard-code the following list as used by +// Android. +static const char* kTimeZones[] = { + "Pacific/Majuro", + "Pacific/Midway", + "Pacific/Honolulu", + "America/Anchorage", + "America/Los_Angeles", + "America/Tijuana", + "America/Denver", + "America/Phoenix", + "America/Chihuahua", + "America/Chicago", + "America/Mexico_City", + "America/Costa_Rica", + "America/Regina", + "America/New_York", + "America/Bogota", + "America/Caracas", + "America/Barbados", + "America/Manaus", "America/Santiago", + "America/St_Johns", "America/Sao_Paulo", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Godthab", + "America/Montevideo", "Atlantic/South_Georgia", + "Atlantic/Azores", "Atlantic/Cape_Verde", + "Africa/Casablanca", "Europe/London", - "Europe/Rome", + "Europe/Amsterdam", + "Europe/Belgrade", + "Europe/Brussels", + "Europe/Sarajevo", + "Africa/Windhoek", + "Africa/Brazzaville", + "Asia/Amman", + "Europe/Athens", + "Asia/Beirut", + "Africa/Cairo", "Europe/Helsinki", + "Asia/Jerusalem", + "Europe/Minsk", + "Africa/Harare", + "Asia/Baghdad", "Europe/Moscow", + "Asia/Kuwait", + "Africa/Nairobi", + "Asia/Tehran", + "Asia/Baku", + "Asia/Tbilisi", + "Asia/Yerevan", "Asia/Dubai", + "Asia/Kabul", "Asia/Karachi", - "Asia/Dhaka", + "Asia/Oral", + "Asia/Yekaterinburg", + "Asia/Calcutta", + "Asia/Colombo", + "Asia/Katmandu", + "Asia/Almaty", + "Asia/Rangoon", + "Asia/Krasnoyarsk", "Asia/Bangkok", + "Asia/Shanghai", "Asia/Hong_Kong", + "Asia/Irkutsk", + "Asia/Kuala_Lumpur", + "Australia/Perth", + "Asia/Taipei", + "Asia/Seoul", "Asia/Tokyo", + "Asia/Yakutsk", + "Australia/Adelaide", + "Australia/Darwin", + "Australia/Brisbane", + "Australia/Hobart", "Australia/Sydney", + "Asia/Vladivostok", + "Pacific/Guam", "Asia/Magadan", - "Pacific/Auckland" }; + "Pacific/Auckland", + "Pacific/Fiji", + "Pacific/Tongatapu", +}; + +static Lock timezone_bundle_lock; + +struct UResClose { + inline void operator() (UResourceBundle* b) const { + ures_close(b); + } +}; + +string16 GetExemplarCity(const icu::TimeZone& zone) { + // TODO(jungshik): After upgrading to ICU 4.6, use U_ICUDATA_ZONE + static const char* zone_bundle_name = NULL; + + // These will be leaked at the end. + static UResourceBundle *zone_bundle = NULL; + static UResourceBundle *zone_strings = NULL; + + UErrorCode status = U_ZERO_ERROR; + { + AutoLock lock(timezone_bundle_lock); + if (zone_bundle == NULL) + zone_bundle = ures_open(zone_bundle_name, uloc_getDefault(), &status); + + if (zone_strings == NULL) + zone_strings = ures_getByKey(zone_bundle, "zone_strings", NULL, &status); + } + + UnicodeString zone_id; + zone.getID(zone_id); + std::string zone_id_str; + zone_id.toUTF8String(zone_id_str); + + // resource keys for timezones use ':' in place of '/'. + ReplaceSubstringsAfterOffset(&zone_id_str, 0, "/", ":"); + scoped_ptr_malloc zone_item( + ures_getByKey(zone_strings, zone_id_str.c_str(), NULL, &status)); + UnicodeString city; + if (U_FAILURE(status)) + goto fallback; + city = ures_getUnicodeStringByKey(zone_item.get(), "ec", &status); + if (U_SUCCESS(status)) + return string16(city.getBuffer(), city.length()); + + fallback: + ReplaceSubstringsAfterOffset(&zone_id_str, 0, ":", "/"); + // Take the last component of a timezone id (e.g. 'Baz' in 'Foo/Bar/Baz'). + // Depending on timezones, keeping all but the 1st component + // (e.g. Bar/Baz) may be better, but our current list does not have + // any timezone for which that's the case. + std::string::size_type slash_pos = zone_id_str.rfind('/'); + if (slash_pos != std::string::npos && slash_pos < zone_id_str.size()) + zone_id_str.erase(0, slash_pos + 1); + // zone id has '_' in place of ' '. + ReplaceSubstringsAfterOffset(&zone_id_str, 0, "_", " "); + return ASCIIToUTF16(zone_id_str); +} + +} // namespace anonymous + +namespace chromeos { SystemSettingsProvider::SystemSettingsProvider() { - // 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++) { + for (size_t i = 0; i < arraysize(kTimeZones); i++) { timezones_.push_back(icu::TimeZone::createTimeZone( - icu::UnicodeString::fromUTF8(kTimeZonesUtf8[i]))); + icu::UnicodeString(kTimeZones[i], -1, US_INV))); } CrosLibrary::Get()->GetSystemLibrary()->AddObserver(this); @@ -114,17 +240,41 @@ ListValue* SystemSettingsProvider::GetTimezoneList() { string16 SystemSettingsProvider::GetTimezoneName( const icu::TimeZone& timezone) { + // Instead of using the raw_offset, use the offset in effect now. + // For instance, US Pacific Time, the offset shown will be -7 in summer + // while it'll be -8 in winter. + int raw_offset, dst_offset; + UDate now = icu::Calendar::getNow(); + UErrorCode status = U_ZERO_ERROR; + timezone.getOffset(now, false, raw_offset, dst_offset, status); + DCHECK(U_SUCCESS(status)); + int offset = raw_offset + dst_offset; + // offset is in msec. + int minute_offset = std::abs(offset) / 60000; + int hour_offset = minute_offset / 60; + int min_remainder = minute_offset % 60; + // Some timezones have a non-integral hour offset. So, we need to + // use hh:mm form. + std::string offset_str = base::StringPrintf(offset >= 0 ? + "UTC+%d:%02d" : "UTC-%d:%02d", hour_offset, min_remainder); + + // TODO(jungshik): When coming up with a better list of timezones, we also + // have to come up with better 'display' names. One possibility is to list + // multiple cities (e.g. "Los Angeles, Vancouver .." in the order of + // the population of a country the city belongs to.). + // We can also think of using LONG_GENERIC or LOCATION once we upgrade + // to ICU 4.6. + // In the meantime, we use "LONG" name with "Exemplar City" to distinguish + // multiple timezones with the same "LONG" name but with different + // rules (e.g. US Mountain Time in Dever vs Phoneix). icu::UnicodeString name; - timezone.getDisplayName(name); - string16 output(name.getBuffer(), name.length()); - int hour_offset = timezone.getRawOffset() / 3600000; - const wchar_t* format; - if (hour_offset == 0) - format = L"(GMT) "; - else - format = L"(GMT%+d) "; - std::wstring offset = base::StringPrintf(format, hour_offset); - return WideToUTF16(offset) + output; + timezone.getDisplayName(dst_offset != 0, icu::TimeZone::LONG, name); + string16 result(l10n_util::GetStringFUTF16( + IDS_OPTIONS_SETTINGS_TIMEZONE_DISPLAY_TEMPLATE, ASCIIToUTF16(offset_str), + string16(name.getBuffer(), name.length()), GetExemplarCity(timezone))); + string16 rtl_safe_result = result; + base::i18n::AdjustStringForLocaleDirection(result, &rtl_safe_result); + return rtl_safe_result; } string16 SystemSettingsProvider::GetTimezoneID( diff --git a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc index cbc9c82..fcf69fa 100644 --- a/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc +++ b/chrome/browser/chromeos/dom_ui/wrench_menu_ui.cc @@ -11,11 +11,11 @@ #include "base/values.h" #include "base/weak_ptr.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/chromeos/views/domui_menu_widget.h" #include "chrome/browser/chromeos/views/native_menu_domui.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_source.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc index a9d95ad..abb8219 100644 --- a/chrome/browser/chromeos/frame/browser_view.cc +++ b/chrome/browser/chromeos/frame/browser_view.cc @@ -18,6 +18,7 @@ #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/gtk/gtk_util.h" #include "chrome/browser/views/frame/browser_frame_gtk.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/frame/browser_view_layout.h" @@ -208,10 +209,13 @@ class BrowserViewLayout : public ::BrowserViewLayout { BrowserView::BrowserView(Browser* browser) : ::BrowserView(browser), - status_area_(NULL) { + status_area_(NULL), + saved_focused_widget_(NULL) { } BrowserView::~BrowserView() { + if (toolbar()) + toolbar()->RemoveMenuListener(this); } //////////////////////////////////////////////////////////////////////////////// @@ -232,6 +236,9 @@ void BrowserView::Init() { BrowserFrameGtk* gtk_frame = static_cast(frame()); gtk_frame->GetNonClientView()->SetContextMenuController(this); + // Listen to wrench menu opens. + toolbar()->AddMenuListener(this); + // Make sure the window is set to the right type. std::vector params; params.push_back(browser()->tab_count()); @@ -285,6 +292,18 @@ bool BrowserView::GetSavedWindowBounds(gfx::Rect* bounds) const { return ::BrowserView::GetSavedWindowBounds(bounds); } +void BrowserView::Cut() { + gtk_util::DoCut(this); +} + +void BrowserView::Copy() { + gtk_util::DoCopy(this); +} + +void BrowserView::Paste() { + gtk_util::DoPaste(this); +} + // views::ContextMenuController overrides. void BrowserView::ShowContextMenu(views::View* source, const gfx::Point& p, @@ -300,6 +319,11 @@ void BrowserView::ShowContextMenu(views::View* source, system_menu_menu_->RunMenuAt(p, views::Menu2::ALIGN_TOPLEFT); } +void BrowserView::OnMenuOpened() { + // Save the focused widget before wrench menu opens. + saved_focused_widget_ = gtk_window_get_focus(GetNativeHandle()); +} + // StatusAreaHost overrides. Profile* BrowserView::GetProfile() const { return browser()->profile(); diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h index c04758b..a99d17c 100644 --- a/chrome/browser/chromeos/frame/browser_view.h +++ b/chrome/browser/chromeos/frame/browser_view.h @@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/status/status_area_host.h" #include "chrome/browser/views/frame/browser_view.h" +#include "views/controls/menu/menu_wrapper.h" class AccessibleToolbarView; class TabStripModel; @@ -40,6 +41,7 @@ class StatusAreaButton; // and adds the system context menu to the remaining arae of the titlebar. class BrowserView : public ::BrowserView, public views::ContextMenuController, + public views::MenuListener, public StatusAreaHost { public: explicit BrowserView(Browser* browser); @@ -52,12 +54,18 @@ class BrowserView : public ::BrowserView, virtual views::LayoutManager* CreateLayoutManager() const; virtual void ChildPreferredSizeChanged(View* child); virtual bool GetSavedWindowBounds(gfx::Rect* bounds) const; + virtual void Cut(); + virtual void Copy(); + virtual void Paste(); // views::ContextMenuController overrides. virtual void ShowContextMenu(views::View* source, const gfx::Point& p, bool is_mouse_gesture); + // views::MenuListener implementation. + virtual void OnMenuOpened(); + // StatusAreaHost overrides. virtual Profile* GetProfile() const; virtual gfx::NativeWindow GetNativeWindow() const; @@ -68,6 +76,10 @@ class BrowserView : public ::BrowserView, virtual bool IsBrowserMode() const; virtual bool IsScreenLockerMode() const; + gfx::NativeView saved_focused_widget() const { + return saved_focused_widget_; + } + protected: virtual void GetAccessiblePanes( std::vector* panes); @@ -82,6 +94,10 @@ class BrowserView : public ::BrowserView, scoped_ptr system_menu_contents_; scoped_ptr system_menu_menu_; + // Focused native widget before wench menu shows up. We need this to properly + // perform cut, copy and paste. See http://crosbug.com/8496 + gfx::NativeView saved_focused_widget_; + DISALLOW_COPY_AND_ASSIGN(BrowserView); }; diff --git a/chrome/browser/chromeos/frame/bubble_frame_view.cc b/chrome/browser/chromeos/frame/bubble_frame_view.cc index becfb78..9fe97c2 100644 --- a/chrome/browser/chromeos/frame/bubble_frame_view.cc +++ b/chrome/browser/chromeos/frame/bubble_frame_view.cc @@ -11,10 +11,12 @@ #include "gfx/path.h" #include "gfx/rect.h" #include "chrome/browser/chromeos/frame/bubble_window.h" +#include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/views/bubble_border.h" #include "grit/theme_resources.h" #include "views/controls/button/image_button.h" #include "views/controls/label.h" +#include "views/controls/throbber.h" #include "views/window/hit_test.h" #include "views/window/window.h" #include "views/window/window_delegate.h" @@ -35,7 +37,8 @@ BubbleFrameView::BubbleFrameView(views::Window* frame, : frame_(frame), style_(style), title_(NULL), - close_button_(NULL) { + close_button_(NULL), + throbber_(NULL) { set_border(new BubbleBorder(BubbleBorder::NONE)); if (frame_->GetDelegate()->ShouldShowWindowTitle()) { @@ -56,11 +59,30 @@ BubbleFrameView::BubbleFrameView(views::Window* frame, rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); AddChildView(close_button_); } + + if (style_ & BubbleWindow::STYLE_THROBBER) { + throbber_ = CreateDefaultSmoothedThrobber(); + AddChildView(throbber_); + } } BubbleFrameView::~BubbleFrameView() { } +void BubbleFrameView::StartThrobber() { + DCHECK(throbber_ != NULL); + if (title_) + title_->SetText(std::wstring()); + throbber_->Start(); +} + +void BubbleFrameView::StopThrobber() { + DCHECK(throbber_ != NULL); + throbber_->Stop(); + if (title_) + title_->SetText(frame_->GetDelegate()->GetWindowTitle()); +} + gfx::Rect BubbleFrameView::GetBoundsForClientView() const { return client_view_bounds_; } @@ -68,20 +90,25 @@ gfx::Rect BubbleFrameView::GetBoundsForClientView() const { gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { gfx::Insets insets = GetInsets(); + gfx::Size title_size; - if (title_) { + if (title_) title_size = title_->GetPreferredSize(); - } - - gfx::Size close_button_size = gfx::Size(); - if (close_button_) { + gfx::Size close_button_size; + if (close_button_) close_button_size = close_button_->GetPreferredSize(); - } + gfx::Size throbber_size; + if (throbber_) + throbber_size = throbber_->GetPreferredSize(); int top_height = insets.top(); - if (title_size.height() > 0 || close_button_size.height() > 0) - top_height += std::max(title_size.height(), close_button_size.height()) + - kTitleContentPadding; + if (title_size.height() > 0 || + close_button_size.height() > 0 || + throbber_size.height() > 0) { + top_height += kTitleContentPadding + std::max( + std::max(title_size.height(), close_button_size.height()), + throbber_size.height()); + } return gfx::Rect(std::max(0, client_bounds.x() - insets.left()), std::max(0, client_bounds.y() - top_height), client_bounds.width() + insets.width(), @@ -125,14 +152,14 @@ void BubbleFrameView::Layout() { gfx::Insets insets = GetInsets(); gfx::Size title_size; - if (title_) { + if (title_) title_size = title_->GetPreferredSize(); - } - - gfx::Size close_button_size = gfx::Size(); - if (close_button_) { + gfx::Size close_button_size; + if (close_button_) close_button_size = close_button_->GetPreferredSize(); - } + gfx::Size throbber_size; + if (throbber_) + throbber_size = throbber_->GetPreferredSize(); if (title_) { title_->SetBounds( @@ -147,10 +174,21 @@ void BubbleFrameView::Layout() { close_button_size.width(), close_button_size.height()); } + if (throbber_) { + throbber_->SetBounds( + insets.left(), insets.top(), + std::min(throbber_size.width(), width()), + throbber_size.height()); + } + int top_height = insets.top(); - if (title_size.height() > 0 || close_button_size.height() > 0) - top_height += std::max(title_size.height(), close_button_size.height()) + - kTitleContentPadding; + if (title_size.height() > 0 || + close_button_size.height() > 0 || + throbber_size.height() > 0) { + top_height += kTitleContentPadding + std::max( + std::max(title_size.height(), close_button_size.height()), + throbber_size.height()); + } client_view_bounds_.SetRect(insets.left(), top_height, std::max(0, width() - insets.width()), std::max(0, height() - top_height - insets.bottom())); @@ -177,9 +215,8 @@ void BubbleFrameView::Paint(gfx::Canvas* canvas) { void BubbleFrameView::ButtonPressed(views::Button* sender, const views::Event& event) { - if (close_button_ != NULL && sender == close_button_) { + if (close_button_ != NULL && sender == close_button_) frame_->Close(); - } } } // namespace chromeos diff --git a/chrome/browser/chromeos/frame/bubble_frame_view.h b/chrome/browser/chromeos/frame/bubble_frame_view.h index 7ebb29e..dd32530 100644 --- a/chrome/browser/chromeos/frame/bubble_frame_view.h +++ b/chrome/browser/chromeos/frame/bubble_frame_view.h @@ -52,6 +52,9 @@ class BubbleFrameView : public views::NonClientFrameView, virtual void ButtonPressed(views::Button* sender, const views::Event& event); + void StartThrobber(); + void StopThrobber(); + private: // The window that owns this view. views::Window* frame_; @@ -68,6 +71,9 @@ class BubbleFrameView : public views::NonClientFrameView, // Close button for STYLE_XBAR case. views::ImageButton* close_button_; + // Throbber is optional. Employed by STYLE_THROBBER. + views::Throbber* throbber_; + DISALLOW_COPY_AND_ASSIGN(BubbleFrameView); }; diff --git a/chrome/browser/chromeos/frame/bubble_window.cc b/chrome/browser/chromeos/frame/bubble_window.cc index 25db342..8f3f4a4 100644 --- a/chrome/browser/chromeos/frame/bubble_window.cc +++ b/chrome/browser/chromeos/frame/bubble_window.cc @@ -25,8 +25,22 @@ BubbleWindow::BubbleWindow(views::WindowDelegate* window_delegate) void BubbleWindow::Init(GtkWindow* parent, const gfx::Rect& bounds) { views::WindowGtk::Init(parent, bounds); + // Turn on double buffering so that the hosted GtkWidgets does not + // flash as in http://crosbug.com/9065. + EnableDoubleBuffer(true); + GdkColor background_color = gfx::SkColorToGdkColor(kBackgroundColor); gtk_widget_modify_bg(GetNativeView(), GTK_STATE_NORMAL, &background_color); + + // A work-around for http://crosbug.com/8538. All GdkWidnow of top-level + // GtkWindow should participate _NET_WM_SYNC_REQUEST protocol and window + // manager should only show the window after getting notified. And we + // should only notify window manager after at least one paint is done. + // TODO(xiyuan): Figure out the right fix. + gtk_widget_realize(GetNativeView()); + gdk_window_set_back_pixmap(GetNativeView()->window, NULL, FALSE); + gtk_widget_realize(window_contents()); + gdk_window_set_back_pixmap(window_contents()->window, NULL, FALSE); } views::Window* BubbleWindow::Create( diff --git a/chrome/browser/chromeos/frame/bubble_window.h b/chrome/browser/chromeos/frame/bubble_window.h index fca4805..a3b313e 100644 --- a/chrome/browser/chromeos/frame/bubble_window.h +++ b/chrome/browser/chromeos/frame/bubble_window.h @@ -14,6 +14,7 @@ class Rect; } namespace views { +class Throbber; class WindowDelegate; } @@ -24,7 +25,8 @@ class BubbleWindow : public views::WindowGtk { public: enum Style { STYLE_GENERIC = 0, // Default style. - STYLE_XBAR = 1 << 0 // Show close button at the top right (left for RTL). + STYLE_XBAR = 1 << 0, // Show close button at the top right (left for RTL). + STYLE_THROBBER = 1 << 1 // Show throbber for slow rendering. }; static views::Window* Create(gfx::NativeWindow parent, @@ -39,8 +41,6 @@ class BubbleWindow : public views::WindowGtk { // Overidden from views::WindowGtk: virtual void Init(GtkWindow* parent, const gfx::Rect& bounds); - - Style style_; }; } // namespace chromeos diff --git a/chrome/browser/chromeos/frame/panel_controller.cc b/chrome/browser/chromeos/frame/panel_controller.cc index bfdc915..ef5d917 100644 --- a/chrome/browser/chromeos/frame/panel_controller.cc +++ b/chrome/browser/chromeos/frame/panel_controller.cc @@ -12,8 +12,8 @@ #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/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "cros/chromeos_wm_ipc_enums.h" #include "gfx/canvas_skia.h" diff --git a/chrome/browser/chromeos/input_method/candidate_window.cc b/chrome/browser/chromeos/input_method/candidate_window.cc index 3444f53..5167629 100644 --- a/chrome/browser/chromeos/input_method/candidate_window.cc +++ b/chrome/browser/chromeos/input_method/candidate_window.cc @@ -1,41 +1,26 @@ // 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. -// -// TODO(satorux): -// - Implement a scroll bar or an indicator showing where you are in the -// candidate window. + +#include "chrome/browser/chromeos/input_method/candidate_window.h" #include #include #include -#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/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 "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" #include "views/fill_layout.h" -#include "views/focus/accelerator_handler.h" #include "views/grid_layout.h" #include "views/screen.h" #include "views/widget/root_view.h" @@ -508,13 +493,17 @@ class CandidateView : public views::View { views::Label* annotation_label_; }; +// The implementation of CandidateWindowController. // CandidateWindowController controls the CandidateWindow. -class CandidateWindowController : public CandidateWindowView::Observer { +class CandidateWindowController::Impl : public CandidateWindowView::Observer { public: - CandidateWindowController(); - virtual ~CandidateWindowController(); + Impl(); + virtual ~Impl(); + + // Initializes the candidate window. Returns true on success. bool Init(); + private: // Returns the work area of the monitor nearest the candidate window. gfx::Rect GetMonitorWorkAreaNearestWindow(); @@ -533,7 +522,6 @@ class CandidateWindowController : public CandidateWindowView::Observer { cursor_location_ = cursor_location; } - private: // Creates the candidate window view. void CreateView(); @@ -1076,26 +1064,27 @@ int CandidateWindowView::GetHorizontalOffset() { } -bool CandidateWindowController::Init() { +bool CandidateWindowController::Impl::Init() { // Initialize the input method UI status connection. InputMethodUiStatusMonitorFunctions functions; functions.hide_auxiliary_text = - &CandidateWindowController::OnHideAuxiliaryText; + &CandidateWindowController::Impl::OnHideAuxiliaryText; functions.hide_lookup_table = - &CandidateWindowController::OnHideLookupTable; + &CandidateWindowController::Impl::OnHideLookupTable; functions.set_cursor_location = - &CandidateWindowController::OnSetCursorLocation; + &CandidateWindowController::Impl::OnSetCursorLocation; functions.update_auxiliary_text = - &CandidateWindowController::OnUpdateAuxiliaryText; + &CandidateWindowController::Impl::OnUpdateAuxiliaryText; functions.update_lookup_table = - &CandidateWindowController::OnUpdateLookupTable; + &CandidateWindowController::Impl::OnUpdateLookupTable; ui_status_connection_ = MonitorInputMethodUiStatus(functions, this); if (!ui_status_connection_) { LOG(ERROR) << "MonitorInputMethodUiStatus() failed."; return false; } - MonitorInputMethodConnection(ui_status_connection_, - &CandidateWindowController::OnConnectionChange); + MonitorInputMethodConnection( + ui_status_connection_, + &CandidateWindowController::Impl::OnConnectionChange); // Create the candidate window view. CreateView(); @@ -1103,7 +1092,7 @@ bool CandidateWindowController::Init() { return true; } -void CandidateWindowController::CreateView() { +void CandidateWindowController::Impl::CreateView() { // Create a non-decorated frame. frame_.reset(views::Widget::CreatePopupWidget( views::Widget::NotTransparent, @@ -1126,22 +1115,22 @@ void CandidateWindowController::CreateView() { root_view->SetContentsView(candidate_window_); } -CandidateWindowController::CandidateWindowController() +CandidateWindowController::Impl::Impl() : ui_status_connection_(NULL), frame_(NULL) { } -CandidateWindowController::~CandidateWindowController() { +CandidateWindowController::Impl::~Impl() { candidate_window_->RemoveObserver(this); chromeos::DisconnectInputMethodUiStatus(ui_status_connection_); } -gfx::Rect CandidateWindowController::GetMonitorWorkAreaNearestWindow() { +gfx::Rect CandidateWindowController::Impl::GetMonitorWorkAreaNearestWindow() { return views::Screen::GetMonitorWorkAreaNearestWindow( frame_->GetNativeView()); } -void CandidateWindowController::MoveCandidateWindow( +void CandidateWindowController::Impl::MoveCandidateWindow( const gfx::Rect& cursor_location, int horizontal_offset) { const int x = cursor_location.x(); @@ -1177,30 +1166,30 @@ void CandidateWindowController::MoveCandidateWindow( frame_->SetBounds(frame_bounds); } -void CandidateWindowController::OnHideAuxiliaryText( +void CandidateWindowController::Impl::OnHideAuxiliaryText( void* input_method_library) { - CandidateWindowController* controller = - static_cast(input_method_library); + CandidateWindowController::Impl* controller = + static_cast(input_method_library); controller->candidate_window_->HideAuxiliaryText(); } -void CandidateWindowController::OnHideLookupTable( +void CandidateWindowController::Impl::OnHideLookupTable( void* input_method_library) { - CandidateWindowController* controller = - static_cast(input_method_library); + CandidateWindowController::Impl* controller = + static_cast(input_method_library); controller->frame_->Hide(); } -void CandidateWindowController::OnSetCursorLocation( +void CandidateWindowController::Impl::OnSetCursorLocation( void* input_method_library, int x, int y, int width, int height) { - CandidateWindowController* controller = - static_cast(input_method_library); + CandidateWindowController::Impl* controller = + static_cast(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. @@ -1223,12 +1212,12 @@ void CandidateWindowController::OnSetCursorLocation( controller->candidate_window_->ResizeAndSchedulePaint(); } -void CandidateWindowController::OnUpdateAuxiliaryText( +void CandidateWindowController::Impl::OnUpdateAuxiliaryText( void* input_method_library, const std::string& utf8_text, bool visible) { - CandidateWindowController* controller = - static_cast(input_method_library); + CandidateWindowController::Impl* controller = + static_cast(input_method_library); // If it's not visible, hide the auxiliary text and return. if (!visible) { controller->candidate_window_->HideAuxiliaryText(); @@ -1238,11 +1227,11 @@ void CandidateWindowController::OnUpdateAuxiliaryText( controller->candidate_window_->ShowAuxiliaryText(); } -void CandidateWindowController::OnUpdateLookupTable( +void CandidateWindowController::Impl::OnUpdateLookupTable( void* input_method_library, const InputMethodLookupTable& lookup_table) { - CandidateWindowController* controller = - static_cast(input_method_library); + CandidateWindowController::Impl* controller = + static_cast(input_method_library); // If it's not visible, hide the window and return. if (!lookup_table.visible) { @@ -1260,13 +1249,13 @@ void CandidateWindowController::OnUpdateLookupTable( controller->candidate_window_->GetHorizontalOffset()); } -void CandidateWindowController::OnCandidateCommitted(int index, +void CandidateWindowController::Impl::OnCandidateCommitted(int index, int button, int flags) { NotifyCandidateClicked(ui_status_connection_, index, button, flags); } -void CandidateWindowController::OnConnectionChange( +void CandidateWindowController::Impl::OnConnectionChange( void* input_method_library, bool connected) { if (!connected) { @@ -1275,60 +1264,16 @@ void CandidateWindowController::OnConnectionChange( } } -} // namespace chromeos - -int main(int argc, char** argv) { - // Initialize gtk stuff. - g_thread_init(NULL); - g_type_init(); - gtk_init(&argc, &argv); - - // Initialize Chrome stuff. - base::AtExitManager exit_manager; - base::EnableTerminationOnHeapCorruption(); - app::RegisterPathProvider(); - CommandLine::Init(argc, argv); - - // 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 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. - chrome::RegisterPathProvider(); // for libcros.so. - chromeos::CrosLibraryLoader lib_loader; - std::string error_string; - CHECK(lib_loader.Load(&error_string)) - << "Failed to load libcros, " << error_string; - - // Create the main message loop. - MessageLoop main_message_loop(MessageLoop::TYPE_UI); - - // Create the candidate window controller. - chromeos::CandidateWindowController controller; - if (!controller.Init()) { - return 1; - } +CandidateWindowController::CandidateWindowController() : + impl_(new CandidateWindowController::Impl) { +} - // Start the main loop. - views::AcceleratorHandler accelerator_handler; - MessageLoopForUI::current()->Run(&accelerator_handler); +CandidateWindowController::~CandidateWindowController() { + delete impl_; +} - return 0; +bool CandidateWindowController::Init() { + return impl_->Init(); } + +} // namespace chromeos diff --git a/chrome/browser/chromeos/input_method/candidate_window.gyp b/chrome/browser/chromeos/input_method/candidate_window.gyp index 0d3b446..faa3788 100644 --- a/chrome/browser/chromeos/input_method/candidate_window.gyp +++ b/chrome/browser/chromeos/input_method/candidate_window.gyp @@ -20,7 +20,9 @@ '../../../../views/views.gyp:views', ], 'sources': [ + 'candidate_window.h', 'candidate_window.cc', + 'candidate_window_main.cc', # For loading libcros. '../cros/cros_library_loader.cc', ], diff --git a/chrome/browser/chromeos/input_method/candidate_window.h b/chrome/browser/chromeos/input_method/candidate_window.h new file mode 100644 index 0000000..367a157 --- /dev/null +++ b/chrome/browser/chromeos/input_method/candidate_window.h @@ -0,0 +1,37 @@ +// 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. +// +// This file implements the input method candidate window used on Chrome OS. + +#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_H_ +#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_H_ +#pragma once + +#include "base/basictypes.h" + +namespace chromeos { + +// CandidateWindowController is used for controlling the input method +// candidate window. Once the initialization is done, the controller +// starts monitoring signals sent from the the background input method +// daemon, and shows and hides the candidate window as neeeded. Upon +// deletion of the object, monitoring stops and the view used for +// rendering the candidate view is deleted. +class CandidateWindowController { + public: + CandidateWindowController(); + virtual ~CandidateWindowController(); + + // Initializes the candidate window. Returns true on success. + bool Init(); + + private: + class Impl; + Impl* impl_; + DISALLOW_COPY_AND_ASSIGN(CandidateWindowController); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_H_ diff --git a/chrome/browser/chromeos/input_method/candidate_window_main.cc b/chrome/browser/chromeos/input_method/candidate_window_main.cc new file mode 100644 index 0000000..a8fbb15 --- /dev/null +++ b/chrome/browser/chromeos/input_method/candidate_window_main.cc @@ -0,0 +1,80 @@ +// 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/input_method/candidate_window.h" + +#include + +#include + +#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/message_loop.h" +#include "base/path_service.h" +#include "base/process_util.h" +#include "chrome/browser/chromeos/cros/cros_library_loader.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "cros/chromeos_cros_api.h" +#include "grit/app_locale_settings.h" +#include "views/focus/accelerator_handler.h" + +int main(int argc, char** argv) { + // Initialize gtk stuff. + g_thread_init(NULL); + g_type_init(); + gtk_init(&argc, &argv); + + // Initialize Chrome stuff. + base::AtExitManager exit_manager; + base::EnableTerminationOnHeapCorruption(); + app::RegisterPathProvider(); + CommandLine::Init(argc, argv); + + // 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 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. + chrome::RegisterPathProvider(); // for libcros.so. + chromeos::CrosLibraryLoader lib_loader; + std::string error_string; + CHECK(lib_loader.Load(&error_string)) + << "Failed to load libcros, " << error_string; + + // Create the main message loop. + MessageLoop main_message_loop(MessageLoop::TYPE_UI); + + // Create the candidate window controller. + chromeos::CandidateWindowController controller; + if (!controller.Init()) { + return 1; + } + + // Start the main loop. + views::AcceleratorHandler accelerator_handler; + MessageLoopForUI::current()->Run(&accelerator_handler); + + return 0; +} diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc index abf4e32..49f9d5b 100644 --- a/chrome/browser/chromeos/input_method/input_method_util.cc +++ b/chrome/browser/chromeos/input_method/input_method_util.cc @@ -376,7 +376,7 @@ std::string NormalizeLanguageCode( } // Upcase the country code part. for (size_t i = 3; i < copied_language_code.size(); ++i) { - copied_language_code[i] = ToUpperASCII(copied_language_code[i]); + copied_language_code[i] = base::ToUpperASCII(copied_language_code[i]); } return copied_language_code; } diff --git a/chrome/browser/chromeos/login/account_creation_view.cc b/chrome/browser/chromeos/login/account_creation_view.cc index 82ff793..0719c4e 100644 --- a/chrome/browser/chromeos/login/account_creation_view.cc +++ b/chrome/browser/chromeos/login/account_creation_view.cc @@ -54,8 +54,8 @@ class AccountCreationTabContents : public WizardWebPageViewTabContents, virtual void FormsSeen(const std::vector& forms) { } - virtual bool GetAutoFillSuggestions( - int query_id, bool form_autofilled, const webkit_glue::FormField& field) { + virtual bool GetAutoFillSuggestions(bool field_autofilled, + const webkit_glue::FormField& field) { return false; } diff --git a/chrome/browser/chromeos/login/auth_attempt_state.cc b/chrome/browser/chromeos/login/auth_attempt_state.cc index 2732aca..459f7e9 100644 --- a/chrome/browser/chromeos/login/auth_attempt_state.cc +++ b/chrome/browser/chromeos/login/auth_attempt_state.cc @@ -8,6 +8,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "cros/chromeos_cryptohome.h" namespace chromeos { @@ -16,7 +17,8 @@ AuthAttemptState::AuthAttemptState(const std::string& username, const std::string& password, const std::string& ascii_hash, const std::string& login_token, - const std::string& login_captcha) + const std::string& login_captcha, + const bool user_is_new) : username(username), password(password), ascii_hash(ascii_hash), @@ -25,6 +27,8 @@ AuthAttemptState::AuthAttemptState(const std::string& username, unlock(false), online_complete_(false), online_outcome_(LoginFailure::NONE), + hosted_policy_(GaiaAuthFetcher::HostedAccountsAllowed), + is_first_time_user_(user_is_new), cryptohome_complete_(false), cryptohome_outcome_(false), cryptohome_code_(kCryptohomeMountErrorNone) { @@ -38,6 +42,8 @@ AuthAttemptState::AuthAttemptState(const std::string& username, online_complete_(true), online_outcome_(LoginFailure::UNLOCK_FAILED), credentials_(GaiaAuthConsumer::ClientLoginResult()), + hosted_policy_(GaiaAuthFetcher::HostedAccountsAllowed), + is_first_time_user_(false), cryptohome_complete_(false), cryptohome_outcome_(false), cryptohome_code_(kCryptohomeMountErrorNone) { @@ -52,6 +58,14 @@ void AuthAttemptState::RecordOnlineLoginStatus( online_complete_ = true; online_outcome_ = outcome; credentials_ = credentials; + // We're either going to not try again, or try again with HOSTED + // accounts not allowed, so just set this here. + DisableHosted(); +} + +void AuthAttemptState::DisableHosted() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + hosted_policy_ = GaiaAuthFetcher::HostedAccountsNotAllowed; } void AuthAttemptState::RecordCryptohomeStatus(bool cryptohome_outcome, @@ -84,6 +98,16 @@ const GaiaAuthConsumer::ClientLoginResult& AuthAttemptState::credentials() { return credentials_; } +bool AuthAttemptState::is_first_time_user() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + return is_first_time_user_; +} + +GaiaAuthFetcher::HostedAccountsSetting AuthAttemptState::hosted_policy() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + return hosted_policy_; +} + bool AuthAttemptState::cryptohome_complete() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); return cryptohome_complete_; diff --git a/chrome/browser/chromeos/login/auth_attempt_state.h b/chrome/browser/chromeos/login/auth_attempt_state.h index 41d5abb..b11ac1d 100644 --- a/chrome/browser/chromeos/login/auth_attempt_state.h +++ b/chrome/browser/chromeos/login/auth_attempt_state.h @@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/login/login_status_consumer.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" namespace chromeos { @@ -23,7 +24,8 @@ class AuthAttemptState { const std::string& password, const std::string& ascii_hash, const std::string& login_token, - const std::string& login_captcha); + const std::string& login_captcha, + const bool user_is_new); // Used to initalize for a screen unlock attempt. AuthAttemptState(const std::string& username, const std::string& ascii_hash); @@ -37,6 +39,9 @@ class AuthAttemptState { const GaiaAuthConsumer::ClientLoginResult& credentials, const LoginFailure& outcome); + // The next attempt will not allow HOSTED accounts to log in. + void DisableHosted(); + // Copy |cryptohome_code| and |cryptohome_outcome| into this object, // so we can have a copy we're sure to own, and can make available // on the IO thread. Must be called from the IO thread. @@ -49,6 +54,8 @@ class AuthAttemptState { virtual bool online_complete(); virtual const LoginFailure& online_outcome(); virtual const GaiaAuthConsumer::ClientLoginResult& credentials(); + virtual bool is_first_time_user(); + virtual GaiaAuthFetcher::HostedAccountsSetting hosted_policy(); virtual bool cryptohome_complete(); virtual bool cryptohome_outcome(); @@ -74,6 +81,11 @@ class AuthAttemptState { LoginFailure online_outcome_; GaiaAuthConsumer::ClientLoginResult credentials_; + // Whether or not we're accepting HOSTED accounts during the current + // online auth attempt. + GaiaAuthFetcher::HostedAccountsSetting hosted_policy_; + bool is_first_time_user_; + // Status of our cryptohome op attempt. Can only have one in flight at a time. bool cryptohome_complete_; bool cryptohome_outcome_; diff --git a/chrome/browser/chromeos/login/background_view.cc b/chrome/browser/chromeos/login/background_view.cc index bbaaaf1..0a8de2b 100644 --- a/chrome/browser/chromeos/login/background_view.cc +++ b/chrome/browser/chromeos/login/background_view.cc @@ -158,6 +158,10 @@ void BackgroundView::SetStatusAreaVisible(bool visible) { status_area_->SetVisible(visible); } +void BackgroundView::SetStatusAreaEnabled(bool enable) { + status_area_->EnableButtons(enable); +} + void BackgroundView::SetOobeProgressBarVisible(bool visible) { if (!progress_bar_ && visible) InitProgressBar(); diff --git a/chrome/browser/chromeos/login/background_view.h b/chrome/browser/chromeos/login/background_view.h index fc4ea91..fec31c5 100644 --- a/chrome/browser/chromeos/login/background_view.h +++ b/chrome/browser/chromeos/login/background_view.h @@ -68,6 +68,9 @@ class BackgroundView : public views::View, // Toggles status area visibility. void SetStatusAreaVisible(bool visible); + // Toggles whether status area is enabled. + void SetStatusAreaEnabled(bool enable); + // Toggles OOBE progress bar visibility, the bar is hidden by default. void SetOobeProgressBarVisible(bool visible); diff --git a/chrome/browser/chromeos/login/cryptohome_op.cc b/chrome/browser/chromeos/login/cryptohome_op.cc index c04c6fe..b73da68 100644 --- a/chrome/browser/chromeos/login/cryptohome_op.cc +++ b/chrome/browser/chromeos/login/cryptohome_op.cc @@ -82,6 +82,7 @@ class MountGuestAttempt : public CryptohomeOp { class MigrateAttempt : public CryptohomeOp { public: + // TODO(cmasone): get rid of passing_old_hash arg, as it's always true. MigrateAttempt(AuthAttemptState* current_attempt, AuthAttemptStateResolver* callback, bool passing_old_hash, diff --git a/chrome/browser/chromeos/login/cryptohome_op_unittest.cc b/chrome/browser/chromeos/login/cryptohome_op_unittest.cc index 6e43bb7..ae65a1b 100644 --- a/chrome/browser/chromeos/login/cryptohome_op_unittest.cc +++ b/chrome/browser/chromeos/login/cryptohome_op_unittest.cc @@ -32,7 +32,7 @@ class CryptohomeOpTest : public ::testing::Test { io_thread_(BrowserThread::IO), username_("me@nowhere.org"), hash_ascii_("0a010000000000a0"), - state_(username_, "", hash_ascii_, "", ""), + state_(username_, "", hash_ascii_, "", "", false), resolver_(new MockAuthAttemptStateResolver), mock_library_(new MockCryptohomeLibrary) { } diff --git a/chrome/browser/chromeos/login/eula_view.cc b/chrome/browser/chromeos/login/eula_view.cc index 42bad5f..204ec6e 100644 --- a/chrome/browser/chromeos/login/eula_view.cc +++ b/chrome/browser/chromeos/login/eula_view.cc @@ -18,13 +18,13 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/cryptohome_library.h" -#include "chrome/browser/chromeos/cros_settings_provider_stats.h" #include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/network_screen_delegate.h" #include "chrome/browser/chromeos/login/rounded_rect_painter.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/metrics_cros_settings_provider.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -196,18 +196,19 @@ void TpmInfoView::PullPassword() { chromeos::CryptohomeLibrary* cryptohome = chromeos::CrosLibrary::Get()->GetCryptohomeLibrary(); - bool password_was_cleared = false; + bool password_acquired = false; if (password_->empty() && cryptohome->TpmIsReady()) { - bool password_acquired = cryptohome->TpmGetPassword(password_); - if (password_acquired) { - cryptohome->TpmClearStoredPassword(); - if (password_->empty()) - password_was_cleared = true; - } else { + password_acquired = cryptohome->TpmGetPassword(password_); + if (!password_acquired) { password_->clear(); + } else if (password_->empty()) { + // For a fresh OOBE flow TPM is uninitialized, + // ownership process is started at the EULA screen, + // password is cleared after EULA is accepted. + LOG(ERROR) << "TPM returned an empty password."; } } - if (password_->empty() && !password_was_cleared) { + if (password_->empty() && !password_acquired) { // Password hasn't been acquired, reschedule pulling. MessageLoop::current()->PostDelayedTask( FROM_HERE, diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 4ee8be9..f102542 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -20,13 +20,14 @@ #include "chrome/browser/chromeos/cros/cryptohome_library.h" #include "chrome/browser/chromeos/cros/login_library.h" #include "chrome/browser/chromeos/cros/network_library.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/status/status_area_view.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/chromeos/view_ids.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/views/window.h" @@ -215,6 +216,12 @@ void ExistingUserController::SelectNewUser() { SelectUser(controllers_.size() - 1); } +void ExistingUserController::SetStatusAreaEnabled(bool enable) { + if (background_view_) { + background_view_->SetStatusAreaEnabled(enable); + } +} + ExistingUserController::~ExistingUserController() { ClearErrors(); @@ -517,7 +524,13 @@ void ExistingUserController::OnPasswordChangeDetected( return; } - PasswordChangedView* view = new PasswordChangedView(this); + // TODO(altimofeev): remove this constrain when full sync for the owner will + // be correctly handled. + // TODO(xiyuan): Wait for the cached settings update before using them. + bool full_sync_disabled = (UserCrosSettingsProvider::cached_owner() == + controllers_[selected_view_index_]->user().email()); + + PasswordChangedView* view = new PasswordChangedView(this, full_sync_disabled); views::Window* window = browser::CreateViewsWindow(GetNativeWindow(), gfx::Rect(), view); diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h index aa4d7ca..e150a31 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.h +++ b/chrome/browser/chromeos/login/existing_user_controller.h @@ -85,6 +85,7 @@ class ExistingUserController : public WmMessageListener::Observer, virtual void RemoveUser(UserController* source); virtual void AddStartUrl(const GURL& start_url) { start_url_ = start_url; } virtual void SelectUser(int index); + virtual void SetStatusAreaEnabled(bool enable); // LoginPerformer::Delegate implementation: virtual void OnLoginFailure(const LoginFailure& error); diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc index a4daccd..81a1851 100644 --- a/chrome/browser/chromeos/login/google_authenticator.cc +++ b/chrome/browser/chromeos/login/google_authenticator.cc @@ -28,7 +28,7 @@ #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_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/notification_service.h" #include "net/base/load_flags.h" @@ -58,7 +58,7 @@ const int kPassHashLen = 32; GoogleAuthenticator::GoogleAuthenticator(LoginStatusConsumer* consumer) : Authenticator(consumer), user_manager_(UserManager::Get()), - hosted_policy_(GaiaAuthenticator2::HostedAccountsAllowed), + hosted_policy_(GaiaAuthFetcher::HostedAccountsAllowed), unlock_(false), try_again_(true), checked_for_localaccount_(false) { @@ -134,9 +134,9 @@ bool GoogleAuthenticator::AuthenticateToLogin( ascii_hash_.assign(HashPassword(password)); gaia_authenticator_.reset( - new GaiaAuthenticator2(this, - GaiaConstants::kChromeOSSource, - profile->GetRequestContext())); + new GaiaAuthFetcher(this, + GaiaConstants::kChromeOSSource, + profile->GetRequestContext())); // Will be used for retries. PrepareClientLoginAttempt(password, login_token, login_captcha); TryClientLogin(); @@ -184,7 +184,7 @@ void GoogleAuthenticator::OnClientLoginSuccess( VLOG(1) << "Online login successful!"; ClearClientLoginAttempt(); - if (hosted_policy_ == GaiaAuthenticator2::HostedAccountsAllowed && + if (hosted_policy_ == GaiaAuthFetcher::HostedAccountsAllowed && !user_manager_->IsKnownUser(username_)) { // First time user, and we don't know if the account is HOSTED or not. // Since we don't allow HOSTED accounts to log in, we need to try @@ -193,7 +193,7 @@ void GoogleAuthenticator::OnClientLoginSuccess( // NOTE: we used to do this in the opposite order, so that we'd only // try the HOSTED pathway if GOOGLE-only failed. This breaks CAPTCHA // handling, though. - hosted_policy_ = GaiaAuthenticator2::HostedAccountsNotAllowed; + hosted_policy_ = GaiaAuthFetcher::HostedAccountsNotAllowed; TryClientLogin(); return; } @@ -219,7 +219,7 @@ void GoogleAuthenticator::OnClientLoginFailure( if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS && !user_manager_->IsKnownUser(username_) && - hosted_policy_ != GaiaAuthenticator2::HostedAccountsAllowed) { + hosted_policy_ != GaiaAuthFetcher::HostedAccountsAllowed) { // This was a first-time login, we already tried allowing HOSTED accounts // and succeeded. That we've failed with INVALID_GAIA_CREDENTIALS now // indicates that the account is HOSTED. @@ -233,7 +233,7 @@ void GoogleAuthenticator::OnClientLoginFailure( &GoogleAuthenticator::OnLoginFailure, failure_details)); LOG(WARNING) << "Rejecting valid HOSTED account."; - hosted_policy_ = GaiaAuthenticator2::HostedAccountsNotAllowed; + hosted_policy_ = GaiaAuthFetcher::HostedAccountsNotAllowed; return; } diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h index a23a96c..d0651fa 100644 --- a/chrome/browser/chromeos/login/google_authenticator.h +++ b/chrome/browser/chromeos/login/google_authenticator.h @@ -16,7 +16,7 @@ #include "chrome/browser/chromeos/cros/cryptohome_library.h" #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" // Authenticates a Chromium OS user against the Google Accounts ClientLogin API. @@ -100,7 +100,7 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { const std::string& login_token, const std::string& login_captcha); - // Callbacks from GaiaAuthenticator2 + // Callbacks from GaiaAuthFetcher virtual void OnClientLoginFailure( const GoogleServiceAuthError& error); virtual void OnClientLoginSuccess( @@ -153,7 +153,7 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { char* hex_string, const unsigned int len); - void set_hosted_policy(GaiaAuthenticator2::HostedAccountsSetting policy) { + void set_hosted_policy(GaiaAuthFetcher::HostedAccountsSetting policy) { hosted_policy_ = policy; } @@ -168,7 +168,7 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { static const char kLocalaccountFile[]; // Handles all net communications with Gaia. - scoped_ptr gaia_authenticator_; + scoped_ptr gaia_authenticator_; // Allows us to look up users of the device. UserManager* user_manager_; @@ -180,7 +180,7 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { static const int kLocalaccountRetryIntervalMs; // Whether or not we're accepting HOSTED accounts on this auth attempt. - GaiaAuthenticator2::HostedAccountsSetting hosted_policy_; + GaiaAuthFetcher::HostedAccountsSetting hosted_policy_; std::string username_; // These fields are saved so we can retry client login. diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc index 956742a..04437fb 100644 --- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc @@ -25,7 +25,7 @@ #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" #include "chrome/common/net/url_fetcher.h" #include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" @@ -136,7 +136,7 @@ class GoogleAuthenticatorTest : public ::testing::Test { void PrepForFailedLogin(GoogleAuthenticator* auth) { PrepForLogin(auth); - auth->set_hosted_policy(GaiaAuthenticator2::HostedAccountsAllowed); + auth->set_hosted_policy(GaiaAuthFetcher::HostedAccountsAllowed); } void CancelLogin(GoogleAuthenticator* auth) { @@ -591,49 +591,6 @@ TEST_F(GoogleAuthenticatorTest, FullLogin) { message_loop.RunAllPending(); } -TEST_F(GoogleAuthenticatorTest, FullHostedLogin) { - MessageLoopForUI message_loop; - BrowserThread ui_thread(BrowserThread::UI, &message_loop); - chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_)); - - LoginFailure failure_details = - LoginFailure::FromNetworkAuthFailure( - GoogleServiceAuthError( - GoogleServiceAuthError::HOSTED_NOT_ALLOWED)); - - MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginFailure(failure_details)) - .WillOnce(Invoke(MockConsumer::OnFailQuit)) - .RetiresOnSaturation(); - // A failure case, but we still want the test to finish gracefully. - ON_CALL(consumer, OnLoginSuccess(username_, password_, _, _)) - .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); - - EXPECT_CALL(*mock_library_, GetSystemSalt()) - .WillOnce(Return(salt_v)) - .RetiresOnSaturation(); - - TestingProfile profile; - - MockFactory factory_invalid; - URLFetcher::set_factory(&factory_invalid); - - scoped_refptr auth(new GoogleAuthenticator(&consumer)); - auth->set_user_manager(user_manager_.get()); - EXPECT_CALL(*user_manager_.get(), IsKnownUser(username_)) - .WillOnce(Return(false)) - .WillOnce(Return(false)) - .RetiresOnSaturation(); - auth->AuthenticateToLogin( - &profile, username_, hash_ascii_, std::string(), std::string()); - - MockFactory factory_success; - URLFetcher::set_factory(&factory_success); - - message_loop.RunAllPending(); - URLFetcher::set_factory(NULL); -} - TEST_F(GoogleAuthenticatorTest, FullHostedLoginFailure) { MessageLoop message_loop(MessageLoop::TYPE_UI); BrowserThread ui_thread(BrowserThread::UI, &message_loop); diff --git a/chrome/browser/chromeos/login/guest_user_view.cc b/chrome/browser/chromeos/login/guest_user_view.cc index 9392c7b..a06e017 100644 --- a/chrome/browser/chromeos/login/guest_user_view.cc +++ b/chrome/browser/chromeos/login/guest_user_view.cc @@ -13,11 +13,11 @@ namespace chromeos { // Button with custom processing for Tab/Shift+Tab to select entries. -class UserEntryButton : public views::NativeButton { +class UserEntryButton : public login::WideButton { public: UserEntryButton(UserController* controller, const std::wstring& label) - : NativeButton(controller, label), + : WideButton(controller, label), controller_(controller) {} // Overridden from views::View: @@ -27,13 +27,13 @@ class UserEntryButton : public views::NativeButton { controller_->SelectUser(index); return true; } - return views::NativeButton::OnKeyPressed(e); + return WideButton::OnKeyPressed(e); } virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e) { if (e.GetKeyCode() == app::VKEY_TAB) return true; - return views::NativeButton::SkipDefaultKeyEventProcessing(e); + return WideButton::SkipDefaultKeyEventProcessing(e); } private: @@ -65,7 +65,6 @@ void GuestUserView::RecreateFields() { submit_button_ = new UserEntryButton( user_controller_, l10n_util::GetString(IDS_ENTER_GUEST_SESSION_BUTTON)); - CorrectNativeButtonFontSize(submit_button_); AddChildView(submit_button_); Layout(); SchedulePaint(); @@ -104,13 +103,11 @@ void GuestUserView::OnLocaleChanged() { void GuestUserView::Layout() { gfx::Size submit_button_size = submit_button_->GetPreferredSize(); - int submit_button_width = std::max(login::kButtonMinWidth, - submit_button_size.width()); - int submit_button_x = (width() - submit_button_width) / 2; + int submit_button_x = (width() - submit_button_size.width()) / 2; int submit_button_y = (height() - submit_button_size.height()) / 2; submit_button_->SetBounds(submit_button_x, submit_button_y, - submit_button_width, + submit_button_size.width(), submit_button_size.height()); } diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc index dea756f..b3905c0 100644 --- a/chrome/browser/chromeos/login/helper.cc +++ b/chrome/browser/chromeos/login/helper.cc @@ -11,6 +11,7 @@ #include "grit/theme_resources.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "views/controls/button/native_button.h" +#include "views/controls/label.h" #include "views/controls/textfield/textfield.h" #include "views/controls/throbber.h" #include "views/painter.h" @@ -96,6 +97,11 @@ gfx::Rect CalculateScreenBounds(const gfx::Size& size) { return bounds; } +void CorrectLabelFontSize(views::Label* label) { + if (label) + label->SetFont(label->font().DeriveFont(kFontSizeCorrectionDelta)); +} + void CorrectNativeButtonFontSize(views::NativeButton* button) { if (button) button->set_font(button->font().DeriveFont(kFontSizeCorrectionDelta)); @@ -110,5 +116,19 @@ GURL GetAccountRecoveryHelpUrl() { return google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl)); } +namespace login { + +// Minimal width for the button. +const int kButtonMinWidth = 90; + +gfx::Size WideButton::GetPreferredSize() { + gfx::Size preferred_size = NativeButton::GetPreferredSize(); + if (preferred_size.width() < kButtonMinWidth) + preferred_size.set_width(kButtonMinWidth); + return preferred_size; +} + +} // namespace login + } // namespace chromeos diff --git a/chrome/browser/chromeos/login/helper.h b/chrome/browser/chromeos/login/helper.h index 9713926..f69d3fc 100644 --- a/chrome/browser/chromeos/login/helper.h +++ b/chrome/browser/chromeos/login/helper.h @@ -8,6 +8,7 @@ #define CHROME_BROWSER_CHROMEOS_LOGIN_HELPER_H_ #pragma once +#include "views/controls/button/native_button.h" #include "third_party/skia/include/core/SkColor.h" class GURL; @@ -18,7 +19,7 @@ class Size; } // namespace gfx namespace views { -class NativeButton; +class Label; class Painter; class Textfield; class Throbber; @@ -41,6 +42,9 @@ views::Painter* CreateBackgroundPainter(); gfx::Rect CalculateScreenBounds(const gfx::Size& size); // Corrects font size for NativeButton control. +void CorrectLabelFontSize(views::Label* label); + +// Corrects font size for NativeButton control. void CorrectNativeButtonFontSize(views::NativeButton* button); // Corrects font size for Textfield control. @@ -58,9 +62,6 @@ enum Command { SIGN_OUT, }; -// Minimal width for the button. -const int kButtonMinWidth = 90; - // Gap between edge and image view, and image view and controls. const int kBorderSize = 6; @@ -84,6 +85,25 @@ const int kWizardScreenHeight = 450; const int kScreenCornerRadius = 10; const int kUserCornerRadius = 5; +// Username label height in different states. +const int kSelectedLabelHeight = 25; +const int kUnselectedLabelHeight = 20; + +class WideButton : public views::NativeButton { + public: + WideButton(views::ButtonListener* listener, const std::wstring& text) + : NativeButton(listener, text) { + CorrectNativeButtonFontSize(this); + } + + ~WideButton() {} + + private: + virtual gfx::Size GetPreferredSize(); + + DISALLOW_COPY_AND_ASSIGN(WideButton); +}; + } // namespace login // Font size correction in points for login/oobe textfields/buttons/title. diff --git a/chrome/browser/chromeos/login/language_switch_menu.cc b/chrome/browser/chromeos/login/language_switch_menu.cc index 3d8bcbc..c18d20d 100644 --- a/chrome/browser/chromeos/login/language_switch_menu.cc +++ b/chrome/browser/chromeos/login/language_switch_menu.cc @@ -78,8 +78,11 @@ void LanguageSwitchMenu::SetFirstLevelMenuWidth(int width) { // static void LanguageSwitchMenu::SwitchLanguage(const std::string& locale) { - // Save new locale. DCHECK(g_browser_process); + if (g_browser_process->GetApplicationLocale() == locale) { + return; + } + // Save new locale. PrefService* prefs = g_browser_process->local_state(); // TODO(markusheintz): If the preference is managed and can not be changed by // the user, changing the language should be disabled in the UI. diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index f307f27..5e6ee92 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc @@ -4,7 +4,6 @@ #include "base/command_line.h" #include "base/time.h" -#include "chrome/browser/browser.h" #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" #include "chrome/browser/chromeos/cros/mock_input_method_library.h" @@ -16,6 +15,7 @@ #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/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/chromeos/login/login_html_dialog.cc b/chrome/browser/chromeos/login/login_html_dialog.cc index e8ae340..f0ff81a 100644 --- a/chrome/browser/chromeos/login/login_html_dialog.cc +++ b/chrome/browser/chromeos/login/login_html_dialog.cc @@ -4,10 +4,12 @@ #include "chrome/browser/chromeos/login/login_html_dialog.h" +#include "chrome/browser/chromeos/frame/bubble_frame_view.h" #include "chrome/browser/chromeos/frame/bubble_window.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/views/html_dialog_view.h" +#include "chrome/common/notification_service.h" #include "gfx/native_widget_types.h" #include "gfx/rect.h" #include "gfx/size.h" @@ -49,7 +51,8 @@ LoginHtmlDialog::LoginHtmlDialog(Delegate* delegate, parent_window_(parent_window), title_(title), url_(url), - style_(style) { + style_(style), + bubble_frame_view_(NULL) { gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size())); width_ = static_cast(kDefaultWidthRatio * screen_bounds.width()); height_ = static_cast(kDefaultHeightRatio * screen_bounds.height()); @@ -63,19 +66,23 @@ void LoginHtmlDialog::Show() { HtmlDialogWithoutContextMenuView* html_view = new HtmlDialogWithoutContextMenuView(ProfileManager::GetDefaultProfile(), this); - switch (style_) { - case STYLE_BUBBLE: - chromeos::BubbleWindow::Create(parent_window_, - gfx::Rect(), - chromeos::BubbleWindow::STYLE_XBAR, - html_view); - break; - case STYLE_GENERIC: - default: - views::Window::CreateChromeWindow(parent_window_, - gfx::Rect(), - html_view); - break; + if (style_ & STYLE_BUBBLE) { + views::Window* bubble_window = BubbleWindow::Create( + parent_window_, gfx::Rect(), + static_cast( + BubbleWindow::STYLE_XBAR | BubbleWindow::STYLE_THROBBER), + html_view); + bubble_frame_view_ = static_cast( + bubble_window->GetNonClientView()->frame_view()); + } else { + (void)views::Window::CreateChromeWindow( + parent_window_, gfx::Rect(), html_view); + } + if (bubble_frame_view_) { + bubble_frame_view_->StartThrobber(); + notification_registrar_.Add(this, + NotificationType::LOAD_COMPLETED_MAIN_FRAME, + NotificationService::AllSources()); } html_view->InitDialog(); html_view->window()->Show(); @@ -87,6 +94,14 @@ void LoginHtmlDialog::SetDialogSize(int width, int height) { height_ = height; } +void LoginHtmlDialog::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type.value == NotificationType::LOAD_COMPLETED_MAIN_FRAME); + if (bubble_frame_view_) + bubble_frame_view_->StopThrobber(); +} + /////////////////////////////////////////////////////////////////////////////// // LoginHtmlDialog, protected: diff --git a/chrome/browser/chromeos/login/login_html_dialog.h b/chrome/browser/chromeos/login/login_html_dialog.h index 45f4d88..0955395 100644 --- a/chrome/browser/chromeos/login/login_html_dialog.h +++ b/chrome/browser/chromeos/login/login_html_dialog.h @@ -9,13 +9,18 @@ #include #include "chrome/browser/dom_ui/html_dialog_ui.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" #include "gfx/native_widget_types.h" #include "gfx/size.h" namespace chromeos { +class BubbleFrameView; + // Launches html dialog during OOBE/Login with specified URL and title. -class LoginHtmlDialog : public HtmlDialogUIDelegate { +class LoginHtmlDialog : public HtmlDialogUIDelegate, + public NotificationObserver { public: // Delegate class to get notifications from the dialog. class Delegate { @@ -59,6 +64,11 @@ class LoginHtmlDialog : public HtmlDialogUIDelegate { virtual void OnCloseContents(TabContents* source, bool* out_close_dialog); virtual bool ShouldShowDialogTitle() const { return true; } + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: // Notifications receiver. Delegate* delegate_; @@ -67,6 +77,8 @@ class LoginHtmlDialog : public HtmlDialogUIDelegate { std::wstring title_; GURL url_; Style style_; + NotificationRegistrar notification_registrar_; + BubbleFrameView* bubble_frame_view_; // Dialog display size. int width_; diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc index 8889bb2..eb5304d 100644 --- a/chrome/browser/chromeos/login/login_performer.cc +++ b/chrome/browser/chromeos/login/login_performer.cc @@ -9,8 +9,8 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/chromeos/boot_times_loader.h" -#include "chrome/browser/chromeos/cros_settings_provider_user.h" #include "chrome/browser/chromeos/login/login_utils.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index 209b889..c8ad2d2 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -14,9 +14,9 @@ #include "base/scoped_ptr.h" #include "base/singleton.h" #include "base/string_util.h" +#include "base/stringprintf.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/browser_thread.h" #include "chrome/browser/chromeos/boot_times_loader.h" @@ -26,6 +26,7 @@ #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/language_switch_menu.h" #include "chrome/browser/chromeos/login/ownership_service.h" #include "chrome/browser/chromeos/login/parallel_authenticator.h" #include "chrome/browser/chromeos/login/user_image_downloader.h" @@ -37,10 +38,11 @@ #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/ui/browser_init.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_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/url_request_context_getter.h" #include "chrome/common/pref_names.h" @@ -53,11 +55,16 @@ namespace chromeos { namespace { -// Prefix for Auth token received from ClientLogin request. +// Affixes for Auth token received from ClientLogin request. const char kAuthPrefix[] = "Auth="; -// Suffix for Auth token received from ClientLogin request. const char kAuthSuffix[] = "\n"; +// Increase logging level for Guest mode to avoid LOG(INFO) messages in logs. +const char kGuestModeLoggingLevel[] = "1"; + +// Format of command line switch. +const char kSwitchFormatString[] = "--%s=\"%s\""; + } // namespace class LoginUtilsImpl : public LoginUtils { @@ -92,6 +99,9 @@ class LoginUtilsImpl : public LoginUtils { virtual void PrewarmAuthentication(); private: + // Check user's profile for kApplicationLocale setting. + void RespectLocalePreference(PrefService* pref); + // Indicates if DoBrowserLaunch will actually launch the browser or not. bool browser_launch_enabled_; @@ -184,7 +194,7 @@ void LoginUtilsImpl::CompleteLogin( // Set the CrOS user by getting this constructor run with the // user's email on first retrieval. - profile->GetProfileSyncService(username)->SetPassphrase(password); + profile->GetProfileSyncService(username)->SetPassphrase(password, false); btl->AddLoginTimeMarker("SyncStarted", false); // Attempt to take ownership; this will fail if device is already owned. @@ -204,6 +214,8 @@ void LoginUtilsImpl::CompleteLogin( } btl->AddLoginTimeMarker("TPMOwned", false); + RespectLocalePreference(profile->GetPrefs()); + static const char kFallbackInputMethodLocale[] = "en-US"; if (first_login) { std::string locale(g_browser_process->GetApplicationLocale()); @@ -251,6 +263,19 @@ void LoginUtilsImpl::CompleteLogin( DoBrowserLaunch(profile); } +void LoginUtilsImpl::RespectLocalePreference(PrefService* pref) { + std::string pref_locale = pref->GetString(prefs::kApplicationLocale); + if (pref_locale.empty()) { + // TODO(dilmah): current code will clobber existing setting in case + // language preference was set via another device + // but still not synced yet. Profile is not synced at this point yet. + pref->SetString(prefs::kApplicationLocale, + g_browser_process->GetApplicationLocale()); + } else { + LanguageSwitchMenu::SwitchLanguage(pref_locale); + } +} + void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) { VLOG(1) << "Completing off the record login"; @@ -260,13 +285,17 @@ void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) { // For guest session 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 + switches::kLoginProfile, + switches::kEnableTabbedOptions, + switches::kCompressSystemFeedback, +#if defined(USE_SECCOMP_SANDBOX) + switches::kDisableSeccompSandbox, +#endif }; const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); @@ -276,15 +305,28 @@ void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) { arraysize(kForwardSwitches)); command_line.AppendSwitch(switches::kGuestSession); command_line.AppendSwitch(switches::kIncognito); - command_line.AppendSwitch(switches::kEnableTabbedOptions); + command_line.AppendSwitchASCII(switches::kLoggingLevel, + kGuestModeLoggingLevel); 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()); + + std::string cmd_line_str = command_line.command_line_string(); + // Special workaround for the arguments that should be quoted. + // Copying switches won't be needed when Guest mode won't need restart + // http://crosbug.com/6924 + if (browser_command_line.HasSwitch(switches::kRegisterPepperPlugins)) { + cmd_line_str += base::StringPrintf( + kSwitchFormatString, + switches::kRegisterPepperPlugins, + browser_command_line.GetSwitchValueNative( + switches::kRegisterPepperPlugins).c_str()); + } + + CrosLibrary::Get()->GetLoginLibrary()->RestartJob(getpid(), cmd_line_str); } } @@ -318,7 +360,7 @@ class WarmingObserver : public NetworkLibrary::NetworkManagerObserver { void OnNetworkManagerChanged(NetworkLibrary* netlib) { if (netlib->Connected()) { chrome_browser_net::Preconnect::PreconnectOnUIThread( - GURL(GaiaAuthenticator2::kClientLoginUrl), + GURL(GaiaAuthFetcher::kClientLoginUrl), chrome_browser_net::UrlInfo::EARLY_LOAD_MOTIVATED); netlib->RemoveNetworkManagerObserver(this); delete this; @@ -331,7 +373,7 @@ void LoginUtilsImpl::PrewarmAuthentication() { NetworkLibrary *network = CrosLibrary::Get()->GetNetworkLibrary(); if (network->Connected()) { chrome_browser_net::Preconnect::PreconnectOnUIThread( - GURL(GaiaAuthenticator2::kClientLoginUrl), + GURL(GaiaAuthFetcher::kClientLoginUrl), chrome_browser_net::UrlInfo::EARLY_LOAD_MOTIVATED); } else { new WarmingObserver(); diff --git a/chrome/browser/chromeos/login/network_screen_browsertest.cc b/chrome/browser/chromeos/login/network_screen_browsertest.cc index b45c02d..809f56c 100644 --- a/chrome/browser/chromeos/login/network_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/network_screen_browsertest.cc @@ -64,7 +64,7 @@ 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_, active_network()) - .Times(1) + .Times(AnyNumber()) .WillRepeatedly((Return((const Network*)(NULL)))) .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, ethernet_connected()) @@ -89,14 +89,26 @@ class NetworkScreenTest : public WizardInProcessBrowserTest { .Times(1) .WillRepeatedly((Return(true))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, ethernet_enabled()) + .Times(1) + .WillRepeatedly((Return(true))) + .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, wifi_available()) .Times(1) .WillRepeatedly((Return(false))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, wifi_enabled()) + .Times(1) + .WillRepeatedly((Return(true))) + .RetiresOnSaturation(); EXPECT_CALL(*mock_network_library_, cellular_available()) .Times(1) .WillRepeatedly((Return(false))) .RetiresOnSaturation(); + EXPECT_CALL(*mock_network_library_, cellular_enabled()) + .Times(1) + .WillRepeatedly((Return(true))) + .RetiresOnSaturation(); // Add a Connecting for prewarming auth url check. EXPECT_CALL(*mock_network_library_, Connecting()) diff --git a/chrome/browser/chromeos/login/network_selection_view.cc b/chrome/browser/chromeos/login/network_selection_view.cc index ec780f1..5280d8b 100644 --- a/chrome/browser/chromeos/login/network_selection_view.cc +++ b/chrome/browser/chromeos/login/network_selection_view.cc @@ -65,7 +65,7 @@ const int kControlPaddingRow = 15; const int kWelcomeTitleFontDelta = 5; // Fixed size for language/keyboard/network controls height. -const int kSelectionBoxHeight = 30; +const int kSelectionBoxHeight = 29; // Menu button is drawn using our custom icons in resources. See // TextButtonBorder::Paint() for details. So this offset compensate @@ -120,14 +120,14 @@ class NetworkControlReportOnActivate : public NetworkDropdownButton { }; // MenuButton with custom processing on focus events. -class NotifyingMenuButton : public views::MenuButton { +class NotifyingMenuButton : public DropDownButton { 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), + : DropDownButton(listener, text, menu_delegate, show_menu_marker), delegate_(delegate) {} // Overridden from View: @@ -305,7 +305,7 @@ void NetworkSelectionView::Init() { select_keyboard_label_ = new views::Label(); select_keyboard_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont)); - keyboards_menubutton_ = new views::MenuButton( + keyboards_menubutton_ = new DropDownButton( NULL /* listener */, L"", delegate_->keyboard_switch_menu(), true /* show_menu_marker */); InitMenuButtonProperties(keyboards_menubutton_); @@ -337,8 +337,7 @@ void NetworkSelectionView::UpdateLocalizedStrings() { delegate_->language_switch_menu()->GetCurrentLocaleName()); keyboards_menubutton_->SetText( delegate_->keyboard_switch_menu()->GetCurrentKeyboardName()); - welcome_label_->SetText(l10n_util::GetStringF(IDS_NETWORK_SELECTION_TITLE, - l10n_util::GetString(IDS_PRODUCT_OS_NAME))); + welcome_label_->SetText(l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE)); select_language_label_->SetText( l10n_util::GetString(IDS_LANGUAGE_SELECTION_SELECT)); select_keyboard_label_->SetText( diff --git a/chrome/browser/chromeos/login/network_selection_view.h b/chrome/browser/chromeos/login/network_selection_view.h index dfcc709..54626dd 100644 --- a/chrome/browser/chromeos/login/network_selection_view.h +++ b/chrome/browser/chromeos/login/network_selection_view.h @@ -9,7 +9,7 @@ #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 "chrome/browser/chromeos/views/dropdown_button.h" #include "views/controls/link.h" #include "views/view.h" #include "views/widget/widget_gtk.h" @@ -105,8 +105,8 @@ class NetworkSelectionView : public views::View, views::View* contents_view_; // Screen controls. - views::MenuButton* languages_menubutton_; - views::MenuButton* keyboards_menubutton_; + DropDownButton* languages_menubutton_; + DropDownButton* keyboards_menubutton_; views::Label* welcome_label_; views::Label* select_language_label_; views::Label* select_keyboard_label_; diff --git a/chrome/browser/chromeos/login/new_user_view.cc b/chrome/browser/chromeos/login/new_user_view.cc index 62b63e5..a20ea7f 100644 --- a/chrome/browser/chromeos/login/new_user_view.cc +++ b/chrome/browser/chromeos/login/new_user_view.cc @@ -20,17 +20,16 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/chromeos/cros/cros_library.h" -#include "chrome/browser/chromeos/cros_settings_provider_user.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/rounded_rect_painter.h" #include "chrome/browser/chromeos/login/textfield_with_margin.h" #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" +#include "chrome/browser/chromeos/views/copy_background.h" #include "gfx/font.h" #include "grit/app_resources.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" -#include "views/background.h" -#include "views/controls/button/native_button.h" #include "views/controls/label.h" #include "views/controls/throbber.h" #include "views/widget/widget_gtk.h" @@ -56,16 +55,6 @@ const SkColor kSplitterDown1Color = 0xFFE3E6E8; const SkColor kSplitterDown2Color = 0xFFEAEDEE; const char kDefaultDomain[] = "@gmail.com"; -// Colors for gradient background of textfields. These should be consistent -// with border window background so textfield border is not visible to the -// user. The background is needed for username and password textfield to -// imitate its borders transparency correctly. -const SkColor kUsernameBackgroundColorTop = SkColorSetRGB(229, 232, 233); -const SkColor kUsernameBackgroundColorBottom = SkColorSetRGB(226, 229, 230); -const SkColor kPasswordBackgroundColorTop = SkColorSetRGB(224, 227, 229); -const SkColor kPasswordBackgroundColorBottom = SkColorSetRGB(221, 224, 226); - - // Textfield that adds domain to the entered username if focus is lost and // username doesn't have full domain. class UsernameField : public chromeos::TextfieldWithMargin { @@ -163,17 +152,12 @@ void NewUserView::Init() { username_field_ = new UsernameField(); CorrectTextfieldFontSize(username_field_); - username_field_->set_background( - views::Background::CreateVerticalGradientBackground( - kUsernameBackgroundColorTop, - kUsernameBackgroundColorBottom)); + username_field_->set_background(new CopyBackground(this)); AddChildView(username_field_); password_field_ = new TextfieldWithMargin(views::Textfield::STYLE_PASSWORD); CorrectTextfieldFontSize(password_field_); - password_field_->set_background( - views::Background::CreateVerticalGradientBackground( - kPasswordBackgroundColorTop, kPasswordBackgroundColorBottom)); + password_field_->set_background(new CopyBackground(this)); AddChildView(password_field_); throbber_ = CreateDefaultSmoothedThrobber(); @@ -242,8 +226,7 @@ void NewUserView::RecreatePeculiarControls() { // 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()); - CorrectNativeButtonFontSize(sign_in_button_); + sign_in_button_ = new login::WideButton(this, std::wstring()); UpdateSignInButtonState(); if (!CrosLibrary::Get()->EnsureLoaded()) @@ -282,8 +265,7 @@ void NewUserView::AddChildView(View* view) { } void NewUserView::UpdateLocalizedStrings() { - title_label_->SetText(l10n_util::GetStringF( - IDS_LOGIN_TITLE, l10n_util::GetString(IDS_PRODUCT_OS_NAME))); + title_label_->SetText(l10n_util::GetString(IDS_LOGIN_TITLE)); 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)); @@ -438,9 +420,7 @@ void NewUserView::Layout() { y += setViewBounds(password_field_, x, y, width, true) + kRowPad; int throbber_y = y; - int sign_in_button_width = - std::max(login::kButtonMinWidth, - sign_in_button_->GetPreferredSize().width()); + int sign_in_button_width = sign_in_button_->GetPreferredSize().width(); setViewBounds(sign_in_button_, x, y, sign_in_button_width,true); setViewBounds(throbber_, x + width - throbber_->GetPreferredSize().width(), diff --git a/chrome/browser/chromeos/login/new_user_view.h b/chrome/browser/chromeos/login/new_user_view.h index face22b..7b40461 100644 --- a/chrome/browser/chromeos/login/new_user_view.h +++ b/chrome/browser/chromeos/login/new_user_view.h @@ -8,6 +8,7 @@ #include +#include "base/task.h" #include "chrome/browser/chromeos/login/language_switch_menu.h" #include "views/accelerator.h" #include "views/controls/button/button.h" diff --git a/chrome/browser/chromeos/login/online_attempt.cc b/chrome/browser/chromeos/login/online_attempt.cc index 14a24c3..597e3e3 100644 --- a/chrome/browser/chromeos/login/online_attempt.cc +++ b/chrome/browser/chromeos/login/online_attempt.cc @@ -14,9 +14,9 @@ #include "chrome/browser/chromeos/login/auth_attempt_state_resolver.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" -#include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" +#include "chrome/common/net/gaia/gaia_constants.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/url_request/url_request_status.h" @@ -45,9 +45,9 @@ OnlineAttempt::~OnlineAttempt() { void OnlineAttempt::Initiate(Profile* profile) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); gaia_authenticator_.reset( - new GaiaAuthenticator2(this, - GaiaConstants::kChromeOSSource, - profile->GetRequestContext())); + new GaiaAuthFetcher(this, + GaiaConstants::kChromeOSSource, + profile->GetRequestContext())); TryClientLogin(); } @@ -60,6 +60,19 @@ void OnlineAttempt::OnClientLoginSuccess( fetch_canceler_ = NULL; } + if (attempt_->hosted_policy() == GaiaAuthFetcher::HostedAccountsAllowed && + attempt_->is_first_time_user()) { + // First time user, and we don't know if the account is HOSTED or not. + // Since we don't allow HOSTED accounts to log in, we need to try + // again, without allowing HOSTED accounts. + // + // NOTE: we used to do this in the opposite order, so that we'd only + // try the HOSTED pathway if GOOGLE-only failed. This breaks CAPTCHA + // handling, though. + attempt_->DisableHosted(); + TryClientLogin(); + return; + } TriggerResolve(credentials, LoginFailure::None()); } @@ -73,6 +86,7 @@ void OnlineAttempt::OnClientLoginFailure( if (error.state() == GoogleServiceAuthError::REQUEST_CANCELED) { if (try_again_) { try_again_ = false; + // TODO(cmasone): add UMA tracking for this to see if we can remove it. LOG(ERROR) << "Login attempt canceled!?!? Trying again."; TryClientLogin(); return; @@ -80,6 +94,20 @@ void OnlineAttempt::OnClientLoginFailure( LOG(ERROR) << "Login attempt canceled again? Already retried..."; } + if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS && + attempt_->is_first_time_user() && + attempt_->hosted_policy() != GaiaAuthFetcher::HostedAccountsAllowed) { + // This was a first-time login, we already tried allowing HOSTED accounts + // and succeeded. That we've failed with INVALID_GAIA_CREDENTIALS now + // indicates that the account is HOSTED. + LOG(WARNING) << "Rejecting valid HOSTED account."; + TriggerResolve(GaiaAuthConsumer::ClientLoginResult(), + LoginFailure::FromNetworkAuthFailure( + GoogleServiceAuthError( + GoogleServiceAuthError::HOSTED_NOT_ALLOWED))); + return; + } + if (error.state() == GoogleServiceAuthError::TWO_FACTOR) { LOG(WARNING) << "Two factor authenticated. Sync will not work."; TriggerResolve(GaiaAuthConsumer::ClientLoginResult(), @@ -104,7 +132,7 @@ void OnlineAttempt::TryClientLogin() { GaiaConstants::kContactsService, attempt_->login_token, attempt_->login_captcha, - GaiaAuthenticator2::HostedAccountsAllowed); + attempt_->hosted_policy()); } void OnlineAttempt::CancelClientLogin() { diff --git a/chrome/browser/chromeos/login/online_attempt.h b/chrome/browser/chromeos/login/online_attempt.h index fccc842..ed1b447 100644 --- a/chrome/browser/chromeos/login/online_attempt.h +++ b/chrome/browser/chromeos/login/online_attempt.h @@ -16,7 +16,7 @@ #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/common/net/gaia/google_service_auth_error.h" -class GaiaAuthenticator2; +class GaiaAuthFetcher; class Profile; namespace chromeos { @@ -36,7 +36,7 @@ class OnlineAttempt // IO thread when useful state is available. void Initiate(Profile* profile); - // Callbacks from GaiaAuthenticator2 + // Callbacks from GaiaAuthFetcher virtual void OnClientLoginFailure( const GoogleServiceAuthError& error); virtual void OnClientLoginSuccess( @@ -56,7 +56,7 @@ class OnlineAttempt AuthAttemptStateResolver* const resolver_; // Handles all net communications with Gaia. - scoped_ptr gaia_authenticator_; + scoped_ptr gaia_authenticator_; CancelableTask* fetch_canceler_; // Whether we're willing to re-try the ClientLogin attempt. diff --git a/chrome/browser/chromeos/login/online_attempt_unittest.cc b/chrome/browser/chromeos/login/online_attempt_unittest.cc index 76889bf..5ab89c2 100644 --- a/chrome/browser/chromeos/login/online_attempt_unittest.cc +++ b/chrome/browser/chromeos/login/online_attempt_unittest.cc @@ -14,7 +14,7 @@ #include "chrome/browser/chromeos/login/mock_url_fetchers.h" #include "chrome/browser/chromeos/login/test_attempt_state.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" #include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" #include "testing/gmock/include/gmock/gmock.h" @@ -33,7 +33,7 @@ class OnlineAttemptTest : public ::testing::Test { : message_loop_(MessageLoop::TYPE_UI), ui_thread_(BrowserThread::UI, &message_loop_), io_thread_(BrowserThread::IO), - state_("", "", "", "", ""), + state_("", "", "", "", "", false), resolver_(new MockAuthAttemptStateResolver) { } @@ -91,7 +91,7 @@ class OnlineAttemptTest : public ::testing::Test { BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask()); } - static void RunCancelTest(OnlineAttempt* attempt, Profile* profile) { + static void RunThreadTest(OnlineAttempt* attempt, Profile* profile) { attempt->Initiate(profile); MessageLoop::current()->RunAllPending(); } @@ -136,7 +136,7 @@ TEST_F(OnlineAttemptTest, LoginCancelRetry) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - NewRunnableFunction(&OnlineAttemptTest::RunCancelTest, + NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, attempt_.get(), &profile)); MessageLoop::current()->Run(); @@ -163,7 +163,7 @@ TEST_F(OnlineAttemptTest, LoginTimeout) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - NewRunnableFunction(&OnlineAttemptTest::RunCancelTest, + NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, attempt_.get(), &profile)); // Post a task to cancel the login attempt. @@ -175,6 +175,60 @@ TEST_F(OnlineAttemptTest, LoginTimeout) { URLFetcher::set_factory(NULL); } +TEST_F(OnlineAttemptTest, HostedLoginRejected) { + LoginFailure error( + LoginFailure::FromNetworkAuthFailure( + GoogleServiceAuthError( + GoogleServiceAuthError::HOSTED_NOT_ALLOWED))); + TestingProfile profile; + + EXPECT_CALL(*(resolver_.get()), Resolve()) + .WillOnce(Invoke(OnlineAttemptTest::Quit)) + .RetiresOnSaturation(); + + // This is how we inject fake URLFetcher objects, with a factory. + MockFactory factory; + URLFetcher::set_factory(&factory); + + TestAttemptState local_state("", "", "", "", "", true); + attempt_ = new OnlineAttempt(&local_state, resolver_.get()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, + attempt_.get(), &profile)); + + MessageLoop::current()->Run(); + + EXPECT_EQ(error, local_state.online_outcome()); + EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED, + local_state.online_outcome().reason()); + URLFetcher::set_factory(NULL); +} + +TEST_F(OnlineAttemptTest, FullLogin) { + TestingProfile profile; + + EXPECT_CALL(*(resolver_.get()), Resolve()) + .WillOnce(Invoke(OnlineAttemptTest::Quit)) + .RetiresOnSaturation(); + + // This is how we inject fake URLFetcher objects, with a factory. + MockFactory factory; + URLFetcher::set_factory(&factory); + + TestAttemptState local_state("", "", "", "", "", true); + attempt_ = new OnlineAttempt(&local_state, resolver_.get()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, + attempt_.get(), &profile)); + + MessageLoop::current()->Run(); + + EXPECT_EQ(LoginFailure::None(), local_state.online_outcome()); + URLFetcher::set_factory(NULL); +} + TEST_F(OnlineAttemptTest, LoginNetFailure) { RunFailureTest( GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); diff --git a/chrome/browser/chromeos/login/owner_manager.cc b/chrome/browser/chromeos/login/owner_manager.cc index b2715f3..71b15a8 100644 --- a/chrome/browser/chromeos/login/owner_manager.cc +++ b/chrome/browser/chromeos/login/owner_manager.cc @@ -11,6 +11,7 @@ #include "base/file_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/chromeos/boot_times_loader.h" #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" @@ -26,6 +27,7 @@ OwnerManager::OwnerManager() OwnerManager::~OwnerManager() {} void OwnerManager::LoadOwnerKey() { + BootTimesLoader::Get()->AddLoginTimeMarker("LoadOwnerKeyStart", false); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); VLOG(1) << "Loading owner key"; NotificationType result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED; @@ -81,6 +83,7 @@ void OwnerManager::ExportKey() { NotificationType::OWNER_KEY_FETCH_ATTEMPT_FAILED, NotificationService::NoDetails())); } + BootTimesLoader::Get()->AddLoginTimeMarker("ExportKeyEnd", false); } void OwnerManager::OnComplete(bool value) { @@ -126,6 +129,7 @@ bool OwnerManager::EnsurePrivateKey() { void OwnerManager::Sign(const BrowserThread::ID thread_id, const std::string& data, Delegate* d) { + BootTimesLoader::Get()->AddLoginTimeMarker("SignStart", false); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); // If it's not the case that we can get both keys... @@ -135,6 +139,7 @@ void OwnerManager::Sign(const BrowserThread::ID thread_id, NewRunnableMethod(this, &OwnerManager::CallDelegate, d, KEY_UNAVAILABLE, std::vector())); + BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false); return; } @@ -150,12 +155,14 @@ void OwnerManager::Sign(const BrowserThread::ID thread_id, NewRunnableMethod(this, &OwnerManager::CallDelegate, d, return_code, signature)); + BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false); } void OwnerManager::Verify(const BrowserThread::ID thread_id, const std::string& data, const std::vector& signature, Delegate* d) { + BootTimesLoader::Get()->AddLoginTimeMarker("VerifyStart", false); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (!EnsurePublicKey()) { @@ -164,6 +171,7 @@ void OwnerManager::Verify(const BrowserThread::ID thread_id, NewRunnableMethod(this, &OwnerManager::CallDelegate, d, KEY_UNAVAILABLE, std::vector())); + BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false); return; } @@ -177,6 +185,7 @@ void OwnerManager::Verify(const BrowserThread::ID thread_id, NewRunnableMethod(this, &OwnerManager::CallDelegate, d, return_code, std::vector())); + BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false); } void OwnerManager::SendNotification(NotificationType type, diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc index 0eaa340..ec499fb 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator.cc +++ b/chrome/browser/chromeos/login/parallel_authenticator.cc @@ -23,10 +23,11 @@ #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/chromeos/login/user_manager.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_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/notification_service.h" #include "net/base/load_flags.h" @@ -71,12 +72,14 @@ bool ParallelAuthenticator::AuthenticateToLogin( const std::string& password, const std::string& login_token, const std::string& login_captcha) { + std::string canonicalized = Authenticator::Canonicalize(username); current_state_.reset( - new AuthAttemptState(Authenticator::Canonicalize(username), + new AuthAttemptState(canonicalized, password, HashPassword(password), login_token, - login_captcha)); + login_captcha, + !UserManager::Get()->IsKnownUser(canonicalized))); mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), this, false /* don't create */); @@ -118,7 +121,7 @@ bool ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, } void ParallelAuthenticator::LoginOffTheRecord() { - current_state_.reset(new AuthAttemptState("", "", "", "", "")); + current_state_.reset(new AuthAttemptState("", "", "", "", "", false)); guest_mounter_ = CryptohomeOp::CreateMountGuestAttempt(current_state_.get(), this); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -256,7 +259,8 @@ void ParallelAuthenticator::RetryAuth(Profile* profile, password, HashPassword(password), login_token, - login_captcha)); + login_captcha, + false /* not a new user */)); current_online_ = new OnlineAttempt(reauth_state_.get(), this); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -353,8 +357,8 @@ void ParallelAuthenticator::Resolve() { key_migrator_ = CryptohomeOp::CreateMigrateAttempt(reauth_state_.get(), this, - false, - reauth_state_->ascii_hash); + true, + current_state_->ascii_hash); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, NewRunnableMethod(key_migrator_.get(), &CryptohomeOp::Initiate)); diff --git a/chrome/browser/chromeos/login/parallel_authenticator.h b/chrome/browser/chromeos/login/parallel_authenticator.h index 2fafdcf..997f252 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator.h +++ b/chrome/browser/chromeos/login/parallel_authenticator.h @@ -23,7 +23,7 @@ #include "chrome/browser/chromeos/login/online_attempt.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -class GaiaAuthenticator2; +class GaiaAuthFetcher; class Lock; class LoginFailure; class Profile; @@ -97,6 +97,10 @@ class ParallelAuthenticator : public Authenticator, // Optionally could pass CAPTCHA challenge token - |login_token| and // |login_captcha| string that user has entered. // + // NOTE: We do not allow HOSTED accounts to log in. In the event that + // we are asked to authenticate valid HOSTED account creds, we will + // call OnLoginFailure() with HOSTED_NOT_ALLOWED. + // // Returns true if the attempt gets sent successfully and false if not. bool AuthenticateToLogin(Profile* profile, const std::string& username, @@ -230,7 +234,7 @@ class ParallelAuthenticator : public Authenticator, static const int kLocalaccountRetryIntervalMs; // Handles all net communications with Gaia. - scoped_ptr gaia_authenticator_; + scoped_ptr gaia_authenticator_; // Used when we need to try online authentication again, after successful // mount, but failed online login. diff --git a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc index 0cac5f7..f6200d7 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/parallel_authenticator_unittest.cc @@ -22,7 +22,7 @@ #include "chrome/browser/chromeos/login/mock_url_fetchers.h" #include "chrome/browser/chromeos/login/test_attempt_state.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" #include "chrome/common/net/url_fetcher.h" #include "chrome/test/testing_profile.h" #include "chrome/test/thread_test_helper.h" @@ -101,7 +101,8 @@ class ParallelAuthenticatorTest : public ::testing::Test { password_, hash_ascii_, "", - "")); + "", + false)); } // Tears down the test fixture. @@ -534,7 +535,10 @@ TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetNewPassword) { // Set up mock cryptohome library to respond successfully to a key migration. mock_library_->SetUp(true, 0); - EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, _, _, _)) + EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, + state_->ascii_hash, + _, + _)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*mock_library_, GetSystemSalt()) diff --git a/chrome/browser/chromeos/login/password_changed_view.cc b/chrome/browser/chromeos/login/password_changed_view.cc index 87c89d5..22f953f 100644 --- a/chrome/browser/chromeos/login/password_changed_view.cc +++ b/chrome/browser/chromeos/login/password_changed_view.cc @@ -30,13 +30,15 @@ namespace { const int kPasswordFieldWidthChars = 20; } // namespace -PasswordChangedView::PasswordChangedView(Delegate* delegate) +PasswordChangedView::PasswordChangedView(Delegate* delegate, + bool full_sync_disabled) : title_label_(NULL), description_label_(NULL), full_sync_radio_(NULL), delta_sync_radio_(NULL), old_password_field_(NULL), - delegate_(delegate) { + delegate_(delegate), + full_sync_disabled_(full_sync_disabled) { } bool PasswordChangedView::Accept() { @@ -47,6 +49,15 @@ int PasswordChangedView::GetDialogButtons() const { return MessageBoxFlags::DIALOGBUTTON_OK; } +views::View* PasswordChangedView::GetInitiallyFocusedView() { + if (!full_sync_disabled_) { + return views::DialogDelegate::GetInitiallyFocusedView(); + } else { + DCHECK(old_password_field_); + return old_password_field_; + } +} + std::wstring PasswordChangedView::GetWindowTitle() const { return l10n_util::GetString(IDS_LOGIN_PASSWORD_CHANGED_DIALOG_BOX_TITLE); } @@ -87,7 +98,6 @@ void PasswordChangedView::Init() { full_sync_radio_ = new RadioButton( l10n_util::GetString(IDS_LOGIN_PASSWORD_CHANGED_RESET), 0); full_sync_radio_->set_listener(this); - full_sync_radio_->SetChecked(true); full_sync_radio_->SetMultiLine(true); delta_sync_radio_ = new RadioButton( @@ -136,7 +146,17 @@ void PasswordChangedView::Init() { layout->StartRow(0, 0); layout->AddView(old_password_field_); - old_password_field_->SetEnabled(false); + + // Disable options if needed. + if (!full_sync_disabled_) { + full_sync_radio_->SetChecked(true); + old_password_field_->SetEnabled(false); + } else { + full_sync_radio_->SetEnabled(false); + delta_sync_radio_->SetChecked(true); + old_password_field_->SetEnabled(true); + } + } bool PasswordChangedView::ExitDialog() { @@ -173,9 +193,4 @@ bool PasswordChangedView::HandleKeystroke(views::Textfield* s, return false; } -void PasswordChangedView::SelectDeltaSyncOption() { - if (!delta_sync_radio_->checked()) - delta_sync_radio_->SetChecked(true); -} - } // namespace chromeos diff --git a/chrome/browser/chromeos/login/password_changed_view.h b/chrome/browser/chromeos/login/password_changed_view.h index 48f6ca3..b7d45da 100644 --- a/chrome/browser/chromeos/login/password_changed_view.h +++ b/chrome/browser/chromeos/login/password_changed_view.h @@ -42,7 +42,7 @@ class PasswordChangedView : public views::View, virtual void ResyncEncryptedData() = 0; }; - explicit PasswordChangedView(Delegate* delegate); + PasswordChangedView(Delegate* delegate, bool full_sync_disabled); virtual ~PasswordChangedView() {} // views::DialogDelegate overrides: @@ -50,6 +50,7 @@ class PasswordChangedView : public views::View, virtual int GetDialogButtons() const; // views::WindowDelegate overrides: + virtual View* GetInitiallyFocusedView(); virtual bool IsModal() const { return true; } virtual views::View* GetContentsView() { return this; } @@ -66,9 +67,6 @@ class PasswordChangedView : public views::View, virtual void ContentsChanged(views::Textfield* sender, const string16& new_contents) {} - // Selects delta sync radio button. - void SelectDeltaSyncOption(); - protected: // views::View overrides: virtual gfx::Size GetPreferredSize(); @@ -93,6 +91,9 @@ class PasswordChangedView : public views::View, // Notifications receiver. Delegate* delegate_; + // Whether full sync option is disabled. + bool full_sync_disabled_; + DISALLOW_COPY_AND_ASSIGN(PasswordChangedView); }; diff --git a/chrome/browser/chromeos/login/screen_lock_view.cc b/chrome/browser/chromeos/login/screen_lock_view.cc index 92c5400..b8af63a 100644 --- a/chrome/browser/chromeos/login/screen_lock_view.cc +++ b/chrome/browser/chromeos/login/screen_lock_view.cc @@ -14,6 +14,8 @@ #include "chrome/browser/chromeos/login/user_view.h" #include "chrome/browser/chromeos/login/username_view.h" #include "chrome/browser/chromeos/login/wizard_accessibility_helper.h" +#include "chrome/browser/chromeos/login/textfield_with_margin.h" +#include "chrome/browser/chromeos/views/copy_background.h" #include "chrome/browser/profile_manager.h" #include "chrome/common/notification_service.h" #include "grit/generated_resources.h" @@ -33,10 +35,10 @@ 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. -class PasswordField : public views::Textfield { +class PasswordField : public TextfieldWithMargin { public: PasswordField() - : views::Textfield(views::Textfield::STYLE_PASSWORD) { + : TextfieldWithMargin(views::Textfield::STYLE_PASSWORD) { set_text_to_display_when_empty( l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT)); } @@ -70,7 +72,7 @@ gfx::Size ScreenLockView::GetPreferredSize() { } void ScreenLockView::Layout() { - int username_height = username_->GetPreferredSize().height(); + int username_height = login::kSelectedLabelHeight; main_->SetBounds(0, 0, width(), height()); username_->SetBounds( kBorderSize, @@ -99,6 +101,7 @@ void ScreenLockView::Init() { // Password field. password_field_ = new PasswordField(); password_field_->SetController(this); + password_field_->set_background(new CopyBackground(main_)); // User icon. UserManager::User user = screen_locker_->user(); @@ -108,8 +111,7 @@ void ScreenLockView::Init() { std::wstring text = UTF8ToWide(user.GetDisplayName()); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - const gfx::Font& font = - rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD); + const gfx::Font& font = rb.GetFont(ResourceBundle::MediumBoldFont); // Layouts image, textfield and button components. GridLayout* layout = new GridLayout(main_); @@ -138,6 +140,7 @@ void ScreenLockView::Init() { UsernameView* username = new UsernameView(text); username_ = username; + username->SetColor(login::kTextColor); username->SetFont(font); AddChildView(username); } diff --git a/chrome/browser/chromeos/login/screen_lock_view.h b/chrome/browser/chromeos/login/screen_lock_view.h index 70b2e6a..9ceefd1 100644 --- a/chrome/browser/chromeos/login/screen_lock_view.h +++ b/chrome/browser/chromeos/login/screen_lock_view.h @@ -87,7 +87,7 @@ class ScreenLockView : public views::View, // User's picture, signout button and password field. views::View* main_; - // Username thaty overlays on top of user's picture. + // Username that overlays on top of user's picture. views::View* username_; DISALLOW_COPY_AND_ASSIGN(ScreenLockView); diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index 7b4d6b5..2d8ccd0 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -16,7 +16,6 @@ #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_thread.h" #include "chrome/browser/browser_window.h" @@ -34,6 +33,7 @@ #include "chrome/browser/chromeos/system_key_event_listener.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "cros/chromeos_wm_ipc_enums.h" @@ -45,11 +45,16 @@ #include "views/widget/widget_gtk.h" namespace { -// The maxium times that the screen locker should try to grab input, -// and its interval. It has to be able to grab all inputs in 30 seconds, -// otherwise chromium process fails and the session is terminated. + +// The maximum duration for which locker should try to grab the keyboard and +// mouse and its interval for regrabbing on failure. +const int kMaxGrabFailureSec = 30; const int64 kRetryGrabIntervalMs = 500; -const int kGrabFailureLimit = 60; + +// Maximum number of times we'll try to grab the keyboard and mouse before +// giving up. If we hit the limit, Chrome exits and the session is terminated. +const int kMaxGrabFailures = kMaxGrabFailureSec * 1000 / kRetryGrabIntervalMs; + // Each keyboard layout has a dummy input method ID which starts with "xkb:". const char kValidInputMethodPrefix[] = "xkb:"; @@ -176,12 +181,12 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer, DISALLOW_COPY_AND_ASSIGN(ScreenLockObserver); }; -// A ScreenLock window that covers entire screen to keeps the keyboard +// A ScreenLock window that covers entire screen to keep the keyboard // focus/events inside the grab widget. class LockWindow : public views::WidgetGtk { public: LockWindow() - : WidgetGtk(views::WidgetGtk::TYPE_WINDOW), + : views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW), toplevel_focus_widget_(NULL) { EnableDoubleBuffer(true); } @@ -267,8 +272,6 @@ class GrabWidget : public views::WidgetGtk { virtual void Show() { views::WidgetGtk::Show(); - // Now steal all inputs. - TryGrabAllInputs(); } void ClearGrab() { @@ -338,9 +341,10 @@ void GrabWidget::TryGrabAllInputs() { } if ((kbd_grab_status_ != GDK_GRAB_SUCCESS || mouse_grab_status_ != GDK_GRAB_SUCCESS) && - grab_failure_count_++ < kGrabFailureLimit) { - LOG(WARNING) << "Failed to grab inputs. Trying again in 1 second: kbd=" - << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; + grab_failure_count_++ < kMaxGrabFailures) { + LOG(WARNING) << "Failed to grab inputs. Trying again in " + << kRetryGrabIntervalMs << " ms: kbd=" + << kbd_grab_status_ << ", mouse=" << mouse_grab_status_; MessageLoop::current()->PostDelayedTask( FROM_HERE, task_factory_.NewRunnableMethod(&GrabWidget::TryGrabAllInputs), @@ -575,14 +579,18 @@ void ScreenLocker::Init() { MessageLoopForUI::current()->AddObserver(input_event_observer_.get()); } - lock_widget_ = new GrabWidget(this); + // Hang on to a cast version of the grab widget so we can call its + // TryGrabAllInputs() method later. (Nobody else needs to use it, so moving + // its declaration to the header instead of keeping it in an anonymous + // namespace feels a bit ugly.) + GrabWidget* cast_lock_widget = new GrabWidget(this); + lock_widget_ = cast_lock_widget; lock_widget_->MakeTransparent(); lock_widget_->InitWithWidget(lock_window_, gfx::Rect()); if (screen_lock_view_) { lock_widget_->SetContentsView( new GrabWidgetRootView(screen_lock_view_)); } - lock_widget_->Show(); // Configuring the background url. @@ -604,6 +612,18 @@ void ScreenLocker::Init() { lock_window_->SetContentsView(background_view_); lock_window_->Show(); + cast_lock_widget->TryGrabAllInputs(); + + // Add the window to its own group so that its grab won't be stolen if + // gtk_grab_add() gets called on behalf on a non-screen-locker widget (e.g. + // a modal dialog) -- see http://crosbug.com/8999. We intentionally do this + // after calling TryGrabAllInputs(), as want to be in the default window group + // then so we can break any existing GTK grabs. + GtkWindowGroup* window_group = gtk_window_group_new(); + gtk_window_group_add_window(window_group, + GTK_WINDOW(lock_window_->GetNativeView())); + g_object_unref(window_group); + // Don't let X draw default background, which was causing flash on // resume. gdk_window_set_back_pixmap(lock_window_->GetNativeView()->window, diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h index a4a40e7..853c40f 100644 --- a/chrome/browser/chromeos/login/screen_locker.h +++ b/chrome/browser/chromeos/login/screen_locker.h @@ -185,7 +185,7 @@ class ScreenLocker : public LoginStatusConsumer, // The time when the screen locker object is created. base::Time start_time_; - // The time when the authenticaton is started. + // The time when the authentication is started. base::Time authentication_start_time_; DISALLOW_COPY_AND_ASSIGN(ScreenLocker); diff --git a/chrome/browser/chromeos/login/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/screen_locker_browsertest.cc index df82083..321e0c8 100644 --- a/chrome/browser/chromeos/login/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/screen_locker_browsertest.cc @@ -6,7 +6,6 @@ #include "base/message_loop.h" #include "base/scoped_ptr.h" #include "chrome/browser/automation/ui_controls.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" @@ -16,6 +15,7 @@ #include "chrome/browser/chromeos/login/screen_locker.h" #include "chrome/browser/chromeos/login/screen_locker_tester.h" #include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/browser_dialogs.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" @@ -32,7 +32,8 @@ namespace { class Waiter : public NotificationObserver { public: explicit Waiter(Browser* browser) - : browser_(browser) { + : browser_(browser), + running_(false) { registrar_.Add(this, NotificationType::SCREEN_LOCK_STATE_CHANGED, NotificationService::AllSources()); @@ -53,11 +54,13 @@ class Waiter : public NotificationObserver { const NotificationSource& source, const NotificationDetails& details) { DCHECK(type == NotificationType::SCREEN_LOCK_STATE_CHANGED); - MessageLoop::current()->Quit(); + if (running_) + MessageLoop::current()->Quit(); } // Wait until the two conditions are met. void Wait(bool locker_state, bool fullscreen) { + running_ = true; scoped_ptr tester(chromeos::ScreenLocker::GetTester()); while (tester->IsLocked() != locker_state || @@ -66,6 +69,7 @@ class Waiter : public NotificationObserver { } // Make sure all pending tasks are executed. ui_test_utils::RunAllPendingInMessageLoop(); + running_ = false; } CHROMEGTK_CALLBACK_1(Waiter, gboolean, OnWindowStateEvent, @@ -76,6 +80,9 @@ class Waiter : public NotificationObserver { gulong handler_id_; NotificationRegistrar registrar_; + // Are we currently running the message loop? + bool running_; + DISALLOW_COPY_AND_ASSIGN(Waiter); }; @@ -112,8 +119,9 @@ class ScreenLockerTest : public CrosInProcessBrowserTest { ScreenLocker::Show(); scoped_ptr tester(ScreenLocker::GetTester()); tester->EmulateWindowManagerReady(); - ui_test_utils::WaitForNotification( - NotificationType::SCREEN_LOCK_STATE_CHANGED); + if (!chromeos::ScreenLocker::GetTester()->IsLocked()) + ui_test_utils::WaitForNotification( + NotificationType::SCREEN_LOCK_STATE_CHANGED); EXPECT_TRUE(tester->IsLocked()); tester->InjectMockAuthenticator("", ""); @@ -154,7 +162,8 @@ class ScreenLockerTest : public CrosInProcessBrowserTest { DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest); }; -IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) { +// PulseAudioMixer sometimes crashes at exit. See http://crosbug.om/9303 +IN_PROC_BROWSER_TEST_F(ScreenLockerTest, FLAKY_TestBasic) { EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods()) .Times(1) .WillRepeatedly((testing::Return(0))) @@ -169,8 +178,9 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) { ScreenLocker::Show(); scoped_ptr tester(ScreenLocker::GetTester()); tester->EmulateWindowManagerReady(); - ui_test_utils::WaitForNotification( - NotificationType::SCREEN_LOCK_STATE_CHANGED); + if (!chromeos::ScreenLocker::GetTester()->IsLocked()) + 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 @@ -263,8 +273,9 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestShowTwice) { ScreenLocker::Show(); scoped_ptr tester(ScreenLocker::GetTester()); tester->EmulateWindowManagerReady(); - ui_test_utils::WaitForNotification( - NotificationType::SCREEN_LOCK_STATE_CHANGED); + if (!chromeos::ScreenLocker::GetTester()->IsLocked()) + ui_test_utils::WaitForNotification( + NotificationType::SCREEN_LOCK_STATE_CHANGED); EXPECT_TRUE(tester->IsLocked()); // Calling Show again simply send LockCompleted signal. diff --git a/chrome/browser/chromeos/login/test_attempt_state.cc b/chrome/browser/chromeos/login/test_attempt_state.cc index 07a5260..b9a00b7 100644 --- a/chrome/browser/chromeos/login/test_attempt_state.cc +++ b/chrome/browser/chromeos/login/test_attempt_state.cc @@ -15,12 +15,14 @@ TestAttemptState::TestAttemptState(const std::string& username, const std::string& password, const std::string& ascii_hash, const std::string& login_token, - const std::string& login_captcha) + const std::string& login_captcha, + const bool user_is_new) : AuthAttemptState(username, password, ascii_hash, login_token, - login_captcha) { + login_captcha, + user_is_new) { } TestAttemptState::TestAttemptState(const std::string& username, @@ -38,6 +40,10 @@ void TestAttemptState::PresetOnlineLoginStatus( credentials_ = credentials; } +void TestAttemptState::DisableHosted() { + hosted_policy_ = GaiaAuthFetcher::HostedAccountsNotAllowed; +} + void TestAttemptState::PresetCryptohomeStatus(bool cryptohome_outcome, int cryptohome_code) { cryptohome_complete_ = true; diff --git a/chrome/browser/chromeos/login/test_attempt_state.h b/chrome/browser/chromeos/login/test_attempt_state.h index dfce306..6d715be 100644 --- a/chrome/browser/chromeos/login/test_attempt_state.h +++ b/chrome/browser/chromeos/login/test_attempt_state.h @@ -20,7 +20,8 @@ class TestAttemptState : public AuthAttemptState { const std::string& password, const std::string& ascii_hash, const std::string& login_token, - const std::string& login_captcha); + const std::string& login_captcha, + const bool user_is_new); TestAttemptState(const std::string& username, const std::string& ascii_hash); @@ -31,18 +32,26 @@ class TestAttemptState : public AuthAttemptState { const GaiaAuthConsumer::ClientLoginResult& credentials, const LoginFailure& outcome); + // The next attempt will not allow HOSTED accounts to log in. + void DisableHosted(); + // Act as though an cryptohome login attempt completed already. void PresetCryptohomeStatus(bool cryptohome_outcome, int cryptohome_code); // To allow state to be queried on the main thread during tests. - bool online_complete() { return online_complete_; } - const LoginFailure& online_outcome() { return online_outcome_; } - const GaiaAuthConsumer::ClientLoginResult& credentials() { + virtual bool online_complete() { return online_complete_; } + virtual const LoginFailure& online_outcome() { return online_outcome_; } + virtual const GaiaAuthConsumer::ClientLoginResult& credentials() { return credentials_; } - bool cryptohome_complete() { return cryptohome_complete_; } - bool cryptohome_outcome() { return cryptohome_outcome_; } - int cryptohome_code() { return cryptohome_code_; } + virtual bool is_first_time_user() { return is_first_time_user_; } + virtual GaiaAuthFetcher::HostedAccountsSetting hosted_policy() { + return hosted_policy_; + } + + virtual bool cryptohome_complete() { return cryptohome_complete_; } + virtual bool cryptohome_outcome() { return cryptohome_outcome_; } + virtual int cryptohome_code() { return cryptohome_code_; } private: DISALLOW_COPY_AND_ASSIGN(TestAttemptState); diff --git a/chrome/browser/chromeos/login/update_screen.cc b/chrome/browser/chromeos/login/update_screen.cc index 6f58ac1..d33c706 100644 --- a/chrome/browser/chromeos/login/update_screen.cc +++ b/chrome/browser/chromeos/login/update_screen.cc @@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/login/update_screen.h" +#include "base/file_util.h" #include "base/logging.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/login/screen_observer.h" @@ -29,6 +30,8 @@ const int kDownloadProgressIncrement = 60; const int kUpdateScreenWidth = 580; const int kUpdateScreenHeight = 305; +const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline"; + } // anonymous namespace namespace chromeos { @@ -39,7 +42,9 @@ UpdateScreen::UpdateScreen(WizardScreenDelegate* delegate) kUpdateScreenHeight), checking_for_update_(true), maximal_curtain_time_(0), - reboot_check_delay_(0) { + reboot_check_delay_(0), + is_downloading_update_(false), + is_all_updates_critical_(false) { } UpdateScreen::~UpdateScreen() { @@ -62,10 +67,30 @@ void UpdateScreen::UpdateStatusChanged(UpdateLibrary* library) { break; case UPDATE_STATUS_UPDATE_AVAILABLE: view()->SetProgress(kBeforeDownloadProgress); - VLOG(1) << "Update available: " << library->status().new_version; + if (!HasCriticalUpdate()) { + VLOG(1) << "Noncritical update available: " + << library->status().new_version; + ExitUpdate(); + } else { + VLOG(1) << "Critical update available: " + << library->status().new_version; + } break; case UPDATE_STATUS_DOWNLOADING: { + if (!is_downloading_update_) { + // Because update engine doesn't send UPDATE_STATUS_UPDATE_AVAILABLE + // we need to is update critical on first downloading notification. + is_downloading_update_ = true; + if (!HasCriticalUpdate()) { + VLOG(1) << "Non-critical update available: " + << library->status().new_version; + ExitUpdate(); + } else { + VLOG(1) << "Critical update available: " + << library->status().new_version; + } + } view()->ShowCurtain(false); int download_progress = static_cast( library->status().download_progress * kDownloadProgressIncrement); @@ -82,12 +107,16 @@ void UpdateScreen::UpdateStatusChanged(UpdateLibrary* library) { // Make sure that first OOBE stage won't be shown after reboot. WizardController::MarkOobeCompleted(); view()->SetProgress(kProgressComplete); - view()->ShowCurtain(false); - CrosLibrary::Get()->GetUpdateLibrary()->RebootAfterUpdate(); - VLOG(1) << "Reboot API was called. Waiting for reboot."; - reboot_timer_.Start(base::TimeDelta::FromSeconds(reboot_check_delay_), - this, - &UpdateScreen::OnWaitForRebootTimeElapsed); + if (HasCriticalUpdate()) { + view()->ShowCurtain(false); + VLOG(1) << "Initiate reboot after update"; + CrosLibrary::Get()->GetUpdateLibrary()->RebootAfterUpdate(); + reboot_timer_.Start(base::TimeDelta::FromSeconds(reboot_check_delay_), + this, + &UpdateScreen::OnWaitForRebootTimeElapsed); + } else { + ExitUpdate(); + } break; case UPDATE_STATUS_IDLE: case UPDATE_STATUS_ERROR: @@ -104,6 +133,7 @@ void UpdateScreen::StartUpdate() { // Reset view. view()->Reset(); view()->set_controller(this); + is_downloading_update_ = false; // Start the maximal curtain time timer. if (maximal_curtain_time_ > 0) { @@ -121,7 +151,7 @@ void UpdateScreen::StartUpdate() { LOG(ERROR) << "Error loading CrosLibrary"; } else { CrosLibrary::Get()->GetUpdateLibrary()->AddObserver(this); - VLOG(1) << "Checking for update"; + VLOG(1) << "Initiate update check"; if (!CrosLibrary::Get()->GetUpdateLibrary()->CheckForUpdate()) { ExitUpdate(); } @@ -145,6 +175,12 @@ void UpdateScreen::ExitUpdate() { UpdateLibrary* update_library = CrosLibrary::Get()->GetUpdateLibrary(); update_library->RemoveObserver(this); switch (update_library->status().status) { + case UPDATE_STATUS_UPDATE_AVAILABLE: + case UPDATE_STATUS_UPDATED_NEED_REBOOT: + case UPDATE_STATUS_DOWNLOADING: + DCHECK(!HasCriticalUpdate()); + // Noncritical update, just exit screen as if there is no update. + // no break case UPDATE_STATUS_IDLE: observer->OnExit(ScreenObserver::UPDATE_NOUPDATE); break; @@ -182,4 +218,24 @@ void UpdateScreen::SetRebootCheckDelay(int seconds) { reboot_check_delay_ = seconds; } +bool UpdateScreen::HasCriticalUpdate() { + if (is_all_updates_critical_) + return true; + + std::string deadline; + FilePath update_deadline_file_path(kUpdateDeadlineFile); + if (!file_util::ReadFileToString(update_deadline_file_path, &deadline) || + deadline.empty()) { + return false; + } + + // TODO(dpolukhin): Analyze file content. Now we can just assume that + // if the file exists and not empty, there is critical update. + return true; +} + +void UpdateScreen::SetAllUpdatesCritical(bool is_critical) { + is_all_updates_critical_ = is_critical; +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/login/update_screen.h b/chrome/browser/chromeos/login/update_screen.h index 2253c2e..5741c5e 100644 --- a/chrome/browser/chromeos/login/update_screen.h +++ b/chrome/browser/chromeos/login/update_screen.h @@ -46,6 +46,14 @@ class UpdateScreen: public DefaultViewScreen, int reboot_check_delay() const { return reboot_check_delay_; } void SetRebootCheckDelay(int seconds); + // Returns true if there is critical system update that requires installation + // and immediate reboot. + bool HasCriticalUpdate(); + + // Set flag to treat all updates as critical (for test purpose mainly). + // Default value is false. + void SetAllUpdatesCritical(bool is_critical); + private: // Timer notification handlers. void OnMaximalCurtainTimeElapsed(); @@ -70,6 +78,12 @@ class UpdateScreen: public DefaultViewScreen, // reboot device manually. int reboot_check_delay_; + // Flag that is used to detect when update download has just started. + bool is_downloading_update_; + + // Is all updates critical? If true, update deadlines are ignored. + bool is_all_updates_critical_; + DISALLOW_COPY_AND_ASSIGN(UpdateScreen); }; diff --git a/chrome/browser/chromeos/login/update_screen_browsertest.cc b/chrome/browser/chromeos/login/update_screen_browsertest.cc index ebf09dd..02f4eb9 100644 --- a/chrome/browser/chromeos/login/update_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/update_screen_browsertest.cc @@ -112,6 +112,7 @@ IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestUpdateAvailable) { UpdateScreen* update_screen = controller()->GetUpdateScreen(); ASSERT_TRUE(update_screen != NULL); ASSERT_EQ(controller()->current_screen(), update_screen); + update_screen->SetAllUpdatesCritical(true); UpdateLibrary::Status status; diff --git a/chrome/browser/chromeos/login/user_controller.cc b/chrome/browser/chromeos/login/user_controller.cc index 7671af4..11b011e 100644 --- a/chrome/browser/chromeos/login/user_controller.cc +++ b/chrome/browser/chromeos/login/user_controller.cc @@ -11,7 +11,7 @@ #include "app/resource_bundle.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/chromeos/cros_settings_provider_user.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/chromeos/login/existing_user_view.h" #include "chrome/browser/chromeos/login/guest_user_view.h" #include "chrome/browser/chromeos/login/helper.h" @@ -49,6 +49,9 @@ const int kUserNameGap = 4; // case to make border window size close to existing users. const int kControlsHeight = 28; +// Delta for the unselected username font. +const int kUnselectedUsernameFontDelta = 1; + // Widget that notifies window manager about clicking on itself. // Doesn't send anything if user is selected. class ClickNotifyingWidget : public views::WidgetGtk { @@ -72,6 +75,13 @@ class ClickNotifyingWidget : public views::WidgetGtk { DISALLOW_COPY_AND_ASSIGN(ClickNotifyingWidget); }; +void CloseWindow(views::WidgetGtk* window) { + if (!window) + return; + window->SetWidgetDelegate(NULL); + window->Close(); +} + } // namespace using login::kBackgroundColor; @@ -146,17 +156,11 @@ UserController::~UserController() { // Reset the widget delegate of every window to NULL, so the user // controller will not get notified about the active window change. // See also crosbug.com/7400. - controls_window_->SetWidgetDelegate(NULL); - image_window_->SetWidgetDelegate(NULL); - border_window_->SetWidgetDelegate(NULL); - label_window_->SetWidgetDelegate(NULL); - unselected_label_window_->SetWidgetDelegate(NULL); - - controls_window_->Close(); - image_window_->Close(); - border_window_->Close(); - label_window_->Close(); - unselected_label_window_->Close(); + CloseWindow(controls_window_); + CloseWindow(image_window_); + CloseWindow(border_window_); + CloseWindow(label_window_); + CloseWindow(unselected_label_window_); } void UserController::Init(int index, @@ -177,7 +181,13 @@ void UserController::Init(int index, void UserController::SetPasswordEnabled(bool enable) { DCHECK(!is_new_user_); existing_user_view_->password_field()->SetEnabled(enable); - enable ? user_view_->StopThrobber() : user_view_->StartThrobber(); + if (enable) { + user_view_->StopThrobber(); + delegate_->SetStatusAreaEnabled(enable); + } else { + delegate_->SetStatusAreaEnabled(enable); + user_view_->StartThrobber(); + } } std::wstring UserController::GetNameTooltip() const { @@ -188,18 +198,18 @@ std::wstring UserController::GetNameTooltip() const { // 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()); + const std::string& email = user_.email(); size_t at_pos = email.rfind('@'); - if (at_pos == std::wstring::npos) { + if (at_pos == std::string::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()); + std::string domain = email.substr(domain_start, + email.length() - domain_start); + return UTF8ToWide(base::StringPrintf("%s (%s)", + user_.GetDisplayName().c_str(), + domain.c_str())); } void UserController::ClearAndEnablePassword() { @@ -430,8 +440,9 @@ WidgetGtk* UserController::CreateLabelWindow(int index, WmIpcWindowType type) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 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); + rb.GetFont(ResourceBundle::MediumBoldFont) : + rb.GetFont(ResourceBundle::BaseFont).DeriveFont( + kUnselectedUsernameFontDelta, gfx::Font::BOLD); std::wstring text; if (is_guest_) { text = l10n_util::GetString(IDS_GUEST); @@ -444,19 +455,11 @@ WidgetGtk* UserController::CreateLabelWindow(int index, text = UTF8ToWide(user_.GetDisplayName()); } - views::Label *label; - views::View *view; - if (is_new_user_) { - label = new views::Label(text); - label->SetColor(kTextColor); - label->SetFont(font); - view = label; - } else { - UsernameView* username_view = new UsernameView(text); - username_view->SetFont(font); - label = username_view->label(); - view = username_view; - } + views::Label *label = is_new_user_ ? + new views::Label(text) : new UsernameView(text); + + label->SetColor(kTextColor); + label->SetFont(font); if (type == WM_IPC_WINDOW_LOGIN_LABEL) label_view_ = label; @@ -469,13 +472,14 @@ WidgetGtk* UserController::CreateLabelWindow(int index, // Make label as small as possible to don't show tooltip. width = 0; } - int height = label->GetPreferredSize().height(); + int height = (type == WM_IPC_WINDOW_LOGIN_LABEL) ? + login::kSelectedLabelHeight : login::kUnselectedLabelHeight; WidgetGtk* window = new ClickNotifyingWidget(WidgetGtk::TYPE_WINDOW, this); ConfigureLoginWindow(window, index, gfx::Rect(0, 0, width, height), type, - view); + label); return window; } diff --git a/chrome/browser/chromeos/login/user_controller.h b/chrome/browser/chromeos/login/user_controller.h index 2ae08f1..6d3ec2c 100644 --- a/chrome/browser/chromeos/login/user_controller.h +++ b/chrome/browser/chromeos/login/user_controller.h @@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" +#include "testing/gtest/include/gtest/gtest_prod.h" #include "views/controls/button/button.h" #include "views/controls/textfield/textfield.h" #include "views/widget/widget_delegate.h" @@ -49,6 +50,7 @@ class UserController : public views::ButtonListener, virtual void ActivateWizard(const std::string& screen_name) = 0; virtual void RemoveUser(UserController* source) = 0; virtual void AddStartUrl(const GURL& start_url) = 0; + virtual void SetStatusAreaEnabled(bool enable) = 0; // Selects user entry with specified |index|. // Does nothing if current user is already selected. @@ -145,6 +147,8 @@ class UserController : public views::ButtonListener, static const int kNewUserUnselectedSize; private: + FRIEND_TEST(UserControllerTest, GetNameTooltip); + // Invoked when the user wants to login. Forwards the call to the delegate. void Login(); diff --git a/chrome/browser/chromeos/login/user_controller_unittest.cc b/chrome/browser/chromeos/login/user_controller_unittest.cc new file mode 100644 index 0000000..379e4fe --- /dev/null +++ b/chrome/browser/chromeos/login/user_controller_unittest.cc @@ -0,0 +1,30 @@ +// 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/login/user_controller.h" + +#include "app/l10n_util.h" +#include "chrome/browser/chromeos/login/user_manager.h" +#include "grit/generated_resources.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +TEST(UserControllerTest, GetNameTooltip) { + UserController guest_user_controller(NULL, false); + EXPECT_EQ(l10n_util::GetString(IDS_ADD_USER), + guest_user_controller.GetNameTooltip()); + + UserController new_user_controller(NULL, true); + EXPECT_EQ(l10n_util::GetString(IDS_GO_INCOGNITO_BUTTON), + new_user_controller.GetNameTooltip()); + + UserManager::User existing_user; + existing_user.set_email("someordinaryuser@domain.com"); + UserController existing_user_controller(NULL, existing_user); + EXPECT_EQ(L"someordinaryuser (domain.com)", + existing_user_controller.GetNameTooltip()); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/login/user_image_screen.cc b/chrome/browser/chromeos/login/user_image_screen.cc index 9016652..7151b4d 100644 --- a/chrome/browser/chromeos/login/user_image_screen.cc +++ b/chrome/browser/chromeos/login/user_image_screen.cc @@ -45,9 +45,6 @@ UserImageScreen::UserImageScreen(WizardScreenDelegate* delegate) this, NotificationType::SCREEN_LOCK_STATE_CHANGED, NotificationService::AllSources()); - camera_thread_.Start(); - camera_ = new Camera(this, &camera_thread_, true); - camera_->Initialize(kFrameWidth, kFrameHeight); } UserImageScreen::~UserImageScreen() { @@ -56,6 +53,9 @@ UserImageScreen::~UserImageScreen() { } void UserImageScreen::Refresh() { + camera_thread_.Start(); + camera_ = new Camera(this, &camera_thread_, true); + InitCamera(); } void UserImageScreen::Hide() { @@ -83,7 +83,7 @@ void UserImageScreen::OnInitializeFailure() { // Retry initializing the camera. if (camera_.get()) { camera_->Uninitialize(); - camera_->Initialize(kFrameWidth, kFrameHeight); + InitCamera(); } } @@ -154,7 +154,13 @@ void UserImageScreen::Observe(NotificationType type, if (is_screen_locked) camera_->Uninitialize(); else - camera_->Initialize(kFrameWidth, kFrameHeight); + InitCamera(); +} + +void UserImageScreen::InitCamera() { + if (view()) + view()->ShowCameraInitializing(); + camera_->Initialize(kFrameWidth, kFrameHeight); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/user_image_screen.h b/chrome/browser/chromeos/login/user_image_screen.h index ce02047..c17a585 100644 --- a/chrome/browser/chromeos/login/user_image_screen.h +++ b/chrome/browser/chromeos/login/user_image_screen.h @@ -47,6 +47,10 @@ class UserImageScreen: public ViewScreen, const NotificationDetails& details); private: + // Starts initializing the camera and shows the appropriate status on the + // screen. + void InitCamera(); + // Capturing timer callback that updates image from camera. void OnCaptureTimer(); diff --git a/chrome/browser/chromeos/login/user_image_view.cc b/chrome/browser/chromeos/login/user_image_view.cc index 6256a62..9b0e2e7 100644 --- a/chrome/browser/chromeos/login/user_image_view.cc +++ b/chrome/browser/chromeos/login/user_image_view.cc @@ -21,6 +21,7 @@ #include "views/controls/button/native_button.h" #include "views/controls/image_view.h" #include "views/controls/label.h" +#include "views/controls/throbber.h" #include "views/grid_layout.h" namespace { @@ -45,6 +46,106 @@ enum ColumnSets { namespace chromeos { +// Image view that can show center throbber above itself or a message at its +// bottom. +class CameraImageView : public views::ImageView { + public: + CameraImageView() + : throbber_(NULL), + message_(NULL) {} + + ~CameraImageView() {} + + void Init() { + DCHECK(NULL == throbber_); + DCHECK(NULL == message_); + + throbber_ = CreateDefaultSmoothedThrobber(); + throbber_->SetVisible(false); + AddChildView(throbber_); + + message_ = new views::Label(); + message_->SetMultiLine(true); + message_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + message_->SetVisible(false); + CorrectLabelFontSize(message_); + AddChildView(message_); + } + + void SetInitializingState() { + ShowThrobber(); + SetMessage(std::wstring()); + SetImage( + ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_USER_IMAGE_INITIALIZING)); + } + + void SetNormalState() { + HideThrobber(); + SetMessage(std::wstring()); + } + + void SetErrorState() { + HideThrobber(); + SetMessage(l10n_util::GetString(IDS_USER_IMAGE_NO_VIDEO)); + SetImage( + ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_USER_IMAGE_NO_VIDEO)); + } + + private: + void ShowThrobber() { + DCHECK(throbber_); + throbber_->SetVisible(true); + throbber_->Start(); + } + + void HideThrobber() { + DCHECK(throbber_); + throbber_->Stop(); + throbber_->SetVisible(false); + } + + void SetMessage(const std::wstring& message) { + DCHECK(message_); + message_->SetText(message); + message_->SetVisible(!message.empty()); + Layout(); + } + + // views::View override: + virtual void Layout() { + gfx::Size size = GetPreferredSize(); + if (throbber_->IsVisible()) { + gfx::Size throbber_size = throbber_->GetPreferredSize(); + int throbber_x = (size.width() - throbber_size.width()) / 2; + int throbber_y = (size.height() - throbber_size.height()) / 2; + throbber_->SetBounds(throbber_x, + throbber_y, + throbber_size.width(), + throbber_size.height()); + } + if (message_->IsVisible()) { + message_->SizeToFit(size.width() - kHorizontalMargin * 2); + gfx::Size message_size = message_->GetPreferredSize(); + int message_y = size.height() - kVerticalMargin - message_size.height(); + message_->SetBounds(kHorizontalMargin, + message_y, + message_size.width(), + message_size.height()); + } + } + + // Throbber centered within the view. + views::Throbber* throbber_; + + // Message, multiline, aligned to the bottom of the view. + views::Label* message_; + + DISALLOW_COPY_AND_ASSIGN(CameraImageView); +}; + + using login::kUserImageSize; UserImageView::UserImageView(Delegate* delegate) @@ -71,29 +172,32 @@ void UserImageView::Init() { new views::Label(l10n_util::GetString(IDS_USER_IMAGE_SCREEN_TITLE)); title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); title_label_->SetMultiLine(true); + CorrectLabelFontSize(title_label_); - user_image_ = new views::ImageView(); + user_image_ = new CameraImageView(); user_image_->SetImageSize( gfx::Size(kUserImageSize, kUserImageSize)); - user_image_->SetImage( - ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_USER_IMAGE_NO_VIDEO)); + user_image_->Init(); snapshot_button_ = new views::ImageButton(this); snapshot_button_->SetFocusable(true); snapshot_button_->SetImage(views::CustomButton::BS_NORMAL, ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_USER_IMAGE_CAPTURE)); + IDR_USER_IMAGE_CAPTURE)); + snapshot_button_->SetImage(views::CustomButton::BS_DISABLED, + ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_USER_IMAGE_CAPTURE_DISABLED)); - ok_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_OK)); + ok_button_ = new login::WideButton(this, l10n_util::GetString(IDS_OK)); ok_button_->SetEnabled(!is_capturing_); - skip_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_SKIP)); + skip_button_ = new login::WideButton(this, l10n_util::GetString(IDS_SKIP)); skip_button_->SetEnabled(true); InitLayout(); // Request focus only after the button is added to views hierarchy. snapshot_button_->RequestFocus(); + user_image_->SetInitializingState(); } void UserImageView::InitLayout() { @@ -153,6 +257,7 @@ void UserImageView::UpdateVideoFrame(const SkBitmap& frame) { return; if (!snapshot_button_->IsEnabled()) { + user_image_->SetNormalState(); snapshot_button_->SetEnabled(true); snapshot_button_->RequestFocus(); } @@ -166,13 +271,18 @@ void UserImageView::UpdateVideoFrame(const SkBitmap& frame) { user_image_->SetImage(&user_image); } +void UserImageView::ShowCameraInitializing() { + if (!is_capturing_) + return; + snapshot_button_->SetEnabled(false); + user_image_->SetInitializingState(); +} + void UserImageView::ShowCameraError() { - if (!is_capturing_ || !snapshot_button_->IsEnabled()) + if (!is_capturing_) return; snapshot_button_->SetEnabled(false); - user_image_->SetImage( - ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_USER_IMAGE_NO_VIDEO)); + user_image_->SetErrorState(); } void UserImageView::ViewHierarchyChanged(bool is_add, diff --git a/chrome/browser/chromeos/login/user_image_view.h b/chrome/browser/chromeos/login/user_image_view.h index 88d9224..c06dedc 100644 --- a/chrome/browser/chromeos/login/user_image_view.h +++ b/chrome/browser/chromeos/login/user_image_view.h @@ -13,13 +13,14 @@ class SkBitmap; namespace views { class ImageButton; -class ImageView; class Label; class NativeButton; } // namespace views namespace chromeos { +class CameraImageView; + // View used for selecting user image. class UserImageView : public views::View, public views::ButtonListener { @@ -46,8 +47,13 @@ class UserImageView : public views::View, // Updates image from camera. void UpdateVideoFrame(const SkBitmap& frame); + // If in capturing mode, shows that camera is initializing by running + // throbber above the picture. Disables snapshot button until frame is + // received. + void ShowCameraInitializing(); + // If in capturing mode, shows that camera is broken instead of video - // frame and disables snapshot button. + // frame and disables snapshot button until new frame is received. void ShowCameraError(); // Overridden from views::View: @@ -70,7 +76,7 @@ class UserImageView : public views::View, views::NativeButton* ok_button_; views::NativeButton* skip_button_; views::ImageButton* snapshot_button_; - views::ImageView* user_image_; + CameraImageView* user_image_; // Notifications receiver. Delegate* delegate_; diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc index 74aad31..ada146e 100644 --- a/chrome/browser/chromeos/login/user_manager.cc +++ b/chrome/browser/chromeos/login/user_manager.cc @@ -19,9 +19,10 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/input_method_library.h" -#include "chrome/browser/chromeos/cros_settings_provider_user.h" #include "chrome/browser/chromeos/login/ownership_service.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/chromeos/wm_ipc.h" +#include "chrome/browser/defaults.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_service.h" @@ -237,6 +238,11 @@ void UserManager::UserLoggedIn(const std::string& email) { return; } + if (!IsKnownUser(email)) { + current_user_is_new_ = true; + browser_defaults::skip_restore = true; + } + // Get a copy of the current users. std::vector users = GetUsers(); @@ -393,7 +399,8 @@ 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))), - current_user_is_owner_(false) { + current_user_is_owner_(false), + current_user_is_new_(false) { registrar_.Add(this, NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED, NotificationService::AllSources()); } diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h index 01766d0..4a29614 100644 --- a/chrome/browser/chromeos/login/user_manager.h +++ b/chrome/browser/chromeos/login/user_manager.h @@ -107,6 +107,11 @@ class UserManager : public UserImageLoader::Delegate, current_user_is_owner_ = current_user_is_owner; } + // Accessor for current_user_is_new_. + bool current_user_is_new() const { + return current_user_is_new_; + } + protected: UserManager(); virtual ~UserManager(); @@ -131,6 +136,10 @@ class UserManager : public UserImageLoader::Delegate, // Cached flag of whether currently logged-in user is owner or not. bool current_user_is_owner_; + // Cached flag of whether the currently logged-in user existed before this + // login. + bool current_user_is_new_; + NotificationRegistrar registrar_; DISALLOW_COPY_AND_ASSIGN(UserManager); diff --git a/chrome/browser/chromeos/login/username_view.cc b/chrome/browser/chromeos/login/username_view.cc index 783c9cd..750c788 100644 --- a/chrome/browser/chromeos/login/username_view.cc +++ b/chrome/browser/chromeos/login/username_view.cc @@ -4,56 +4,92 @@ #include "chrome/browser/chromeos/login/username_view.h" -#include "chrome/browser/chromeos/login/helper.h" +#include "base/logging.h" +#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" +#include "gfx/rect.h" +#include "third_party/skia/include/core/SkComposeShader.h" +#include "third_party/skia/include/effects/SkGradientShader.h" #include "views/background.h" -#include "views/painter.h" -#include "views/controls/label.h" namespace { // Username label background color. const SkColor kLabelBackgoundColor = 0x55000000; +// Holds margin to height ratio. +const double kMarginRatio = 1.0 / 3.0; } // namespace namespace chromeos { -UsernameView::UsernameView(const std::wstring& username) { - label_ = new views::Label(username); - label_->SetColor(login::kTextColor); - label_->set_background( - views::Background::CreateSolidBackground(kLabelBackgoundColor)); - label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - AddChildView(label_); - - gradient_ = new views::View; - gradient_->SetVisible(false); - views::Background* gradient_background = - views::Background::CreateBackgroundPainter(true, - views::Painter::CreateHorizontalGradient( - kLabelBackgoundColor, 0x00000000)); - gradient_->set_background(gradient_background); - AddChildView(gradient_); +UsernameView::UsernameView(const std::wstring& username) + : views::Label(username) { } -void UsernameView::SetFont(const gfx::Font& font) { - label_->SetFont(font); -} +void UsernameView::Paint(gfx::Canvas* canvas) { + gfx::Rect bounds = GetLocalBounds(false); + if (!text_image_.get()) + PaintUsername(bounds); + + DCHECK(bounds.size() == + gfx::Size(text_image_->width(), text_image_->height())); + + // Only alpha channel counts. + SkColor gradient_colors[2]; + gradient_colors[0] = 0xFFFFFFFF; + gradient_colors[1] = 0x00FFFFFF; + + int gradient_start = std::min(margin_width_ + text_width_, + bounds.width() - bounds.height()); -// views::View -void UsernameView::Layout() { - int text_width = std::min(label_->GetPreferredSize().width(), width()); - label_->SetBounds(0, 0, text_width, height()); - int gradient_width = std::min(width() - text_width, height()); - if (gradient_width > 0) { - gradient_->SetVisible(true); - gradient_->SetBounds(0 + text_width, 0, gradient_width, height()); - } else { - // No place for the gradient part. - gradient_->SetVisible(false); - } + SkPoint gradient_borders[2]; + gradient_borders[0].set(SkIntToScalar(gradient_start), SkIntToScalar(0)); + gradient_borders[1].set(SkIntToScalar( + gradient_start + bounds.height()), SkIntToScalar(0)); + + SkShader* gradient_shader = + SkGradientShader::CreateLinear(gradient_borders, gradient_colors, NULL, 2, + SkShader::kClamp_TileMode, NULL); + SkShader* image_shader = SkShader::CreateBitmapShader( + *text_image_, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + + SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcIn_Mode); + SkShader* composite_shader = new SkComposeShader(gradient_shader, + image_shader, mode); + gradient_shader->unref(); + image_shader->unref(); + + SkPaint paint; + paint.setAntiAlias(true); + paint.setFilterBitmap(true); + paint.setShader(composite_shader)->unref(); + canvas->DrawRectInt(bounds.x(), bounds.y(), + bounds.width(), bounds.height(), paint); } -gfx::Size UsernameView::GetPreferredSize() { - return label_->GetPreferredSize(); +void UsernameView::PaintUsername(const gfx::Rect& bounds) { + margin_width_ = bounds.height() * kMarginRatio; + gfx::CanvasSkia canvas(bounds.width(), bounds.height(), false); + // Draw background. + canvas.drawColor(kLabelBackgoundColor); + // Calculate needed space. + int flags = gfx::Canvas::TEXT_ALIGN_LEFT | + gfx::Canvas::TEXT_VALIGN_MIDDLE | + gfx::Canvas::NO_ELLIPSIS; + int text_height; + gfx::CanvasSkia::SizeStringInt(GetText(), font(), + &text_width_, &text_height, + flags); + text_width_ = std::min(text_width_, bounds.width() - margin_width_); + // Draw the text. + canvas.DrawStringInt(GetText(), font(), GetColor(), + bounds.x() + margin_width_, bounds.y(), + bounds.width() - margin_width_, bounds.height(), + flags); + + text_image_.reset(new SkBitmap(canvas.ExtractBitmap())); + text_image_->buildMipMap(false); } } // namespace chromeos diff --git a/chrome/browser/chromeos/login/username_view.h b/chrome/browser/chromeos/login/username_view.h index 856a609..f1ad180 100644 --- a/chrome/browser/chromeos/login/username_view.h +++ b/chrome/browser/chromeos/login/username_view.h @@ -8,39 +8,36 @@ #include -#include "views/view.h" +#include "views/controls/label.h" +#include "third_party/skia/include/core/SkBitmap.h" +// Forward declaration. namespace gfx { -class Font; -} // namespace gfx - -namespace views { -class Label; -} // namespace views + class Rect; +} namespace chromeos { -// View that contains two parts. First one is a label with username, second one -// is an empty view with gradient transparency background. -class UsernameView : public views::View { +// Label with customized paddings and long text fade out. +class UsernameView : public views::Label { public: - explicit UsernameView(const std::wstring& username); + UsernameView(const std::wstring& username); virtual ~UsernameView() {} - // Set the font of the username text. - void SetFont(const gfx::Font& font); + // Overriden from views::Label. + virtual void Paint(gfx::Canvas* canvas); + + private: + // Paints username to the bitmap with the bounds given. + void PaintUsername(const gfx::Rect& bounds); - // Returns username label. - views::Label* label() const { - return label_; - } + // Holds painted username. + scoped_ptr text_image_; - // views::View overrides. - virtual void Layout(); - virtual gfx::Size GetPreferredSize(); + // Holds width of the text drawn. + int text_width_; - private: - views::Label* label_; - views::View* gradient_; + // Holds margins width (depends on the height). + int margin_width_; DISALLOW_COPY_AND_ASSIGN(UsernameView); }; diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 1962a29..54f12c2 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -17,6 +17,7 @@ #include "base/logging.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/cros/cryptohome_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" @@ -578,6 +579,11 @@ void WizardController::OnUpdateCompleted() { void WizardController::OnEulaAccepted() { MarkEulaAccepted(); + if (chromeos::CrosLibrary::Get()->EnsureLoaded()) { + // TPM password could be seen on EULA screen, now it's safe to clear it. + chromeos::CrosLibrary::Get()-> + GetCryptohomeLibrary()->TpmClearStoredPassword(); + } InitiateOOBEUpdate(); } diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc index 87f3a73..9bf0618 100644 --- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc @@ -68,7 +68,9 @@ class WizardControllerTest : public chromeos::WizardInProcessBrowserTest { DISALLOW_COPY_AND_ASSIGN(WizardControllerTest); }; -IN_PROC_BROWSER_TEST_F(WizardControllerTest, SwitchLanguage) { +// TODO(zelidrag): Need to revisit this once translation for fr and ar is +// complete. See http://crosbug.com/8974 +IN_PROC_BROWSER_TEST_F(WizardControllerTest, FAILS_SwitchLanguage) { WizardController* const wizard = controller(); ASSERT_TRUE(wizard != NULL); wizard->ShowFirstScreen(WizardController::kNetworkScreenName); diff --git a/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc b/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc index dc87e97..e18ba3a 100644 --- a/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc +++ b/chrome/browser/chromeos/login/wizard_in_process_browser_test.cc @@ -5,8 +5,8 @@ #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h" #include "base/message_loop.h" -#include "chrome/browser/browser.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/browser_dialogs.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/chromeos/metrics_cros_settings_provider.cc b/chrome/browser/chromeos/metrics_cros_settings_provider.cc new file mode 100644 index 0000000..ba36cc2 --- /dev/null +++ b/chrome/browser/chromeos/metrics_cros_settings_provider.cc @@ -0,0 +1,66 @@ +// 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/metrics_cros_settings_provider.h" + +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/chromeos/cros_settings.h" +#include "chrome/browser/chromeos/cros_settings_names.h" +#include "chrome/browser/options_util.h" +#include "chrome/installer/util/google_update_settings.h" + +#if defined(USE_LINUX_BREAKPAD) +#include "chrome/app/breakpad_linux.h" +#endif + +namespace chromeos { + +void MetricsCrosSettingsProvider::DoSet(const std::string& path, + Value* value) { + DCHECK(path == kStatsReportingPref); + bool enabled = false; + CHECK(value->GetAsBoolean(&enabled)); + if (SetMetricsStatus(enabled)) { + CrosSettings::Get()->FireObservers(path.c_str()); + } +} + +bool MetricsCrosSettingsProvider::Get(const std::string& path, + Value** value) const { + DCHECK(path == kStatsReportingPref); + *value = Value::CreateBooleanValue(GetMetricsStatus()); + return true; +} + +// static +bool MetricsCrosSettingsProvider::SetMetricsStatus(bool enabled) { + VLOG(1) << "Setting cros stats/crash metric reporting to " << enabled; + if (enabled != GoogleUpdateSettings::GetCollectStatsConsent()) { + bool new_enabled = OptionsUtil::ResolveMetricsReportingEnabled(enabled); +#if defined(USE_LINUX_BREAKPAD) + if (new_enabled) + InitCrashReporter(); + // Else, if (!new_enabled), we should have turned crash reporting off + // here, but there is no API for that currently (while we use + // BreakPad). But this is not a big deal: crash reporting will be off + // after reboot for the current process while other Chrome processes + // will start when the setting is already set up. Other ChromeOS + // processes does not use BreakPad. +#endif + return new_enabled == enabled; + } + return false; +} + +// static +bool MetricsCrosSettingsProvider::GetMetricsStatus() { + return GoogleUpdateSettings::GetCollectStatsConsent(); +} + +bool MetricsCrosSettingsProvider::HandlesSetting(const std::string& path) { + return ::StartsWithASCII(path, kStatsReportingPref, true); +} + +}; // namespace chromeos diff --git a/chrome/browser/chromeos/metrics_cros_settings_provider.h b/chrome/browser/chromeos/metrics_cros_settings_provider.h new file mode 100644 index 0000000..ad479ec --- /dev/null +++ b/chrome/browser/chromeos/metrics_cros_settings_provider.h @@ -0,0 +1,41 @@ +// 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_METRICS_CROS_SETTINGS_PROVIDER_H_ +#define CHROME_BROWSER_CHROMEOS_METRICS_CROS_SETTINGS_PROVIDER_H_ +#pragma once + +#include + +#include "base/basictypes.h" +#include "chrome/browser/chromeos/cros_settings_provider.h" + +namespace chromeos { + +// CrosSettingsProvider that abstracts switching of stats/crash +// reporting to Google. +class MetricsCrosSettingsProvider : public CrosSettingsProvider { + public: + MetricsCrosSettingsProvider() {} + + // CrosSettingsProvider implementation. + virtual bool Get(const std::string& path, Value** value) const; + virtual bool HandlesSetting(const std::string& path); + + // Actual methods to control stats/crash reporting. Currently these + // methods are public and static so they are accessible directly + // from cros code. But this will change soon: crosbug.com/7359 + static bool SetMetricsStatus(bool enabled); + static bool GetMetricsStatus(); + + private: + // CrosSettingsProvider implementation. + virtual void DoSet(const std::string& path, Value* value); + + DISALLOW_COPY_AND_ASSIGN(MetricsCrosSettingsProvider); +}; + +}; // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_METRICS_CROS_SETTINGS_PROVIDER_H_ diff --git a/chrome/browser/chromeos/network_message_observer.cc b/chrome/browser/chromeos/network_message_observer.cc index 8a09207..945b9e0 100644 --- a/chrome/browser/chromeos/network_message_observer.cc +++ b/chrome/browser/chromeos/network_message_observer.cc @@ -9,13 +9,13 @@ #include "base/stl_util-inl.h" #include "base/string_number_conversions.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/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/notifications/balloon_view_host.h" #include "chrome/browser/chromeos/options/network_config_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/window.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -67,8 +67,22 @@ void NetworkMessageObserver::CreateModalPopup(views::WindowDelegate* view) { window->Show(); } -void NetworkMessageObserver::MobileSetup(const ListValue* args) { - BrowserList::GetLastActive()->OpenMobilePlanTabAndActivate(); +void NetworkMessageObserver::OpenMobileSetupPage(const ListValue* args) { + Browser* browser = BrowserList::GetLastActive(); + if (browser) + browser->OpenMobilePlanTabAndActivate(); +} + +void NetworkMessageObserver::OpenMoreInfoPage(const ListValue* args) { + Browser* browser = BrowserList::GetLastActive(); + if (!browser) + return; + chromeos::NetworkLibrary* lib = + chromeos::CrosLibrary::Get()->GetNetworkLibrary(); + chromeos::CellularNetwork* cellular = lib->cellular_network(); + if (!cellular) + return; + browser->ShowSingletonTab(GURL(cellular->payment_url()), false); } void NetworkMessageObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { @@ -173,11 +187,25 @@ void NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* obj) { plan.plan_type != cellular_data_plan_.plan_type) { new_plan = true; } + + cellular_data_plan_ = plan; + if (new_plan) { - // New network, so hide the notifications and set the notifications title. notification_low_data_.Hide(); notification_no_data_.Hide(); - if (plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED) { + if (plans.empty() && cellular->needs_new_plan()) { + notification_no_data_.set_title( + l10n_util::GetStringFUTF16(IDS_NETWORK_NO_DATA_PLAN_TITLE, + UTF8ToUTF16(cellular->service_name()))); + notification_no_data_.Show( + l10n_util::GetStringFUTF16( + IDS_NETWORK_NO_DATA_PLAN_MESSAGE, + UTF8ToUTF16(cellular->service_name())), + l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), + NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage), + false, false); + return; + } else if (plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED) { notification_no_data_.set_title( l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE, ASCIIToUTF16(plan.plan_name))); @@ -194,40 +222,37 @@ void NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* obj) { } } - if (plan.plan_type != CELLULAR_DATA_PLAN_UNKNOWN) { - if (cellular->data_left() == CellularNetwork::DATA_NONE) { - notification_low_data_.Hide(); - int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? - IDS_NETWORK_MINUTES_REMAINING_MESSAGE : - IDS_NETWORK_DATA_REMAINING_MESSAGE; - notification_no_data_.Show(l10n_util::GetStringFUTF16( - message, ASCIIToUTF16("0")), - l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), - NewCallback(this, &NetworkMessageObserver::MobileSetup), - false, false); - } else if (cellular->data_left() == CellularNetwork::DATA_VERY_LOW) { - notification_no_data_.Hide(); - int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? - IDS_NETWORK_MINUTES_REMAINING_MESSAGE : - IDS_NETWORK_DATA_REMAINING_MESSAGE; - int64 remaining_minutes = - base::TimeDelta(plan.plan_end_time - plan.update_time).InMinutes(); - int64 remaining = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? - remaining_minutes : - (plan.plan_data_bytes - plan.data_bytes_used) / (1024 * 1024); - notification_low_data_.Show(l10n_util::GetStringFUTF16( - message, UTF8ToUTF16(base::Int64ToString(remaining))), - l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), - NewCallback(this, &NetworkMessageObserver::MobileSetup), - false, false); - } else { - // Got data, so hide notifications. - notification_low_data_.Hide(); - notification_no_data_.Hide(); - } - } + if (plan.plan_type == CELLULAR_DATA_PLAN_UNKNOWN) + return; - cellular_data_plan_ = plan; + if (cellular->data_left() == CellularNetwork::DATA_NONE) { + notification_low_data_.Hide(); + int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? + IDS_NETWORK_MINUTES_REMAINING_MESSAGE : + IDS_NETWORK_DATA_REMAINING_MESSAGE; + notification_no_data_.Show(l10n_util::GetStringFUTF16( + message, ASCIIToUTF16("0")), + l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), + NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage), + false, false); + } else if (cellular->data_left() == CellularNetwork::DATA_VERY_LOW) { + notification_no_data_.Hide(); + int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? + IDS_NETWORK_MINUTES_REMAINING_MESSAGE : + IDS_NETWORK_DATA_REMAINING_MESSAGE; + int64 remaining = plan.plan_type == + CELLULAR_DATA_PLAN_UNLIMITED ? plan.remaining_minutes() : + plan.remaining_mbytes(); + notification_low_data_.Show(l10n_util::GetStringFUTF16( + message, UTF8ToUTF16(base::Int64ToString(remaining))), + l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE), + NewCallback(this, &NetworkMessageObserver::OpenMoreInfoPage), + false, false); + } else { + // Got data, so hide notifications. + notification_low_data_.Hide(); + notification_no_data_.Hide(); + } } } // namespace chromeos diff --git a/chrome/browser/chromeos/network_message_observer.h b/chrome/browser/chromeos/network_message_observer.h index db1ba1b..a6dd9fd 100644 --- a/chrome/browser/chromeos/network_message_observer.h +++ b/chrome/browser/chromeos/network_message_observer.h @@ -33,7 +33,8 @@ class NetworkMessageObserver : public NetworkLibrary::NetworkManagerObserver, typedef std::map ServicePathCellularMap; private: virtual void CreateModalPopup(views::WindowDelegate* view); - virtual void MobileSetup(const ListValue* args); + virtual void OpenMobileSetupPage(const ListValue* args); + virtual void OpenMoreInfoPage(const ListValue* args); // NetworkLibrary::NetworkManagerObserver implementation. virtual void OnNetworkManagerChanged(NetworkLibrary* obj); diff --git a/chrome/browser/chromeos/notifications/notification_browsertest.cc b/chrome/browser/chromeos/notifications/notification_browsertest.cc index 5901454..b5830d5 100644 --- a/chrome/browser/chromeos/notifications/notification_browsertest.cc +++ b/chrome/browser/chromeos/notifications/notification_browsertest.cc @@ -10,7 +10,6 @@ #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" #include "chrome/browser/chromeos/notifications/balloon_view.h" @@ -18,6 +17,7 @@ #include "chrome/browser/chromeos/notifications/system_notification_factory.h" #include "chrome/browser/notifications/notification_delegate.h" #include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/chromeos/offline/offline_load_page.cc b/chrome/browser/chromeos/offline/offline_load_page.cc index 63c9eae..e4829e7 100644 --- a/chrome/browser/chromeos/offline/offline_load_page.cc +++ b/chrome/browser/chromeos/offline/offline_load_page.cc @@ -12,12 +12,12 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/notification_type.h" #include "grit/browser_resources.h" diff --git a/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc b/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc index 98f4e1f..02d5066 100644 --- a/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc +++ b/chrome/browser/chromeos/options/wifi_config_view_browsertest.cc @@ -41,7 +41,7 @@ IN_PROC_BROWSER_TEST_F(WifiConfigViewTest, NoChangeSaveTest) { IN_PROC_BROWSER_TEST_F(WifiConfigViewTest, ChangeAutoConnectSaveTest) { EXPECT_CALL(*mock_network_library_, SaveWifiNetwork(_)).Times(1); scoped_ptr remembered_network(new WifiNetwork()); - remembered_network->set_favorite(true); + remembered_network->favorite_ = true; WifiConfigView* view = new WifiConfigView(NULL, remembered_network.get()); ASSERT_TRUE(view->autoconnect_checkbox_ != NULL); view->autoconnect_checkbox_->SetChecked( diff --git a/chrome/browser/chromeos/panels/panel_browsertest.cc b/chrome/browser/chromeos/panels/panel_browsertest.cc index d89204b..f655369 100644 --- a/chrome/browser/chromeos/panels/panel_browsertest.cc +++ b/chrome/browser/chromeos/panels/panel_browsertest.cc @@ -3,13 +3,13 @@ // found in the LICENSE file. #include "base/command_line.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/chromeos/panels/panel_scroller.h b/chrome/browser/chromeos/panels/panel_scroller.h index cc9befb..366bc5a 100644 --- a/chrome/browser/chromeos/panels/panel_scroller.h +++ b/chrome/browser/chromeos/panels/panel_scroller.h @@ -8,6 +8,7 @@ #include +#include "app/animation_delegate.h" #include "app/slide_animation.h" #include "base/basictypes.h" #include "views/view.h" diff --git a/chrome/browser/chromeos/pipe_reader_unittest.cc b/chrome/browser/chromeos/pipe_reader_unittest.cc index f45fe50..3cb55ee 100644 --- a/chrome/browser/chromeos/pipe_reader_unittest.cc +++ b/chrome/browser/chromeos/pipe_reader_unittest.cc @@ -76,7 +76,14 @@ TEST_F(PipeReaderTest, SuccessfulMultiLineReadTest) { } } -TEST_F(PipeReaderTest, SuccessfulMultiLineReadNoEndingNewlineTest) { +// http://crbug.com/63228 +#if defined(OS_CHROMEOS) +#define MAYBE_SuccessfulMultiLineReadNoEndingNewlineTest FLAKY_SuccessfulMultiLineReadNoEndingNewlineTest +#else +#define MAYBE_SuccessfulMultiLineReadNoEndingNewlineTest SuccessfulMultiLineReadNoEndingNewlineTest +#endif + +TEST_F(PipeReaderTest, MAYBE_SuccessfulMultiLineReadNoEndingNewlineTest) { FilePath pipe_name("/tmp/TESTFIFO"); /* Create the FIFO if it does not exist */ umask(0); diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc index 73693fd..5b2902c 100644 --- a/chrome/browser/chromeos/proxy_config_service_impl.cc +++ b/chrome/browser/chromeos/proxy_config_service_impl.cc @@ -286,13 +286,13 @@ bool ProxyConfigServiceImpl::ProxyConfig::Deserialize( net::ProxyServer::SCHEME_HTTP, &http_proxy)) return false; if (!DecodeManualProxy(dict, kHttpsProxy, true, - net::ProxyServer::SCHEME_HTTPS, &https_proxy)) + net::ProxyServer::SCHEME_HTTP, &https_proxy)) return false; if (!DecodeManualProxy(dict, kFtpProxy, true, net::ProxyServer::SCHEME_HTTP, &ftp_proxy)) return false; if (!DecodeManualProxy(dict, kSocksProxy, true, - net::ProxyServer::SCHEME_SOCKS4, &socks_proxy)) + net::ProxyServer::SCHEME_SOCKS5, &socks_proxy)) return false; // Make sure we have valid server for at least one of the protocols. if (!(http_proxy.server.is_valid() || https_proxy.server.is_valid() || diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc index 46fc3ff..7ba6def 100644 --- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc +++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc @@ -192,7 +192,7 @@ const struct { "www.google.com:80", // http "https://www.foo.com:110", // https "ftp.foo.com:121", // ftp - "socks4://socks.com:888", // fallback proxy + "socks5://socks.com:888", // fallback proxy ""), // bypass rules }, @@ -287,7 +287,7 @@ class ProxyConfigServiceImplTest : public PlatformTest { init_config, &init_config->https_proxy); SetManualProxy(input.mode, source, input.ftp_uri, MK_SCHM(HTTP), init_config, &init_config->ftp_proxy); - SetManualProxy(input.mode, source, input.socks_uri, MK_SCHM(SOCKS4), + SetManualProxy(input.mode, source, input.socks_uri, MK_SCHM(SOCKS5), init_config, &init_config->socks_proxy); break; } @@ -419,7 +419,7 @@ TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) { } if (input.socks_uri) { config_service()->UISetProxyConfigToProxyPerScheme("socks", - net::ProxyServer::FromURI(input.socks_uri, MK_SCHM(SOCKS4))); + net::ProxyServer::FromURI(input.socks_uri, MK_SCHM(SOCKS5))); } if (input.bypass_rules) { bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules); diff --git a/chrome/browser/chromeos/proxy_cros_settings_provider.cc b/chrome/browser/chromeos/proxy_cros_settings_provider.cc new file mode 100644 index 0000000..cc4f586 --- /dev/null +++ b/chrome/browser/chromeos/proxy_cros_settings_provider.cc @@ -0,0 +1,334 @@ +// 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/proxy_cros_settings_provider.h" + +#include "base/string_util.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/profile_manager.h" + +namespace chromeos { + +static const char kProxyPacUrl[] = "cros.proxy.pacurl"; +static const char kProxySingleHttp[] = "cros.proxy.singlehttp"; +static const char kProxySingleHttpPort[] = "cros.proxy.singlehttpport"; +static const char kProxyHttpUrl[] = "cros.proxy.httpurl"; +static const char kProxyHttpPort[] = "cros.proxy.httpport"; +static const char kProxyHttpsUrl[] = "cros.proxy.httpsurl"; +static const char kProxyHttpsPort[] = "cros.proxy.httpsport"; +static const char kProxyType[] = "cros.proxy.type"; +static const char kProxySingle[] = "cros.proxy.single"; +static const char kProxyFtpUrl[] = "cros.proxy.ftpurl"; +static const char kProxyFtpPort[] = "cros.proxy.ftpport"; +static const char kProxySocks[] = "cros.proxy.socks"; +static const char kProxySocksPort[] = "cros.proxy.socksport"; +static const char kProxyIgnoreList[] = "cros.proxy.ignorelist"; + +//------------------ ProxyCrosSettingsProvider: public methods ----------------- + +ProxyCrosSettingsProvider::ProxyCrosSettingsProvider() { } + +void ProxyCrosSettingsProvider::DoSet(const std::string& path, + Value* in_value) { + if (!in_value) { + return; + } + + // Keep whatever user inputs so that we could use it later. + SetCache(path, in_value); + + chromeos::ProxyConfigServiceImpl* config_service = GetConfigService(); + chromeos::ProxyConfigServiceImpl::ProxyConfig config; + config_service->UIGetProxyConfig(&config); + + if (path == kProxyPacUrl) { + std::string val; + if (in_value->GetAsString(&val)) { + GURL url(val); + config_service->UISetProxyConfigToPACScript(url); + } + } else if (path == kProxySingleHttp) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri = val; + AppendPortIfValid(kProxySingleHttpPort, &uri); + config_service->UISetProxyConfigToSingleProxy( + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxySingleHttpPort) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri; + FormServerUriIfValid(kProxySingleHttp, val, &uri); + config_service->UISetProxyConfigToSingleProxy( + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyHttpUrl) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri = val; + AppendPortIfValid(kProxyHttpPort, &uri); + config_service->UISetProxyConfigToProxyPerScheme("http", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyHttpPort) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri; + FormServerUriIfValid(kProxyHttpUrl, val, &uri); + config_service->UISetProxyConfigToProxyPerScheme("http", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyHttpsUrl) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri = val; + AppendPortIfValid(kProxyHttpsPort, &uri); + config_service->UISetProxyConfigToProxyPerScheme("https", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyHttpsPort) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri; + FormServerUriIfValid(kProxyHttpsUrl, val, &uri); + config_service->UISetProxyConfigToProxyPerScheme("https", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyType) { + int val; + if (in_value->GetAsInteger(&val)) { + if (val == 3) { + if (config.automatic_proxy.pac_url.is_valid()) + config_service->UISetProxyConfigToPACScript( + config.automatic_proxy.pac_url); + else + config_service->UISetProxyConfigToAutoDetect(); + } else if (val == 2) { + if (config.single_proxy.server.is_valid()) { + config_service->UISetProxyConfigToSingleProxy( + config.single_proxy.server); + } else { + bool set_config = false; + if (config.http_proxy.server.is_valid()) { + config_service->UISetProxyConfigToProxyPerScheme("http", + config.http_proxy.server); + set_config = true; + } + if (config.https_proxy.server.is_valid()) { + config_service->UISetProxyConfigToProxyPerScheme("https", + config.https_proxy.server); + set_config = true; + } + if (config.ftp_proxy.server.is_valid()) { + config_service->UISetProxyConfigToProxyPerScheme("ftp", + config.ftp_proxy.server); + set_config = true; + } + if (config.socks_proxy.server.is_valid()) { + config_service->UISetProxyConfigToProxyPerScheme("socks", + config.socks_proxy.server); + set_config = true; + } + if (!set_config) { + config_service->UISetProxyConfigToProxyPerScheme("http", + net::ProxyServer()); + } + } + } else { + config_service->UISetProxyConfigToDirect(); + } + } + } else if (path == kProxySingle) { + bool val; + if (in_value->GetAsBoolean(&val)) { + if (val) + config_service->UISetProxyConfigToSingleProxy( + config.single_proxy.server); + else + config_service->UISetProxyConfigToProxyPerScheme("http", + config.http_proxy.server); + } + } else if (path == kProxyFtpUrl) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri = val; + AppendPortIfValid(kProxyFtpPort, &uri); + config_service->UISetProxyConfigToProxyPerScheme("ftp", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxyFtpPort) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri; + FormServerUriIfValid(kProxyFtpUrl, val, &uri); + config_service->UISetProxyConfigToProxyPerScheme("ftp", + net::ProxyServer::FromURI(uri, net::ProxyServer::SCHEME_HTTP)); + } + } else if (path == kProxySocks) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri = val; + AppendPortIfValid(kProxySocksPort, &uri); + config_service->UISetProxyConfigToProxyPerScheme("socks", + net::ProxyServer::FromURI(uri, + StartsWithASCII(uri, "socks4://", false) ? + net::ProxyServer::SCHEME_SOCKS4 : + net::ProxyServer::SCHEME_SOCKS5)); + } + } else if (path == kProxySocksPort) { + std::string val; + if (in_value->GetAsString(&val)) { + std::string uri; + FormServerUriIfValid(kProxySocks, val, &uri); + config_service->UISetProxyConfigToProxyPerScheme("socks", + net::ProxyServer::FromURI(uri, + StartsWithASCII(uri, "socks4://", false) ? + net::ProxyServer::SCHEME_SOCKS4 : + net::ProxyServer::SCHEME_SOCKS5)); + } + } else if (path == kProxyIgnoreList) { + net::ProxyBypassRules bypass_rules; + if (in_value->GetType() == Value::TYPE_LIST) { + const ListValue* list_value = static_cast(in_value); + for (size_t x = 0; x < list_value->GetSize(); x++) { + std::string val; + if (list_value->GetString(x, &val)) { + bypass_rules.AddRuleFromString(val); + } + } + config_service->UISetProxyConfigBypassRules(bypass_rules); + } + } +} + +bool ProxyCrosSettingsProvider::Get(const std::string& path, + Value** out_value) const { + bool found = false; + bool managed = false; + Value* data; + chromeos::ProxyConfigServiceImpl* config_service = GetConfigService(); + chromeos::ProxyConfigServiceImpl::ProxyConfig config; + config_service->UIGetProxyConfig(&config); + + if (path == kProxyPacUrl) { + if (config.automatic_proxy.pac_url.is_valid()) { + data = Value::CreateStringValue(config.automatic_proxy.pac_url.spec()); + found = true; + } + } else if (path == kProxySingleHttp) { + found = (data = CreateServerHostValue(config.single_proxy)); + } else if (path == kProxySingleHttpPort) { + found = (data = CreateServerPortValue(config.single_proxy)); + } else if (path == kProxyHttpUrl) { + found = (data = CreateServerHostValue(config.http_proxy)); + } else if (path == kProxyHttpsUrl) { + found = (data = CreateServerHostValue(config.https_proxy)); + } else if (path == kProxyType) { + if (config.mode == + chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT || + config.mode == + chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT) { + data = Value::CreateIntegerValue(3); + } else if (config.mode == + chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY || + config.mode == + chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) { + data = Value::CreateIntegerValue(2); + } else { + data = Value::CreateIntegerValue(1); + } + found = true; + } else if (path == kProxySingle) { + data = Value::CreateBooleanValue(config.mode == + chromeos::ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY); + found = true; + } else if (path == kProxyFtpUrl) { + found = (data = CreateServerHostValue(config.ftp_proxy)); + } else if (path == kProxySocks) { + found = (data = CreateServerHostValue(config.socks_proxy)); + } else if (path == kProxyHttpPort) { + found = (data = CreateServerPortValue(config.http_proxy)); + } else if (path == kProxyHttpsPort) { + found = (data = CreateServerPortValue(config.https_proxy)); + } else if (path == kProxyFtpPort) { + found = (data = CreateServerPortValue(config.ftp_proxy)); + } else if (path == kProxySocksPort) { + found = (data = CreateServerPortValue(config.socks_proxy)); + } else if (path == kProxyIgnoreList) { + ListValue* list = new ListValue(); + net::ProxyBypassRules::RuleList bypass_rules = config.bypass_rules.rules(); + for (size_t x = 0; x < bypass_rules.size(); x++) { + list->Append(Value::CreateStringValue(bypass_rules[x]->ToString())); + } + *out_value = list; + return true; + } + if (found) { + DictionaryValue* dict = new DictionaryValue; + dict->Set("value", data); + dict->SetBoolean("managed", managed); + *out_value = dict; + return true; + } else { + *out_value = NULL; + return false; + } +} + +bool ProxyCrosSettingsProvider::HandlesSetting(const std::string& path) { + return ::StartsWithASCII(path, "cros.proxy", true); +} + +//----------------- ProxyCrosSettingsProvider: private methods ----------------- + +chromeos::ProxyConfigServiceImpl* + ProxyCrosSettingsProvider::GetConfigService() const { + Browser* browser = BrowserList::GetLastActive(); + // browser is NULL at OOBE/login stage. + Profile* profile = browser ? + browser->profile() : + ProfileManager::GetDefaultProfile(); + return profile->GetChromeOSProxyConfigServiceImpl(); +} + +void ProxyCrosSettingsProvider::AppendPortIfValid( + const char* port_cache_key, + std::string* server_uri) { + std::string port; + if (!server_uri->empty() && cache_.GetString(port_cache_key, &port) && + !port.empty()) { + *server_uri += ":" + port; + } +} + +void ProxyCrosSettingsProvider::FormServerUriIfValid( + const char* host_cache_key, + const std::string& port_num, std::string* server_uri) { + if (cache_.GetString(host_cache_key, server_uri) && !server_uri->empty() && + !port_num.empty()) + *server_uri += ":" + port_num; +} + +Value* ProxyCrosSettingsProvider::CreateServerHostValue( + const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const { + return proxy.server.is_valid() ? + Value::CreateStringValue(proxy.server.host_port_pair().host()) : + NULL; +} + +Value* ProxyCrosSettingsProvider::CreateServerPortValue( + const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const { + return proxy.server.is_valid() ? + Value::CreateIntegerValue(proxy.server.host_port_pair().port()) : + NULL; +} + +void ProxyCrosSettingsProvider::SetCache(const std::string& key, + const Value* value) { + cache_.Set(key, value->DeepCopy()); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/proxy_cros_settings_provider.h b/chrome/browser/chromeos/proxy_cros_settings_provider.h new file mode 100644 index 0000000..d724815 --- /dev/null +++ b/chrome/browser/chromeos/proxy_cros_settings_provider.h @@ -0,0 +1,50 @@ +// 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_PROXY_CROS_SETTINGS_PROVIDER_H_ +#define CHROME_BROWSER_CHROMEOS_PROXY_CROS_SETTINGS_PROVIDER_H_ +#pragma once + +#include "base/singleton.h" +#include "base/values.h" +#include "chrome/browser/chromeos/cros_settings_provider.h" +#include "chrome/browser/chromeos/proxy_config_service_impl.h" + +namespace chromeos { + +class ProxyCrosSettingsProvider : public CrosSettingsProvider { + public: + ProxyCrosSettingsProvider(); + // CrosSettingsProvider implementation. + virtual bool Get(const std::string& path, Value** out_value) const; + virtual bool HandlesSetting(const std::string& path); + + private: + // CrosSettingsProvider implementation. + virtual void DoSet(const std::string& path, Value* value); + + chromeos::ProxyConfigServiceImpl* GetConfigService() const; + + void AppendPortIfValid(const char* port_cache_key, std::string* server_uri); + + void FormServerUriIfValid(const char* host_cache_key, + const std::string& port_num, std::string* server_uri); + + Value* CreateServerHostValue( + const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const; + + Value* CreateServerPortValue( + const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) const; + + void SetCache(const std::string& key, const Value* value); + + // A cache to keep whatever user typed. + DictionaryValue cache_; + + DISALLOW_COPY_AND_ASSIGN(ProxyCrosSettingsProvider); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PROXY_CROS_SETTINGS_PROVIDER_H_ diff --git a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc index f7a6f1c..2d494e1 100644 --- a/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc +++ b/chrome/browser/chromeos/status/clock_menu_button_browsertest.cc @@ -5,8 +5,6 @@ #include "chrome/browser/chromeos/status/clock_menu_button.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/system_library.h" #include "chrome/browser/chromeos/frame/browser_view.h" @@ -14,6 +12,8 @@ #include "chrome/browser/chromeos/view_ids.h" #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/pref_names.h" #include "chrome/test/in_process_browser_test.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc b/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc index 2fc8977..ca9e9fe 100644 --- a/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc +++ b/chrome/browser/chromeos/status/input_method_menu_button_browsertest.cc @@ -5,13 +5,13 @@ #include "chrome/browser/chromeos/status/input_method_menu_button.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" #include "chrome/browser/chromeos/cros/mock_input_method_library.h" #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/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "grit/theme_resources.h" namespace chromeos { diff --git a/chrome/browser/chromeos/status/network_dropdown_button.cc b/chrome/browser/chromeos/status/network_dropdown_button.cc index bf8a3be..32ff4e6 100644 --- a/chrome/browser/chromeos/status/network_dropdown_button.cc +++ b/chrome/browser/chromeos/status/network_dropdown_button.cc @@ -25,15 +25,15 @@ const int NetworkDropdownButton::kThrobDuration = 1000; NetworkDropdownButton::NetworkDropdownButton(bool browser_mode, gfx::NativeWindow parent_window) - : MenuButton(NULL, - l10n_util::GetString(IDS_STATUSBAR_NO_NETWORKS_MESSAGE), - this, - true), + : DropDownButton(NULL, + l10n_util::GetString(IDS_STATUSBAR_NO_NETWORKS_MESSAGE), + this, + true), browser_mode_(browser_mode), ALLOW_THIS_IN_INITIALIZER_LIST(animation_connecting_(this)), parent_window_(parent_window) { animation_connecting_.SetThrobDuration(kThrobDuration); - animation_connecting_.SetTweenType(Tween::LINEAR); + animation_connecting_.SetTweenType(Tween::EASE_IN_OUT); CrosLibrary::Get()->GetNetworkLibrary()->AddNetworkManagerObserver(this); // The initial state will be updated on Refresh. // See network_selection_view.cc. @@ -48,14 +48,8 @@ NetworkDropdownButton::~NetworkDropdownButton() { void NetworkDropdownButton::AnimationProgressed(const Animation* animation) { if (animation == &animation_connecting_) { - // Figure out which image to draw. We want a value between 0-100. - // 0 represents no signal and 100 represents full signal strength. - int value = static_cast(animation_connecting_.GetCurrentValue()*100.0); - if (value < 0) - value = 0; - else if (value > 100) - value = 100; - SetIcon(IconForNetworkStrength(value, true)); + SetIcon(IconForNetworkConnecting(animation_connecting_.GetCurrentValue(), + true)); SchedulePaint(); } else { MenuButton::AnimationProgressed(animation); @@ -91,14 +85,14 @@ void NetworkDropdownButton::OnNetworkManagerChanged(NetworkLibrary* cros) { DCHECK(active_network->type() == TYPE_WIFI || active_network->type() == TYPE_CELLULAR); wireless = static_cast(active_network); - SetIcon(IconForNetworkStrength(wireless->strength(), false)); + SetIcon(IconForNetworkStrength(wireless->strength(), true)); SetText(ASCIIToWide(wireless->name())); } } else if (cros->wifi_connecting() || cros->cellular_connecting()) { if (!animation_connecting_.is_animating()) { animation_connecting_.Reset(); animation_connecting_.StartThrobbing(-1); - SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS1_BLACK)); + SetIcon(IconForNetworkConnecting(0, true)); } if (cros->wifi_connecting()) SetText(ASCIIToWide(cros->wifi_network()->name())); diff --git a/chrome/browser/chromeos/status/network_dropdown_button.h b/chrome/browser/chromeos/status/network_dropdown_button.h index ec2e337..68ac84f 100644 --- a/chrome/browser/chromeos/status/network_dropdown_button.h +++ b/chrome/browser/chromeos/status/network_dropdown_button.h @@ -6,10 +6,11 @@ #define CHROME_BROWSER_CHROMEOS_STATUS_NETWORK_DROPDOWN_BUTTON_H_ #pragma once +#include "app/animation_delegate.h" #include "app/throb_animation.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/status/network_menu.h" -#include "views/controls/button/menu_button.h" +#include "chrome/browser/chromeos/views/dropdown_button.h" namespace chromeos { @@ -17,7 +18,7 @@ namespace chromeos { // This class will handle getting the networks to show connected network // at top level and populating the menu. // See NetworkMenu for more details. -class NetworkDropdownButton : public views::MenuButton, +class NetworkDropdownButton : public DropDownButton, public NetworkMenu, public NetworkLibrary::NetworkManagerObserver { public: diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc index fb64aa3..17686d8 100644 --- a/chrome/browser/chromeos/status/network_menu.cc +++ b/chrome/browser/chromeos/status/network_menu.cc @@ -11,10 +11,10 @@ #include "base/command_line.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/dom_ui/network_menu_ui.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/browser/views/window.h" @@ -145,6 +145,7 @@ bool NetworkMenu::GetNetworkAt(int index, NetworkInfo* info) const { } info->ip_address = wifi->ip_address(); info->remembered = wifi->favorite(); + info->auto_connect = info->remembered ? wifi->auto_connect() : true; } else { res = false; // Network not found, hide entry. } @@ -200,7 +201,7 @@ bool NetworkMenu::GetNetworkAt(int index, NetworkInfo* info) const { bool NetworkMenu::ConnectToNetworkAt(int index, const std::string& passphrase, const std::string& ssid, - int remember) const { + int auto_connect) const { int flags = menu_items_[index].flags; NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); if (flags & FLAG_WIFI) { @@ -208,8 +209,8 @@ bool NetworkMenu::ConnectToNetworkAt(int index, menu_items_[index].wireless_path); if (wifi) { // Connect or reconnect. - if (remember >= 0) - wifi->set_favorite(remember ? true : false); + if (auto_connect >= 0) + wifi->set_auto_connect(auto_connect ? true : false); if (cros->wifi_network() && wifi->service_path() == cros->wifi_network()->service_path()) { // Show the config settings for the active network. @@ -255,7 +256,8 @@ bool NetworkMenu::ConnectToNetworkAt(int index, CellularNetwork* cellular = cros->FindCellularNetworkByPath( menu_items_[index].wireless_path); if (cellular) { - if (cellular->activation_state() != ACTIVATION_STATE_ACTIVATED) { + if (cellular->activation_state() != ACTIVATION_STATE_ACTIVATED || + cellular->needs_new_plan()) { ActivateCellular(cellular); return true; } else if (cros->cellular_network() && @@ -278,10 +280,11 @@ bool NetworkMenu::ConnectToNetworkAt(int index, } else if (flags & FLAG_OTHER_NETWORK) { bool connected = false; if (MenuUI::IsEnabled()) { - bool favorite = remember == 0 ? false : true; // default is true + // default is true + bool auto_connect_bool = auto_connect == 0 ? false : true; connected = cros->ConnectToWifiNetwork( passphrase.empty() ? SECURITY_NONE : SECURITY_UNKNOWN, - ssid, passphrase, std::string(), std::string(), favorite); + ssid, passphrase, std::string(), std::string(), auto_connect_bool); } if (!connected) { ShowOther(); @@ -385,6 +388,7 @@ SkBitmap NetworkMenu::IconForNetworkStrength(int strength, bool black) { return *ResourceBundle::GetSharedInstance().GetBitmapNamed(images[index]); } +// static SkBitmap NetworkMenu::IconForNetworkStrength(const CellularNetwork* cellular) { DCHECK(cellular); // Compose wifi icon by superimposing various icons. @@ -408,6 +412,22 @@ SkBitmap NetworkMenu::IconForNetworkStrength(const CellularNetwork* cellular) { } // static +SkBitmap NetworkMenu::IconForNetworkConnecting(double animation_value, + bool black) { + // Draw animation of bars icon fading in and out. + // We are fading between 0 bars and a third of the opacity of 4 bars. + // Use the current value of the animation to calculate the alpha value + // of how transparent the icon is. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + return SkBitmapOperations::CreateBlendedBitmap( + *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK : + IDR_STATUSBAR_NETWORK_BARS0), + *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS4_BLACK : + IDR_STATUSBAR_NETWORK_BARS4), + animation_value / 3); +} + +// static // TODO(ers) update for GSM when we have the necessary images SkBitmap NetworkMenu::BadgeForNetworkTechnology( const CellularNetwork* cellular) { @@ -490,13 +510,12 @@ void NetworkMenu::InitMenuItems() { NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - bool no_networks = true; string16 label; // Ethernet bool ethernet_available = cros->ethernet_available(); - if (ethernet_available) { - no_networks = false; + bool ethernet_enabled = cros->ethernet_enabled(); + if (ethernet_available && ethernet_enabled) { bool ethernet_connected = cros->ethernet_connected(); bool ethernet_connecting = cros->ethernet_connecting(); @@ -521,15 +540,12 @@ void NetworkMenu::InitMenuItems() { // Wifi Networks bool wifi_available = cros->wifi_available(); - if (wifi_available) { + bool wifi_enabled = cros->wifi_enabled(); + if (wifi_available && wifi_enabled) { const WifiNetworkVector& wifi_networks = cros->wifi_networks(); const WifiNetwork* active_wifi = cros->wifi_network(); - if (wifi_networks.size() > 0) { - no_networks = false; - // Separator - menu_items_.push_back(MenuItem()); - } + bool separator_added = false; // List Wifi networks. for (size_t i = 0; i < wifi_networks.size(); ++i) { if (wifi_networks[i]->connecting()) { @@ -540,11 +556,22 @@ void NetworkMenu::InitMenuItems() { } else { label = ASCIIToUTF16(wifi_networks[i]->name()); } + + // First add a separator if necessary. + if (!separator_added) { + separator_added = true; + if (!menu_items_.empty()) { // Don't add if first menu item. + menu_items_.push_back(MenuItem()); // Separator + } + } + SkBitmap icon = IconForNetworkStrength(wifi_networks[i]->strength(), true); SkBitmap badge = wifi_networks[i]->encrypted() ? *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE) : SkBitmap(); int flag = FLAG_WIFI; + if (!wifi_networks[i]->connectable()) + flag |= FLAG_DISABLED; if (active_wifi && wifi_networks[i]->service_path() == active_wifi->service_path()) flag |= FLAG_ASSOCIATED; @@ -557,7 +584,8 @@ void NetworkMenu::InitMenuItems() { // Cellular Networks bool cellular_available = cros->cellular_available(); - if (cellular_available) { + bool cellular_enabled = cros->cellular_enabled(); + if (cellular_available && cellular_enabled) { const CellularNetworkVector& cell_networks = cros->cellular_networks(); const CellularNetwork* active_cellular = cros->cellular_network(); @@ -566,15 +594,17 @@ void NetworkMenu::InitMenuItems() { for (size_t i = 0; i < cell_networks.size(); ++i) { chromeos::ActivationState activation_state = cell_networks[i]->activation_state(); - if (activation_state == ACTIVATION_STATE_NOT_ACTIVATED) { - // If we are on the OOBE/login screen, do not show activating 3G option. - if (!IsBrowserMode()) - continue; + + // If we are on the OOBE/login screen, do not show activating 3G option. + if (!IsBrowserMode() && activation_state != ACTIVATION_STATE_ACTIVATED) + continue; + + if (activation_state == ACTIVATION_STATE_NOT_ACTIVATED || + activation_state == ACTIVATION_STATE_PARTIALLY_ACTIVATED) { label = l10n_util::GetStringFUTF16( IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATE, ASCIIToUTF16(cell_networks[i]->name())); - } else if (activation_state == ACTIVATION_STATE_PARTIALLY_ACTIVATED || - activation_state == ACTIVATION_STATE_ACTIVATING) { + } else if (activation_state == ACTIVATION_STATE_ACTIVATING) { label = l10n_util::GetStringFUTF16( IDS_STATUSBAR_NETWORK_DEVICE_STATUS, ASCIIToUTF16(cell_networks[i]->name()), @@ -590,29 +620,48 @@ void NetworkMenu::InitMenuItems() { // First add a separator if necessary. if (!separator_added) { - no_networks = false; - menu_items_.push_back(MenuItem()); separator_added = true; + if (!menu_items_.empty()) { // Don't add if first menu item. + menu_items_.push_back(MenuItem()); // Separator + } } SkBitmap icon = IconForNetworkStrength(cell_networks[i]->strength(), true); SkBitmap badge = BadgeForNetworkTechnology(cell_networks[i]); int flag = FLAG_CELLULAR; - if (active_cellular && - cell_networks[i]->service_path() == - active_cellular->service_path() && - (cell_networks[i]->connecting() || cell_networks[i]->connected())) + if (!cell_networks[i]->connectable()) + flag |= FLAG_DISABLED; + bool isActive = active_cellular && + cell_networks[i]->service_path() == active_cellular->service_path() && + (cell_networks[i]->connecting() || cell_networks[i]->connected()); + if (isActive) flag |= FLAG_ASSOCIATED; menu_items_.push_back( MenuItem(menus::MenuModel::TYPE_COMMAND, label, IconForDisplay(icon, badge), cell_networks[i]->service_path(), flag)); + if (isActive) { + label.clear(); + if (active_cellular->needs_new_plan()) { + label = l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_NO_PLAN_LABEL); + } else if (!active_cellular->GetDataPlans().empty()) { + const chromeos::CellularDataPlan& plan = + *active_cellular->GetDataPlans().begin(); + label = plan.GetUsageInfo(); + } + if (label.length()) { + menu_items_.push_back( + MenuItem(menus::MenuModel::TYPE_COMMAND, + label, SkBitmap(), + std::string(), FLAG_DISABLED)); + } + } } } // No networks available message. - if (no_networks) { + if (menu_items_.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, @@ -620,10 +669,8 @@ void NetworkMenu::InitMenuItems() { } // Add network. - if (wifi_available) { - // Separator - menu_items_.push_back(MenuItem()); - + if (wifi_available && wifi_enabled) { + menu_items_.push_back(MenuItem()); // Separator menu_items_.push_back(MenuItem( menus::MenuModel::TYPE_COMMAND, l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS), @@ -634,12 +681,11 @@ void NetworkMenu::InitMenuItems() { // Enable / disable wireless. if (wifi_available || cellular_available) { - // Separator - menu_items_.push_back(MenuItem()); + menu_items_.push_back(MenuItem()); // Separator if (wifi_available) { - int id = cros->wifi_enabled() ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE : - IDS_STATUSBAR_NETWORK_DEVICE_ENABLE; + int id = 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, @@ -647,8 +693,8 @@ void NetworkMenu::InitMenuItems() { } if (cellular_available) { - int id = cros->cellular_enabled() ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE : - IDS_STATUSBAR_NETWORK_DEVICE_ENABLE; + int id = 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, @@ -663,31 +709,24 @@ void NetworkMenu::InitMenuItems() { // l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OFFLINE_MODE), // SkBitmap(), std::string(), FLAG_TOGGLE_OFFLINE)); - bool connected = cros->Connected(); // alwasy call for test expectations. - bool show_ip = !MenuUI::IsEnabled() && connected; - bool show_settings = ShouldOpenButtonOptions(); - - // Separator. - if (show_ip || show_settings) { - menu_items_.push_back(MenuItem()); - } - - // IP Address - if (show_ip) { - menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, - ASCIIToUTF16(cros->IPAddress()), SkBitmap(), - std::string(), FLAG_DISABLED)); - } - - // Network settings. - if (show_settings) { - if (IsBrowserMode()) { - label = l10n_util::GetStringUTF16( - IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG); - } else { - label = l10n_util::GetStringUTF16( - IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG); + bool connected = cros->Connected(); // always call for test expectations. + bool oobe = !ShouldOpenButtonOptions(); // we don't show options for OOBE. + // Network settings. (And IP Address) + if (!oobe) { + menu_items_.push_back(MenuItem()); // Separator + + if (!MenuUI::IsEnabled() && connected) { + std::string ip_address = cros->IPAddress(); + if (!ip_address.empty()) { + menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, + ASCIIToUTF16(cros->IPAddress()), SkBitmap(), std::string(), + FLAG_DISABLED)); + } } + + label = l10n_util::GetStringUTF16(IsBrowserMode() ? + IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG : + IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG); menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label, SkBitmap(), std::string(), FLAG_OPTIONS)); } @@ -745,8 +784,9 @@ void NetworkMenu::ShowCellular(const CellularNetwork* cellular, void NetworkMenu::ActivateCellular(const CellularNetwork* cellular) const { DCHECK(cellular); Browser* browser = BrowserList::GetLastActive(); - // TODO(stevenjb) : specify which service to activate. - browser->ShowSingletonTab(GURL(chrome::kChromeUIMobileSetupURL)); + if (!browser) + return; + browser->OpenMobilePlanTabAndActivate(); } void NetworkMenu::ShowEthernet(const EthernetNetwork* ethernet) const { diff --git a/chrome/browser/chromeos/status/network_menu.h b/chrome/browser/chromeos/status/network_menu.h index 28f4d68..05b941e 100644 --- a/chrome/browser/chromeos/status/network_menu.h +++ b/chrome/browser/chromeos/status/network_menu.h @@ -52,7 +52,8 @@ class NetworkMenu : public views::ViewMenuDelegate, public menus::MenuModel { public: struct NetworkInfo { - NetworkInfo() : need_passphrase(false), remembered(true) {} + NetworkInfo() : + need_passphrase(false), remembered(true), auto_connect(true) {} // "ethernet" | "wifi" | "cellular" | "other". std::string network_type; // "connected" | "connecting" | "disconnected" | "error". @@ -67,6 +68,8 @@ class NetworkMenu : public views::ViewMenuDelegate, bool need_passphrase; // true if the network is currently remembered. bool remembered; + // true if the network is auto connect (meaningful for Wifi only). + bool auto_connect; }; NetworkMenu(); @@ -118,6 +121,11 @@ class NetworkMenu : public views::ViewMenuDelegate, // Returns the Icon for a network strength for CellularNetwork |cellular|. // This returns different colored bars depending on cellular data left. static SkBitmap IconForNetworkStrength(const CellularNetwork* cellular); + // Returns the Icon for animating network connecting. + // |animation_value| is the value from Animation.GetCurrentValue() + // |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 IconForNetworkConnecting(double animation_value, bool black); // Returns the Badge for a given network technology. // This returns different colored symbols depending on cellular data left. static SkBitmap BadgeForNetworkTechnology(const CellularNetwork* cellular); diff --git a/chrome/browser/chromeos/status/network_menu_button.cc b/chrome/browser/chromeos/status/network_menu_button.cc index 6d2486f..2a422d3 100644 --- a/chrome/browser/chromeos/status/network_menu_button.cc +++ b/chrome/browser/chromeos/status/network_menu_button.cc @@ -15,7 +15,6 @@ #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/window/window.h" @@ -52,16 +51,8 @@ NetworkMenuButton::~NetworkMenuButton() { void NetworkMenuButton::AnimationProgressed(const Animation* animation) { if (animation == &animation_connecting_) { - // Draw animation of bars icon fading in and out. - // We are fading between 0 bars and a third of the opacity of 4 bars. - // Use the current value of the animation to calculate the alpha value - // of how transparent the icon is. - SetIcon(SkBitmapOperations::CreateBlendedBitmap( - *ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_STATUSBAR_NETWORK_BARS0), - *ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_STATUSBAR_NETWORK_BARS4), - animation_connecting_.GetCurrentValue() / 3)); + SetIcon(IconForNetworkConnecting(animation_connecting_.GetCurrentValue(), + false)); SchedulePaint(); } else { MenuButton::AnimationProgressed(animation); @@ -82,28 +73,13 @@ void NetworkMenuButton::DrawIcon(gfx::Canvas* canvas) { void NetworkMenuButton::OnNetworkManagerChanged(NetworkLibrary* cros) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); if (CrosLibrary::Get()->EnsureLoaded()) { - // Add an observer for the active network, if any const Network* network = cros->active_network(); - if (active_network_.empty() || network == NULL || - active_network_ != network->service_path()) { - if (!active_network_.empty()) { - cros->RemoveNetworkObserver(active_network_, this); - } - if (network != NULL) { - cros->AddNetworkObserver(network->service_path(), this); - } - } - if (network) - active_network_ = network->service_path(); - else - active_network_ = ""; - if (cros->wifi_connecting() || cros->cellular_connecting()) { // Start the connecting animation if not running. if (!animation_connecting_.is_animating()) { animation_connecting_.Reset(); - animation_connecting_.StartThrobbing(std::numeric_limits::max()); - SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0)); + animation_connecting_.StartThrobbing(-1); + SetIcon(IconForNetworkConnecting(0, false)); } std::string network_name = cros->wifi_connecting() ? cros->wifi_network()->name() : cros->cellular_network()->name(); @@ -134,6 +110,7 @@ void NetworkMenuButton::OnNetworkManagerChanged(NetworkLibrary* cros) { IDS_STATUSBAR_NETWORK_NO_NETWORK_TOOLTIP)); } + RefreshNetworkObserver(cros); SchedulePaint(); UpdateMenu(); } @@ -154,6 +131,7 @@ void NetworkMenuButton::OnNetworkChanged(NetworkLibrary* cros, IDS_STATUSBAR_NETWORK_NO_NETWORK_TOOLTIP)); } + RefreshNetworkObserver(cros); SchedulePaint(); UpdateMenu(); } @@ -232,4 +210,18 @@ void NetworkMenuButton::SetNetworkBadge(NetworkLibrary* cros, } } +void NetworkMenuButton::RefreshNetworkObserver(NetworkLibrary* cros) { + const Network* network = cros->active_network(); + std::string new_network = network ? network->service_path() : std::string(); + if (active_network_ != new_network) { + if (!active_network_.empty()) { + cros->RemoveNetworkObserver(active_network_, this); + } + if (!new_network.empty()) { + cros->AddNetworkObserver(new_network, this); + } + active_network_ = new_network; + } +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/status/network_menu_button.h b/chrome/browser/chromeos/status/network_menu_button.h index 208efe2..3dfe007 100644 --- a/chrome/browser/chromeos/status/network_menu_button.h +++ b/chrome/browser/chromeos/status/network_menu_button.h @@ -83,6 +83,10 @@ class NetworkMenuButton : public StatusAreaButton, void SetNetworkIcon(const Network* network); void SetNetworkBadge(NetworkLibrary* cros, const Network* network); + // Called when the active network has possibly changed. This will remove + // old network observer and add a network observer for the active network. + void RefreshNetworkObserver(NetworkLibrary* cros); + // The status area host, StatusAreaHost* host_; diff --git a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc index 9e383bc..52ab1af 100644 --- a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc +++ b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc @@ -4,13 +4,13 @@ #include "chrome/browser/chromeos/status/power_menu_button.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" #include "chrome/browser/chromeos/cros/mock_power_library.h" #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/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "grit/theme_resources.h" namespace chromeos { diff --git a/chrome/browser/chromeos/status/status_area_button.cc b/chrome/browser/chromeos/status/status_area_button.cc index eb6c2d5..2ddaa20 100644 --- a/chrome/browser/chromeos/status/status_area_button.cc +++ b/chrome/browser/chromeos/status/status_area_button.cc @@ -17,7 +17,7 @@ namespace chromeos { StatusAreaButton::StatusAreaButton(views::ViewMenuDelegate* menu_delegate) : MenuButton(NULL, std::wstring(), menu_delegate, false), - use_menu_button_paint_(false) { + use_menu_button_paint_(false), enabled_(true) { set_border(NULL); // Use an offset that is top aligned with toolbar. @@ -81,4 +81,12 @@ void StatusAreaButton::DrawIcon(gfx::Canvas* canvas) { canvas->DrawBitmapInt(icon(), horizontal_padding(), 0); } +bool StatusAreaButton::Activate() { + if (enabled_) { + return views::MenuButton::Activate(); + } else { + return true; + } +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/status/status_area_button.h b/chrome/browser/chromeos/status/status_area_button.h index cefc474..fda3af8 100644 --- a/chrome/browser/chromeos/status/status_area_button.h +++ b/chrome/browser/chromeos/status/status_area_button.h @@ -29,6 +29,11 @@ class StatusAreaButton : public views::MenuButton { use_menu_button_paint_ = use_menu_button_paint; } + void Enable(bool enable) { enabled_ = enable; } + + // views::MenuButton overrides. + virtual bool Activate(); + protected: // Draws the icon for this status area button on the canvas. // Subclasses should override this method if they need to draw their own icon. @@ -49,6 +54,8 @@ class StatusAreaButton : public views::MenuButton { // Insets to use for this button. gfx::Insets insets_; + bool enabled_; + DISALLOW_COPY_AND_ASSIGN(StatusAreaButton); }; diff --git a/chrome/browser/chromeos/status/status_area_view.cc b/chrome/browser/chromeos/status/status_area_view.cc index 6a89d42..5adbcab 100644 --- a/chrome/browser/chromeos/status/status_area_view.cc +++ b/chrome/browser/chromeos/status/status_area_view.cc @@ -94,4 +94,12 @@ void StatusAreaView::ChildPreferredSizeChanged(View* child) { PreferredSizeChanged(); } +void StatusAreaView::EnableButtons(bool enable) { + clock_view()->Enable(enable); + feedback_view()->Enable(enable); + input_method_view()->Enable(enable); + network_view()->Enable(enable); + power_view()->Enable(enable); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/status/status_area_view.h b/chrome/browser/chromeos/status/status_area_view.h index 5fbae5f..7e76bc5 100644 --- a/chrome/browser/chromeos/status/status_area_view.h +++ b/chrome/browser/chromeos/status/status_area_view.h @@ -27,6 +27,7 @@ class StatusAreaView : public AccessiblePaneView { virtual ~StatusAreaView() {} virtual void Init(); + void EnableButtons(bool enable); // views::View* overrides. virtual gfx::Size GetPreferredSize(); diff --git a/chrome/browser/chromeos/system_key_event_listener.cc b/chrome/browser/chromeos/system_key_event_listener.cc index 999f5bb..74af308 100644 --- a/chrome/browser/chromeos/system_key_event_listener.cc +++ b/chrome/browser/chromeos/system_key_event_listener.cc @@ -84,18 +84,21 @@ GdkFilterReturn SystemKeyEventListener::GdkEventFilter(GdkXEvent* gxevent, if (xevent->type == KeyPress) { int32 keycode = xevent->xkey.keycode; if (keycode) { - if ((keycode == listener->key_f8_) || - (keycode == listener->key_volume_mute_)) { - listener->OnVolumeMute(); - return GDK_FILTER_REMOVE; - } else if ((keycode == listener->key_f9_) || - keycode == listener->key_volume_down_) { - listener->OnVolumeDown(); - return GDK_FILTER_REMOVE; - } else if ((keycode == listener->key_f10_) || - (keycode == listener->key_volume_up_)) { - listener->OnVolumeUp(); - return GDK_FILTER_REMOVE; + // Only doing non-Alt/Shift/Ctrl modified keys + if (!(xevent->xkey.state & (Mod1Mask | ShiftMask | ControlMask))) { + if ((keycode == listener->key_f8_) || + (keycode == listener->key_volume_mute_)) { + listener->OnVolumeMute(); + return GDK_FILTER_REMOVE; + } else if ((keycode == listener->key_f9_) || + keycode == listener->key_volume_down_) { + listener->OnVolumeDown(); + return GDK_FILTER_REMOVE; + } else if ((keycode == listener->key_f10_) || + (keycode == listener->key_volume_up_)) { + listener->OnVolumeUp(); + return GDK_FILTER_REMOVE; + } } } } diff --git a/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc b/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc index 97362b7..f94cfd0 100644 --- a/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc +++ b/chrome/browser/chromeos/tab_closeable_state_watcher_browsertest.cc @@ -6,13 +6,13 @@ #include "base/file_path.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/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/chromeos/update_browsertest.cc b/chrome/browser/chromeos/update_browsertest.cc index bbb67c3..2c0798d 100644 --- a/chrome/browser/chromeos/update_browsertest.cc +++ b/chrome/browser/chromeos/update_browsertest.cc @@ -4,11 +4,11 @@ #include "base/ref_counted.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.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/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/automation/dom_element_proxy.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/chromeos/usb_mount_observer.cc b/chrome/browser/chromeos/usb_mount_observer.cc index 3d0695f..734f8c6 100644 --- a/chrome/browser/chromeos/usb_mount_observer.cc +++ b/chrome/browser/chromeos/usb_mount_observer.cc @@ -4,14 +4,14 @@ #include "chrome/browser/chromeos/usb_mount_observer.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_window.h" +#include "base/command_line.h" #include "chrome/browser/dom_ui/filebrowse_ui.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/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" namespace chromeos { @@ -59,8 +59,8 @@ void USBMountObserver::OpenFileBrowse(const std::string& url, return; } profile = browser->profile(); - PrefService* pref_service = profile->GetPrefs(); - if (!pref_service->GetBoolean(prefs::kLabsAdvancedFilesystemEnabled)) { + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableAdvancedFileSystem)) { return; } if (small) { diff --git a/chrome/browser/chromeos/usb_mount_observer_browsertest.cc b/chrome/browser/chromeos/usb_mount_observer_browsertest.cc index e6a5c99..6c8d12e 100644 --- a/chrome/browser/chromeos/usb_mount_observer_browsertest.cc +++ b/chrome/browser/chromeos/usb_mount_observer_browsertest.cc @@ -4,12 +4,12 @@ #include "base/ref_counted.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/chromeos/cros/mock_mount_library.h" #include "chrome/browser/chromeos/usb_mount_observer.h" #include "chrome/browser/dom_ui/mediaplayer_ui.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/automation/dom_element_proxy.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/chromeos/user_cros_settings_provider.cc b/chrome/browser/chromeos/user_cros_settings_provider.cc new file mode 100644 index 0000000..1cdfd3a --- /dev/null +++ b/chrome/browser/chromeos/user_cros_settings_provider.cc @@ -0,0 +1,300 @@ +// 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/user_cros_settings_provider.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/cros/login_library.h" +#include "chrome/browser/chromeos/cros_settings.h" +#include "chrome/browser/chromeos/cros_settings_names.h" +#include "chrome/browser/chromeos/login/user_manager.h" +#include "chrome/browser/prefs/pref_service.h" + +namespace chromeos { + +namespace { + +Value* CreateSettingsBooleanValue(bool value, bool managed) { + DictionaryValue* dict = new DictionaryValue; + dict->Set("value", Value::CreateBooleanValue(value)); + dict->Set("managed", Value::CreateBooleanValue(managed)); + return dict; +} + +// static +void UpdateCacheBool(const char* name, bool value) { + PrefService* prefs = g_browser_process->local_state(); + prefs->SetBoolean(name, value); + prefs->ScheduleSavePersistentPrefs(); +} + +void UpdateCacheString(const char* name, const std::string& value) { + PrefService* prefs = g_browser_process->local_state(); + prefs->SetString(name, value); + prefs->ScheduleSavePersistentPrefs(); +} + +bool GetUserWhitelist(ListValue* user_list) { + std::vector whitelist; + if (!CrosLibrary::Get()->EnsureLoaded() || + !CrosLibrary::Get()->GetLoginLibrary()->EnumerateWhitelisted( + &whitelist)) { + LOG(WARNING) << "Failed to retrieve user whitelist."; + return false; + } + + PrefService* prefs = g_browser_process->local_state(); + ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); + cached_whitelist->Clear(); + + const UserManager::User& self = UserManager::Get()->logged_in_user(); + bool is_owner = UserManager::Get()->current_user_is_owner(); + + for (size_t i = 0; i < whitelist.size(); ++i) { + const std::string& email = whitelist[i]; + + if (user_list) { + DictionaryValue* user = new DictionaryValue; + user->SetString("email", email); + user->SetString("name", ""); + user->SetBoolean("owner", is_owner && email == self.email()); + user_list->Append(user); + } + + cached_whitelist->Append(Value::CreateStringValue(email)); + } + + prefs->ScheduleSavePersistentPrefs(); + + return true; +} + +} // namespace + +UserCrosSettingsProvider::UserCrosSettingsProvider() { + StartFetchingBoolSetting(kAccountsPrefAllowGuest); + StartFetchingBoolSetting(kAccountsPrefAllowNewUser); + StartFetchingBoolSetting(kAccountsPrefShowUserNamesOnSignIn); + StartFetchingStringSetting(kDeviceOwner); +} + +UserCrosSettingsProvider::~UserCrosSettingsProvider() { + // Cancels all pending callbacks from us. + SignedSettingsHelper::Get()->CancelCallback(this); +} + +// static +void UserCrosSettingsProvider::RegisterPrefs(PrefService* local_state) { + // Cached signed settings values + local_state->RegisterBooleanPref(kAccountsPrefAllowGuest, true); + local_state->RegisterBooleanPref(kAccountsPrefAllowNewUser, true); + local_state->RegisterBooleanPref(kAccountsPrefShowUserNamesOnSignIn, true); + local_state->RegisterListPref(kAccountsPrefUsers); + local_state->RegisterStringPref(kDeviceOwner, ""); +} + +// static +bool UserCrosSettingsProvider::cached_allow_guest() { + return g_browser_process->local_state()->GetBoolean(kAccountsPrefAllowGuest); +} + +// static +bool UserCrosSettingsProvider::cached_allow_new_user() { + return g_browser_process->local_state()->GetBoolean( + kAccountsPrefAllowNewUser); +} + +// static +bool UserCrosSettingsProvider::cached_show_users_on_signin() { + return g_browser_process->local_state()->GetBoolean( + kAccountsPrefShowUserNamesOnSignIn); +} + +// static +const ListValue* UserCrosSettingsProvider::cached_whitelist() { + PrefService* prefs = g_browser_process->local_state(); + const ListValue* cached_users = prefs->GetList(kAccountsPrefUsers); + + if (!cached_users) { + // Update whitelist cache. + GetUserWhitelist(NULL); + + cached_users = prefs->GetList(kAccountsPrefUsers); + } + + return cached_users; +} + +// static +std::string UserCrosSettingsProvider::cached_owner() { + if (!g_browser_process || !g_browser_process->local_state()) + return std::string(); + return g_browser_process->local_state()->GetString(kDeviceOwner); +} + +// static +bool UserCrosSettingsProvider::IsEmailInCachedWhitelist( + const std::string& email) { + const ListValue* whitelist = cached_whitelist(); + if (whitelist) { + StringValue email_value(email); + for (ListValue::const_iterator i(whitelist->begin()); + i != whitelist->end(); ++i) { + if ((*i)->Equals(&email_value)) + return true; + } + } + return false; +} + +void UserCrosSettingsProvider::DoSet(const std::string& path, + Value* in_value) { + if (!UserManager::Get()->current_user_is_owner()) { + LOG(WARNING) << "Changing settings from non-owner, setting=" << path; + + // Revert UI change. + CrosSettings::Get()->FireObservers(path.c_str()); + return; + } + + if (path == kAccountsPrefAllowGuest || + path == kAccountsPrefAllowNewUser || + path == kAccountsPrefShowUserNamesOnSignIn) { + bool bool_value = false; + if (in_value->GetAsBoolean(&bool_value)) { + std::string value = bool_value ? "true" : "false"; + SignedSettingsHelper::Get()->StartStorePropertyOp(path, value, this); + UpdateCacheBool(path.c_str(), bool_value); + + VLOG(1) << "Set cros setting " << path << "=" << value; + } + } else if (path == kDeviceOwner) { + VLOG(1) << "Setting owner is not supported. Please use 'UpdateCachedOwner' " + "instead."; + } else if (path == kAccountsPrefUsers) { + VLOG(1) << "Setting user whitelist is not implemented. Please use " + "whitelist/unwhitelist instead."; + } else { + LOG(WARNING) << "Try to set unhandled cros setting " << path; + } +} + +bool UserCrosSettingsProvider::Get(const std::string& path, + Value** out_value) const { + if (path == kAccountsPrefAllowGuest || + path == kAccountsPrefAllowNewUser || + path == kAccountsPrefShowUserNamesOnSignIn) { + *out_value = CreateSettingsBooleanValue( + g_browser_process->local_state()->GetBoolean(path.c_str()), + !UserManager::Get()->current_user_is_owner()); + return true; + } else if (path == kAccountsPrefUsers) { + ListValue* user_list = new ListValue; + GetUserWhitelist(user_list); + *out_value = user_list; + return true; + } + + return false; +} + +bool UserCrosSettingsProvider::HandlesSetting(const std::string& path) { + return ::StartsWithASCII(path, "cros.accounts.", true); +} + +void UserCrosSettingsProvider::OnWhitelistCompleted(bool success, + const std::string& email) { + VLOG(1) << "Add " << email << " to whitelist, success=" << success; + + // Reload the whitelist on settings op failure. + if (!success) + CrosSettings::Get()->FireObservers(kAccountsPrefUsers); +} + +void UserCrosSettingsProvider::OnUnwhitelistCompleted(bool success, + const std::string& email) { + VLOG(1) << "Remove " << email << " from whitelist, success=" << success; + + // Reload the whitelist on settings op failure. + if (!success) + CrosSettings::Get()->FireObservers(kAccountsPrefUsers); +} + +void UserCrosSettingsProvider::OnStorePropertyCompleted( + bool success, const std::string& name, const std::string& value) { + VLOG(1) << "Store cros setting " << name << "=" << value << ", success=" + << success; + + // Reload the setting if store op fails. + if (!success) + SignedSettingsHelper::Get()->StartRetrieveProperty(name, this); +} + +void UserCrosSettingsProvider::OnRetrievePropertyCompleted( + bool success, const std::string& name, const std::string& value) { + if (!success) { + LOG(WARNING) << "Failed to retrieve cros setting, name=" << name; + return; + } + + VLOG(1) << "Retrieved cros setting " << name << "=" << value; + + if (bool_settings_.count(name)) { + UpdateCacheBool(name.c_str(), value == "true" ? true : false); + } + + if (string_settings_.count(name)) { + UpdateCacheString(name.c_str(), value); + } + + CrosSettings::Get()->FireObservers(name.c_str()); +} + +void UserCrosSettingsProvider::WhitelistUser(const std::string& email) { + SignedSettingsHelper::Get()->StartWhitelistOp(email, true, this); + + PrefService* prefs = g_browser_process->local_state(); + ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); + cached_whitelist->Append(Value::CreateStringValue(email)); + prefs->ScheduleSavePersistentPrefs(); +} + +void UserCrosSettingsProvider::UnwhitelistUser(const std::string& email) { + SignedSettingsHelper::Get()->StartWhitelistOp(email, false, this); + + PrefService* prefs = g_browser_process->local_state(); + ListValue* cached_whitelist = prefs->GetMutableList(kAccountsPrefUsers); + StringValue email_value(email); + if (cached_whitelist->Remove(email_value) != -1) + prefs->ScheduleSavePersistentPrefs(); +} + +// static +void UserCrosSettingsProvider::UpdateCachedOwner(const std::string& email) { + UpdateCacheString(kDeviceOwner, email); +} + +void UserCrosSettingsProvider::StartFetchingBoolSetting( + const std::string& name) { + bool_settings_.insert(name); + StartFetchingSetting(name); +} + +void UserCrosSettingsProvider::StartFetchingStringSetting( + const std::string& name) { + string_settings_.insert(name); + StartFetchingSetting(name); +} + +void UserCrosSettingsProvider::StartFetchingSetting( + const std::string& name) { + if (CrosLibrary::Get()->EnsureLoaded()) + SignedSettingsHelper::Get()->StartRetrieveProperty(name, this); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/user_cros_settings_provider.h b/chrome/browser/chromeos/user_cros_settings_provider.h new file mode 100644 index 0000000..aa7db0f --- /dev/null +++ b/chrome/browser/chromeos/user_cros_settings_provider.h @@ -0,0 +1,76 @@ +// 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_USER_CROS_SETTINGS_PROVIDER_H_ +#define CHROME_BROWSER_CHROMEOS_USER_CROS_SETTINGS_PROVIDER_H_ +#pragma once + +#include + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "chrome/browser/chromeos/cros_settings_provider.h" +#include "chrome/browser/chromeos/login/signed_settings_helper.h" + +class ListValue; +class PrefService; + +namespace chromeos { + +class UserCrosSettingsProvider : public CrosSettingsProvider, + public SignedSettingsHelper::Callback { + public: + UserCrosSettingsProvider(); + virtual ~UserCrosSettingsProvider(); + + // Registers cached users settings in preferences. + static void RegisterPrefs(PrefService* local_state); + + // Helper functions to access cached settings. + static bool cached_allow_guest(); + static bool cached_allow_new_user(); + static bool cached_show_users_on_signin(); + static const ListValue* cached_whitelist(); + static std::string cached_owner(); + + // 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. + static bool IsEmailInCachedWhitelist(const std::string& email); + + // CrosSettingsProvider implementation. + virtual bool Get(const std::string& path, Value** out_value) const; + virtual bool HandlesSetting(const std::string& path); + + // SignedSettingsHelper::Callback overrides. + virtual void OnWhitelistCompleted(bool success, const std::string& email); + virtual void OnUnwhitelistCompleted(bool success, const std::string& email); + virtual void OnStorePropertyCompleted( + bool success, const std::string& name, const std::string& value); + virtual void OnRetrievePropertyCompleted( + bool success, const std::string& name, const std::string& value); + + void WhitelistUser(const std::string& email); + void UnwhitelistUser(const std::string& email); + + // Updates cached value of the owner. + static void UpdateCachedOwner(const std::string& email); + + private: + // CrosSettingsProvider implementation. + virtual void DoSet(const std::string& path, Value* value); + + void StartFetchingBoolSetting(const std::string& name); + void StartFetchingStringSetting(const std::string& name); + void StartFetchingSetting(const std::string& name); + + base::hash_set bool_settings_; + base::hash_set string_settings_; + + DISALLOW_COPY_AND_ASSIGN(UserCrosSettingsProvider); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_USER_CROS_SETTINGS_PROVIDER_H_ diff --git a/chrome/browser/chromeos/views/copy_background.cc b/chrome/browser/chromeos/views/copy_background.cc new file mode 100644 index 0000000..617fdc4 --- /dev/null +++ b/chrome/browser/chromeos/views/copy_background.cc @@ -0,0 +1,34 @@ +// 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/views/copy_background.h" + +#include "base/logging.h" +#include "gfx/canvas.h" +#include "views/background.h" +#include "views/view.h" + +namespace chromeos { + +CopyBackground::CopyBackground(views::View* copy_from) + : background_owner_(copy_from) { + DCHECK(background_owner_); + DCHECK(background_owner_->background()); +} + +void CopyBackground::Paint(gfx::Canvas* canvas, views::View* view) const { + const Background* background = background_owner_->background(); + DCHECK(background); + gfx::Point origin(0, 0); + views::View::ConvertPointToView(view, + background_owner_, + &origin); + canvas->Save(); + // Move the origin and paint as if it's paint onto the owner. + canvas->TranslateInt(-origin.x(), -origin.y()); + background->Paint(canvas, background_owner_); + canvas->Restore(); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/views/copy_background.h b/chrome/browser/chromeos/views/copy_background.h new file mode 100644 index 0000000..af4b018 --- /dev/null +++ b/chrome/browser/chromeos/views/copy_background.h @@ -0,0 +1,35 @@ +// 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_VIEWS_COPY_BACKGROUND_H_ +#define CHROME_BROWSER_CHROMEOS_VIEWS_COPY_BACKGROUND_H_ +#pragma once + +#include "views/background.h" + +namespace views { +class View; +} // namespace views + +namespace chromeos { + +// A background that copies the background renderer from +// other (typically one of parent chain) view. +class CopyBackground : public views::Background { + public: + explicit CopyBackground(views::View* copy_from); + virtual ~CopyBackground() {} + + // Overridden from views::Background. + virtual void Paint(gfx::Canvas* canvas, views::View* view) const; + + private: + views::View* background_owner_; + + DISALLOW_COPY_AND_ASSIGN(CopyBackground); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_VIEWS_COPY_BACKGROUND_H_ diff --git a/chrome/browser/chromeos/views/dropdown_button.cc b/chrome/browser/chromeos/views/dropdown_button.cc new file mode 100644 index 0000000..58e9d36 --- /dev/null +++ b/chrome/browser/chromeos/views/dropdown_button.cc @@ -0,0 +1,73 @@ +// 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 "app/resource_bundle.h" +#include "chrome/browser/chromeos/views/dropdown_button.h" +#include "gfx/canvas_skia.h" +#include "grit/theme_resources.h" + +namespace { +// Asset icon particularities makes us offset focus frame. +const int kFocusFrameTopOffset = 0; +const int kFocusFrameLeftOffset = 0; +const int kFocusFrameRightOffset = 0; +const int kFocusFrameBottomOffset = 1; + +// TextButtonBorder specification that uses different icons to draw the +// button. +class DropDownButtonBorder : public views::TextButtonBorder { + public: + DropDownButtonBorder(); + + private: + DISALLOW_COPY_AND_ASSIGN(DropDownButtonBorder); +}; + +DropDownButtonBorder::DropDownButtonBorder() { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + + hot_set_.top_left = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_LEFT_H); + hot_set_.top = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_H); + hot_set_.top_right = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_RIGHT_H); + hot_set_.left = rb.GetBitmapNamed(IDR_DROPDOWN_LEFT_H); + hot_set_.center = rb.GetBitmapNamed(IDR_DROPDOWN_CENTER_H); + hot_set_.right = rb.GetBitmapNamed(IDR_DROPDOWN_RIGHT_H); + hot_set_.bottom_left = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_LEFT_H); + hot_set_.bottom = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_H); + hot_set_.bottom_right = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_RIGHT_H); + + pushed_set_.top_left = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_LEFT_P); + pushed_set_.top = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_P); + pushed_set_.top_right = rb.GetBitmapNamed(IDR_DROPDOWN_TOP_RIGHT_P); + pushed_set_.left = rb.GetBitmapNamed(IDR_DROPDOWN_LEFT_P); + pushed_set_.center = rb.GetBitmapNamed(IDR_DROPDOWN_CENTER_P); + pushed_set_.right = rb.GetBitmapNamed(IDR_DROPDOWN_RIGHT_P); + pushed_set_.bottom_left = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_LEFT_P); + pushed_set_.bottom = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_P); + pushed_set_.bottom_right = rb.GetBitmapNamed(IDR_DROPDOWN_BOTTOM_RIGHT_P); +} + +} // namespace + +namespace chromeos { + +DropDownButton::DropDownButton(views::ButtonListener* listener, + const std::wstring& text, + views::ViewMenuDelegate* menu_delegate, + bool show_menu_marker) + : MenuButton(listener, text, menu_delegate, show_menu_marker) { + set_border(new DropDownButtonBorder); +} + +DropDownButton::~DropDownButton() { +} + +void DropDownButton::PaintFocusBorder(gfx::Canvas* canvas) { + if (HasFocus() && (IsFocusable() || IsAccessibilityFocusableInRootView())) + canvas->DrawFocusRect(kFocusFrameLeftOffset, kFocusFrameTopOffset, + width() - kFocusFrameRightOffset, + height() - kFocusFrameBottomOffset); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/views/dropdown_button.h b/chrome/browser/chromeos/views/dropdown_button.h new file mode 100644 index 0000000..637b7fa --- /dev/null +++ b/chrome/browser/chromeos/views/dropdown_button.h @@ -0,0 +1,33 @@ +// 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_VIEWS_DROPDOWN_BUTTON_H_ +#define CHROME_BROWSER_CHROMEOS_VIEWS_DROPDOWN_BUTTON_H_ +#pragma once + +#include + +#include "views/controls/button/menu_button.h" + +namespace chromeos { + +// MenuButton specification that uses different icons to draw the button and +// adjust focus frame accordingly to the icons particularities. +class DropDownButton : public views::MenuButton { + public: + DropDownButton(views::ButtonListener* listener, + const std::wstring& text, + views::ViewMenuDelegate* menu_delegate, + bool show_menu_marker); + virtual ~DropDownButton(); + + virtual void PaintFocusBorder(gfx::Canvas* canvas); + + private: + DISALLOW_COPY_AND_ASSIGN(DropDownButton); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_VIEWS_DROPDOWN_BUTTON_H_ diff --git a/chrome/browser/chromeos/views/native_menu_domui.cc b/chrome/browser/chromeos/views/native_menu_domui.cc index 5ce238c..ed30c93 100644 --- a/chrome/browser/chromeos/views/native_menu_domui.cc +++ b/chrome/browser/chromeos/views/native_menu_domui.cc @@ -9,13 +9,13 @@ #include "app/menus/menu_model.h" #include "base/message_loop.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/dom_ui/menu_ui.h" #include "chrome/browser/chromeos/views/domui_menu_widget.h" #include "chrome/browser/chromeos/views/menu_locator.h" #include "chrome/browser/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/url_constants.h" #include "gfx/rect.h" #include "views/controls/menu/menu_2.h" diff --git a/chrome/browser/chromeos/volume_bubble.cc b/chrome/browser/chromeos/volume_bubble.cc index f4e978d..512dac7 100644 --- a/chrome/browser/chromeos/volume_bubble.cc +++ b/chrome/browser/chromeos/volume_bubble.cc @@ -7,11 +7,11 @@ #include #include "base/timer.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/chromeos/volume_bubble_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/info_bubble.h" #include "views/widget/root_view.h" diff --git a/chrome/browser/chromeos/volume_bubble.h b/chrome/browser/chromeos/volume_bubble.h index c2da38e..addd7e4 100644 --- a/chrome/browser/chromeos/volume_bubble.h +++ b/chrome/browser/chromeos/volume_bubble.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_H_ #pragma once +#include "app/animation_delegate.h" #include "app/slide_animation.h" #include "base/singleton.h" #include "chrome/browser/views/info_bubble.h" diff --git a/chrome/browser/chromeos/wm_overview_controller.cc b/chrome/browser/chromeos/wm_overview_controller.cc index 785651a..2d56e7b 100644 --- a/chrome/browser/chromeos/wm_overview_controller.cc +++ b/chrome/browser/chromeos/wm_overview_controller.cc @@ -8,7 +8,6 @@ #include #include "base/linked_ptr.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/chromeos/wm_overview_fav_icon.h" @@ -21,6 +20,7 @@ #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/ui/browser.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_snapshot.cc b/chrome/browser/chromeos/wm_overview_snapshot.cc index dccf223..2182273 100644 --- a/chrome/browser/chromeos/wm_overview_snapshot.cc +++ b/chrome/browser/chromeos/wm_overview_snapshot.cc @@ -7,9 +7,9 @@ #include #include "app/x11_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chromeos/wm_ipc.h" +#include "chrome/browser/ui/browser.h" #include "views/controls/image_view.h" #include "views/controls/label.h" #include "views/grid_layout.h" diff --git a/chrome/browser/chromeos/wm_overview_title.cc b/chrome/browser/chromeos/wm_overview_title.cc index 0325065..a5ce96e 100644 --- a/chrome/browser/chromeos/wm_overview_title.cc +++ b/chrome/browser/chromeos/wm_overview_title.cc @@ -9,11 +9,11 @@ #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" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/chromeos/wm_overview_snapshot.h" +#include "chrome/browser/ui/browser.h" #include "cros/chromeos_wm_ipc_enums.h" #include "third_party/skia/include/core/SkBitmap.h" #include "views/border.h" diff --git a/chrome/browser/cocoa/applescript/window_applescript.mm b/chrome/browser/cocoa/applescript/window_applescript.mm index 07401d3..7f5e6a5 100644 --- a/chrome/browser/cocoa/applescript/window_applescript.mm +++ b/chrome/browser/cocoa/applescript/window_applescript.mm @@ -11,7 +11,6 @@ #import "chrome/browser/app_controller_mac.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/browser_window.h" #import "chrome/browser/chrome_browser_application_mac.h" #include "chrome/browser/cocoa/applescript/constants_applescript.h" @@ -20,6 +19,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser_navigator.h" #include "chrome/common/url_constants.h" @interface WindowAppleScript(WindowAppleScriptPrivateMethods) diff --git a/chrome/browser/cocoa/browser_test_helper.h b/chrome/browser/cocoa/browser_test_helper.h index f09bf10..22d0efc 100644 --- a/chrome/browser/cocoa/browser_test_helper.h +++ b/chrome/browser/cocoa/browser_test_helper.h @@ -6,9 +6,9 @@ #define CHROME_BROWSER_COCOA_BROWSER_TEST_HELPER_H_ #pragma once -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/testing_profile.h" // Base class which contains a valid Browser*. Lots of boilerplate to diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index 9a46f7d..486ec11 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -66,7 +66,6 @@ class BrowserWindowCocoa : public BrowserWindow, virtual bool IsBookmarkBarVisible() const; virtual bool IsBookmarkBarAnimating() const; virtual bool IsToolbarVisible() const; - virtual gfx::Rect GetRootWindowResizerRect() const; virtual void ConfirmAddSearchProvider(const TemplateURL* template_url, Profile* profile); virtual void ToggleBookmarkBar(); @@ -107,6 +106,7 @@ class BrowserWindowCocoa : public BrowserWindow, virtual void Paste(); virtual void ToggleTabStripMode(); virtual void OpenTabpose(); + virtual void PrepareForInstant(); virtual void ShowInstant(TabContents* preview_contents); virtual void HideInstant(); virtual gfx::Rect GetInstantBounds(); diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 5e21af0..5ce7156 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -216,11 +216,6 @@ bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const { return false; } -gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const { - NSRect tabRect = [controller_ selectedTabGrowBoxRect]; - return gfx::Rect(NSRectToCGRect(tabRect)); -} - void BrowserWindowCocoa::ConfirmAddSearchProvider( const TemplateURL* template_url, Profile* profile) { @@ -577,6 +572,10 @@ void BrowserWindowCocoa::OpenTabpose() { [controller_ openTabpose]; } +void BrowserWindowCocoa::PrepareForInstant() { + // TODO: implement fade as done on windows. +} + void BrowserWindowCocoa::ShowInstant(TabContents* preview_contents) { [controller_ showInstant:preview_contents]; } diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index 39bd9c4..ce55ec6 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -18,6 +18,7 @@ #import "chrome/browser/cocoa/bookmarks/bookmark_bar_controller.h" #import "chrome/browser/cocoa/bookmarks/bookmark_bubble_controller.h" #import "chrome/browser/cocoa/browser_command_executor.h" +#import "chrome/browser/cocoa/tab_contents_controller.h" #import "chrome/browser/cocoa/tab_strip_controller.h" #import "chrome/browser/cocoa/tab_window_controller.h" #import "chrome/browser/cocoa/themed_window.h" @@ -52,6 +53,7 @@ class TabContents; BookmarkBarControllerDelegate, BrowserCommandExecutor, ViewResizer, + TabContentsControllerDelegate, TabStripControllerDelegate> { @private // The ordering of these members is important as it determines the order in @@ -170,10 +172,6 @@ class TabContents; // Sets whether or not the current page in the frontmost tab is bookmarked. - (void)setStarredState:(BOOL)isStarred; -// Return the rect, in WebKit coordinates (flipped), of the window's grow box -// in the coordinate system of the content area of the currently selected tab. -- (NSRect)selectedTabGrowBoxRect; - // Called to tell the selected tab to update its loading state. // |force| is set if the update is due to changing tabs, as opposed to // the page-load finishing. See comment in reload_button.h. diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 0e39267..b074603 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -46,6 +46,7 @@ #import "chrome/browser/cocoa/toolbar_controller.h" #include "chrome/browser/dock_info.h" #include "chrome/browser/encoding_menu_controller.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" @@ -56,6 +57,7 @@ #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/themes/browser_theme_provider.h" #include "chrome/browser/window_sizer.h" +#include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -238,14 +240,15 @@ // Create a sub-controller for the docked devTools and add its view to the // hierarchy. This must happen before the sidebar controller is // instantiated. - devToolsController_.reset([[DevToolsController alloc] init]); + devToolsController_.reset( + [[DevToolsController alloc] initWithDelegate:self]); [[devToolsController_ view] setFrame:[[self tabContentArea] bounds]]; [[self tabContentArea] addSubview:[devToolsController_ view]]; // Create a sub-controller for the docked sidebar and add its view to the // hierarchy. This must happen before the previewable contents controller // is instantiated. - sidebarController_.reset([[SidebarController alloc] init]); + sidebarController_.reset([[SidebarController alloc] initWithDelegate:self]); [[sidebarController_ view] setFrame:[[devToolsController_ view] bounds]]; [[devToolsController_ view] addSubview:[sidebarController_ view]]; @@ -442,10 +445,12 @@ - (void)updateDevToolsForContents:(TabContents*)contents { [devToolsController_ updateDevToolsForTabContents:contents]; + [devToolsController_ ensureContentsVisible]; } - (void)updateSidebarForContents:(TabContents*)contents { [sidebarController_ updateSidebarForTabContents:contents]; + [sidebarController_ ensureContentsVisible]; } // Called when the user wants to close a window or from the shutdown process. @@ -1043,24 +1048,6 @@ [toolbarController_ setStarredState:isStarred]; } -// Return the rect, in WebKit coordinates (flipped), of the window's grow box -// in the coordinate system of the content area of the currently selected tab. -// |windowGrowBox| needs to be in the window's coordinate system. -- (NSRect)selectedTabGrowBoxRect { - NSWindow* window = [self window]; - if (![window respondsToSelector:@selector(_growBoxRect)]) - return NSZeroRect; - - // Before we return a rect, we need to convert it from window coordinates - // to tab content area coordinates and flip the coordinate system. - NSRect growBoxRect = - [[self tabContentArea] convertRect:[window _growBoxRect] fromView:nil]; - growBoxRect.origin.y = - [[self tabContentArea] frame].size.height - growBoxRect.size.height - - growBoxRect.origin.y; - return growBoxRect; -} - // Accept tabs from a BrowserWindowController with the same Profile. - (BOOL)canReceiveFrom:(TabWindowController*)source { if (![source isKindOfClass:[BrowserWindowController class]]) { @@ -1350,6 +1337,44 @@ return [self supportsWindowFeature:Browser::FEATURE_TABSTRIP]; } +// TabContentsControllerDelegate protocol. +- (void)tabContentsViewFrameWillChange:(TabContentsController*)source + frameRect:(NSRect)frameRect { + TabContents* contents = [source tabContents]; + RenderWidgetHostView* render_widget_host_view = contents ? + contents->GetRenderWidgetHostView() : NULL; + if (!render_widget_host_view) + return; + + gfx::Rect reserved_rect; + + NSWindow* window = [self window]; + if ([window respondsToSelector:@selector(_growBoxRect)]) { + NSView* view = [source view]; + NSRect windowGrowBoxRect = [window _growBoxRect]; + NSRect viewRect = [[view superview] convertRect:frameRect toView:nil]; + NSRect growBoxRect = NSIntersectionRect(windowGrowBoxRect, viewRect); + if (!NSIsEmptyRect(growBoxRect)) { + // Before we return a rect, we need to convert it from window coordinates + // to content area coordinates and flip the coordinate system. + // Superview is used here because, first, it's a frame rect, so it is + // specified in the parent's coordinates and, second, view is not + // positioned yet. + growBoxRect = [[view superview] convertRect:growBoxRect fromView:nil]; + growBoxRect.origin.y = + NSHeight(frameRect) - NSHeight(growBoxRect); + growBoxRect = + NSOffsetRect(growBoxRect, -frameRect.origin.x, -frameRect.origin.y); + + reserved_rect = + gfx::Rect(growBoxRect.origin.x, growBoxRect.origin.y, + growBoxRect.size.width, growBoxRect.size.height); + } + } + + render_widget_host_view->set_reserved_contents_rect(reserved_rect); +} + // TabStripControllerDelegate protocol. - (void)onSelectTabWithContents:(TabContents*)contents { // Update various elements that are interested in knowing the current @@ -1358,8 +1383,8 @@ // Update all the UI bits. windowShim_->UpdateTitleBar(); - [self updateSidebarForContents:contents]; - [self updateDevToolsForContents:contents]; + [sidebarController_ updateSidebarForTabContents:contents]; + [devToolsController_ updateDevToolsForTabContents:contents]; // Update the bookmark bar. // Must do it after sidebar and devtools update, otherwise bookmark bar might @@ -1369,6 +1394,10 @@ [self updateBookmarkBarVisibilityWithAnimation:NO]; [infoBarContainerController_ changeTabContents:contents]; + + // Update devTools and sidebar contents after size for all views is set. + [sidebarController_ ensureContentsVisible]; + [devToolsController_ ensureContentsVisible]; } - (void)onReplaceTabWithContents:(TabContents*)contents { @@ -1615,9 +1644,9 @@ SadTabController* sad_tab = static_cast(sender); TabContents* tab_contents = [sad_tab tabContents]; if (tab_contents) { - std::string linkUrl = l10n_util::GetStringUTF8(IDS_CRASH_REASON_URL); - tab_contents->OpenURL(GURL(linkUrl), GURL(), CURRENT_TAB, - PageTransition::LINK); + GURL helpUrl = + google_util::AppendGoogleLocaleParam(GURL(chrome::kCrashReasonURL)); + tab_contents->OpenURL(helpUrl, GURL(), CURRENT_TAB, PageTransition::LINK); } } } diff --git a/chrome/browser/cocoa/content_exceptions_window_controller.h b/chrome/browser/cocoa/content_exceptions_window_controller.h index ede76f7..98af089 100644 --- a/chrome/browser/cocoa/content_exceptions_window_controller.h +++ b/chrome/browser/cocoa/content_exceptions_window_controller.h @@ -10,6 +10,7 @@ #include "chrome/common/content_settings_types.h" class ContentExceptionsTableModel; +class ContentSettingComboModel; class UpdatingContentSettingsObserver; // Controller for the content exception dialogs. @@ -28,9 +29,7 @@ class UpdatingContentSettingsObserver; HostContentSettingsMap* settingsMap_; // weak HostContentSettingsMap* otrSettingsMap_; // weak scoped_ptr model_; - - // Is set if "Session" should be a valid option in the "action" popup. - BOOL showSession_; + scoped_ptr popup_model_; // Is set if adding and editing exceptions for the current OTR session should // be allowed. diff --git a/chrome/browser/cocoa/content_exceptions_window_controller.mm b/chrome/browser/cocoa/content_exceptions_window_controller.mm index e589261..b50204f 100644 --- a/chrome/browser/cocoa/content_exceptions_window_controller.mm +++ b/chrome/browser/cocoa/content_exceptions_window_controller.mm @@ -12,6 +12,7 @@ #import "base/scoped_nsobject.h" #include "base/sys_string_conversions.h" #include "chrome/browser/content_exceptions_table_model.h" +#include "chrome/browser/content_setting_combo_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" @@ -27,10 +28,7 @@ forOtr:(BOOL)isOtr; - (void)adjustEditingButtons; - (void)modelDidChange; -- (size_t)menuItemCount; - (NSString*)titleForIndex:(size_t)index; -- (ContentSetting)settingForIndex:(size_t)index; -- (size_t)indexForSetting:(ContentSetting)setting; @end //////////////////////////////////////////////////////////////////////////////// @@ -126,20 +124,6 @@ NSString* GetWindowTitle(ContentSettingsType settingsType) { const CGFloat kButtonBarHeight = 35.0; -// The settings shown in the combobox for plug-ins; -const ContentSetting kPluginSettings[] = { CONTENT_SETTING_ALLOW, - CONTENT_SETTING_ASK, - CONTENT_SETTING_BLOCK }; - -// The settings shown in the combobox if showSession_ is false; -const ContentSetting kNoSessionSettings[] = { CONTENT_SETTING_ALLOW, - CONTENT_SETTING_BLOCK }; - -// The settings shown in the combobox if showSession_ is true; -const ContentSetting kSessionSettings[] = { CONTENT_SETTING_ALLOW, - CONTENT_SETTING_SESSION_ONLY, - CONTENT_SETTING_BLOCK }; - } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -175,7 +159,7 @@ static ContentExceptionsWindowController* otrSettingsMap_ = otrSettingsMap; model_.reset(new ContentExceptionsTableModel( settingsMap_, otrSettingsMap_, settingsType_)); - showSession_ = settingsType_ == CONTENT_SETTINGS_TYPE_COOKIES; + popup_model_.reset(new ContentSettingComboModel(settingsType_)); otrAllowed_ = otrSettingsMap != NULL; tableObserver_.reset(new UpdatingContentSettingsObserver(self)); updatesEnabled_ = YES; @@ -203,10 +187,12 @@ static ContentExceptionsWindowController* // Initialize menu for the data cell in the "action" column. scoped_nsobject menu([[NSMenu alloc] initWithTitle:@"exceptionMenu"]); - for (size_t i = 0; i < [self menuItemCount]; ++i) { - scoped_nsobject allowItem([[NSMenuItem alloc] - initWithTitle:[self titleForIndex:i] action:NULL keyEquivalent:@""]); - [allowItem.get() setTag:[self settingForIndex:i]]; + for (int i = 0; i < popup_model_->GetItemCount(); ++i) { + NSString* title = + l10n_util::FixUpWindowsStyleLabel(popup_model_->GetItemAt(i)); + scoped_nsobject allowItem( + [[NSMenuItem alloc] initWithTitle:title action:NULL keyEquivalent:@""]); + [allowItem.get() setTag:popup_model_->SettingForIndex(i)]; [menu.get() addItem:allowItem.get()]; } NSCell* menuCell = @@ -375,7 +361,8 @@ static ContentExceptionsWindowController* if ([identifier isEqualToString:@"pattern"]) { result = base::SysUTF8ToNSString(entry->first.AsString()); } else if ([identifier isEqualToString:@"action"]) { - result = [NSNumber numberWithInt:[self indexForSetting:entry->second]]; + result = + [NSNumber numberWithInt:popup_model_->IndexForSetting(entry->second)]; } else if ([identifier isEqualToString:@"otr"]) { result = [NSNumber numberWithInt:isOtr]; } else { @@ -436,7 +423,7 @@ static ContentExceptionsWindowController* } if ([identifier isEqualToString:@"action"]) { int index = [object intValue]; - entry.second = [self settingForIndex:index]; + entry.second = popup_model_->SettingForIndex(index); } if ([identifier isEqualToString:@"otr"]) { isOtr = [object intValue] != 0; @@ -500,43 +487,4 @@ static ContentExceptionsWindowController* [self adjustEditingButtons]; } -- (size_t)menuItemCount { - if (settingsType_ == CONTENT_SETTINGS_TYPE_PLUGINS) - return arraysize(kPluginSettings); - return showSession_ ? arraysize(kSessionSettings) - : arraysize(kNoSessionSettings); -} - -- (NSString*)titleForIndex:(size_t)index { - switch ([self settingForIndex:index]) { - case CONTENT_SETTING_ALLOW: - return l10n_util::GetNSStringWithFixup(IDS_EXCEPTIONS_ALLOW_BUTTON); - case CONTENT_SETTING_ASK: - return l10n_util::GetNSStringWithFixup(IDS_EXCEPTIONS_ASK_BUTTON); - case CONTENT_SETTING_BLOCK: - return l10n_util::GetNSStringWithFixup(IDS_EXCEPTIONS_BLOCK_BUTTON); - case CONTENT_SETTING_SESSION_ONLY: - return l10n_util::GetNSStringWithFixup( - IDS_EXCEPTIONS_SESSION_ONLY_BUTTON); - default: - NOTREACHED(); - } - return @""; -} - -- (ContentSetting)settingForIndex:(size_t)index { - if (settingsType_ == CONTENT_SETTINGS_TYPE_PLUGINS) - return kPluginSettings[index]; - return showSession_ ? kSessionSettings[index] : kNoSessionSettings[index]; -} - -- (size_t)indexForSetting:(ContentSetting)setting { - for (size_t i = 0; i < [self menuItemCount]; ++i) { - if ([self settingForIndex:i] == setting) - return i; - } - NOTREACHED(); - return 0; -} - @end diff --git a/chrome/browser/cocoa/content_setting_bubble_cocoa.mm b/chrome/browser/cocoa/content_setting_bubble_cocoa.mm index dda55f5..dc8b967 100644 --- a/chrome/browser/cocoa/content_setting_bubble_cocoa.mm +++ b/chrome/browser/cocoa/content_setting_bubble_cocoa.mm @@ -391,32 +391,17 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) { } - (void)sizeToFitLoadPluginsButton { - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableClickToPlay)) { - const ContentSettingBubbleModel::BubbleContent& content = - contentSettingBubbleModel_->bubble_content(); - [loadAllPluginsButton_ setEnabled:content.load_plugins_link_enabled]; - - // Resize horizontally to fit button if necessary. - NSRect windowFrame = [[self window] frame]; - int widthNeeded = NSWidth([loadAllPluginsButton_ frame]) + - 2 * NSMinX([loadAllPluginsButton_ frame]); - if (NSWidth(windowFrame) < widthNeeded) { - windowFrame.size.width = widthNeeded; - [[self window] setFrame:windowFrame display:NO]; - } - } else { - // Remove button and resize vertically. - int deltaY = kLoadAllPluginsButtonVerticalPadding + - NSHeight([loadAllPluginsButton_ frame]); - [loadAllPluginsButton_ removeFromSuperview]; - NSRect frame = [[self window] frame]; - frame.size.height -= deltaY; - [[self window] setFrame:frame display:NO]; - NSPoint radioOrigin = [allowBlockRadioGroup_ frame].origin; - radioOrigin.y -= deltaY; - [allowBlockRadioGroup_ setFrameOrigin:radioOrigin]; - [allowBlockRadioGroup_ setNeedsDisplay]; + const ContentSettingBubbleModel::BubbleContent& content = + contentSettingBubbleModel_->bubble_content(); + [loadAllPluginsButton_ setEnabled:content.load_plugins_link_enabled]; + + // Resize horizontally to fit button if necessary. + NSRect windowFrame = [[self window] frame]; + int widthNeeded = NSWidth([loadAllPluginsButton_ frame]) + + 2 * NSMinX([loadAllPluginsButton_ frame]); + if (NSWidth(windowFrame) < widthNeeded) { + windowFrame.size.width = widthNeeded; + [[self window] setFrame:windowFrame display:NO]; } } diff --git a/chrome/browser/cocoa/content_settings_dialog_controller.h b/chrome/browser/cocoa/content_settings_dialog_controller.h index 45601ce..40e9a04 100644 --- a/chrome/browser/cocoa/content_settings_dialog_controller.h +++ b/chrome/browser/cocoa/content_settings_dialog_controller.h @@ -48,6 +48,7 @@ class Profile; @private IBOutlet NSTabView* tabView_; IBOutlet TabViewPickerTable* tabViewPicker_; + IBOutlet NSMatrix* pluginDefaultSettingMatrix_; Profile* profile_; // weak IntegerPrefMember lastSelectedTab_; BooleanPrefMember clearSiteDataOnExit_; diff --git a/chrome/browser/cocoa/content_settings_dialog_controller.mm b/chrome/browser/cocoa/content_settings_dialog_controller.mm index 910e127..d9fedc1 100644 --- a/chrome/browser/cocoa/content_settings_dialog_controller.mm +++ b/chrome/browser/cocoa/content_settings_dialog_controller.mm @@ -187,6 +187,24 @@ class PrefObserverDisabler { label = [label stringByReplacingOccurrencesOfString:@":" withString:@""]; [tabViewPicker_ setHeading:label]; + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)) { + // The |pluginsEnabledIndex| property is bound to the selected *tag*, + // so we don't have to worry about index shifts when removing a row + // from the matrix. + [pluginDefaultSettingMatrix_ removeRow:kPluginsAskIndex]; + NSArray* siblingViews = [[pluginDefaultSettingMatrix_ superview] subviews]; + for (NSView* view in siblingViews) { + NSRect frame = [view frame]; + if (frame.origin.y < [pluginDefaultSettingMatrix_ frame].origin.y) { + frame.origin.y += + ([pluginDefaultSettingMatrix_ cellSize].height + + [pluginDefaultSettingMatrix_ intercellSpacing].height); + [view setFrame:frame]; + } + } + } + NSRect frame = [[self window] frame]; frame.origin.y -= windowDelta; frame.size.height += windowDelta; @@ -430,9 +448,15 @@ class PrefObserverDisabler { ContentSetting setting = map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS); switch (setting) { - case CONTENT_SETTING_ALLOW: return kPluginsAllowIndex; - case CONTENT_SETTING_ASK: return kPluginsAskIndex; - case CONTENT_SETTING_BLOCK: return kPluginsBlockIndex; + case CONTENT_SETTING_ALLOW: + return kPluginsAllowIndex; + case CONTENT_SETTING_ASK: + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)) + return kPluginsAskIndex; + // Fall through to the next case. + case CONTENT_SETTING_BLOCK: + return kPluginsBlockIndex; default: NOTREACHED(); return kPluginsAllowIndex; diff --git a/chrome/browser/cocoa/content_settings_dialog_controller_unittest.mm b/chrome/browser/cocoa/content_settings_dialog_controller_unittest.mm index 405082c..3558b62 100644 --- a/chrome/browser/cocoa/content_settings_dialog_controller_unittest.mm +++ b/chrome/browser/cocoa/content_settings_dialog_controller_unittest.mm @@ -4,6 +4,8 @@ #import "chrome/browser/cocoa/content_settings_dialog_controller.h" +#include "base/auto_reset.h" +#include "base/command_line.h" #import "base/scoped_nsobject.h" #include "base/ref_counted.h" #include "chrome/browser/cocoa/browser_test_helper.h" @@ -13,6 +15,7 @@ #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/pref_names.h" +#include "chrome/common/chrome_switches.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -164,9 +167,16 @@ TEST_F(ContentSettingsDialogControllerTest, PluginsSetting) { CONTENT_SETTING_BLOCK); EXPECT_EQ(kPluginsBlockIndex, [controller_ pluginsEnabledIndex]); - settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, - CONTENT_SETTING_ASK); - EXPECT_EQ(kPluginsAskIndex, [controller_ pluginsEnabledIndex]); + { + // Click-to-play needs to be enabled to set the content setting to ASK. + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableClickToPlay); + + settingsMap_->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, + CONTENT_SETTING_ASK); + EXPECT_EQ(kPluginsAskIndex, [controller_ pluginsEnabledIndex]); + } // Change dialog property, check setting. NSInteger setting; @@ -180,10 +190,16 @@ TEST_F(ContentSettingsDialogControllerTest, PluginsSetting) { settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS); EXPECT_EQ(CONTENT_SETTING_BLOCK, setting); - [controller_ setPluginsEnabledIndex:kPluginsAskIndex]; - setting = - settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS); - EXPECT_EQ(CONTENT_SETTING_ASK, setting); + { + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableClickToPlay); + + [controller_ setPluginsEnabledIndex:kPluginsAskIndex]; + setting = + settingsMap_->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS); + EXPECT_EQ(CONTENT_SETTING_ASK, setting); + } } TEST_F(ContentSettingsDialogControllerTest, PopupsSetting) { diff --git a/chrome/browser/cocoa/dev_tools_controller.h b/chrome/browser/cocoa/dev_tools_controller.h index 774d799..05aaca4 100644 --- a/chrome/browser/cocoa/dev_tools_controller.h +++ b/chrome/browser/cocoa/dev_tools_controller.h @@ -9,6 +9,7 @@ #import #include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/tab_contents_controller.h" @class NSSplitView; @class NSView; @@ -22,9 +23,12 @@ class TabContents; @private // A view hosting docked devTools contents. scoped_nsobject splitView_; + + // Manages currently displayed devTools contents. + scoped_nsobject contentsController_; } -- (id)init; +- (id)initWithDelegate:(id)delegate; // This controller's view. - (NSView*)view; @@ -38,6 +42,10 @@ class TabContents; // the actual resize). - (void)updateDevToolsForTabContents:(TabContents*)contents; +// Call when the devTools view is properly sized and the render widget host view +// should be put into the view hierarchy. +- (void)ensureContentsVisible; + @end #endif // CHROME_BROWSER_COCOA_DEV_TOOLS_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/dev_tools_controller.mm b/chrome/browser/cocoa/dev_tools_controller.mm index c9cf4e1..cba5822 100644 --- a/chrome/browser/cocoa/dev_tools_controller.mm +++ b/chrome/browser/cocoa/dev_tools_controller.mm @@ -36,16 +36,26 @@ const int kMinWebHeight = 50; @implementation DevToolsController -- (id)init { +- (id)initWithDelegate:(id)delegate { if ((self = [super init])) { splitView_.reset([[NSSplitView alloc] initWithFrame:NSZeroRect]); [splitView_ setDividerStyle:NSSplitViewDividerStyleThin]; [splitView_ setVertical:NO]; [splitView_ setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + [splitView_ setDelegate:self]; + + contentsController_.reset( + [[TabContentsController alloc] initWithContents:NULL + delegate:delegate]); } return self; } +- (void)dealloc { + [splitView_ setDelegate:nil]; + [super dealloc]; +} + - (NSView*)view { return splitView_.get(); } @@ -62,7 +72,13 @@ const int kMinWebHeight = 50; [self showDevToolsContents:devToolsContents]; } +- (void)ensureContentsVisible { + [contentsController_ ensureContentsVisible]; +} + - (void)showDevToolsContents:(TabContents*)devToolsContents { + [contentsController_ ensureContentsSizeDoesNotChange]; + NSArray* subviews = [splitView_ subviews]; if (devToolsContents) { DCHECK_GE([subviews count], 1u); @@ -70,8 +86,8 @@ const int kMinWebHeight = 50; // |devToolsView| is a TabContentsViewCocoa object, whose ViewID was // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to // VIEW_ID_DEV_TOOLS_DOCKED here. - NSView* devToolsView = devToolsContents->GetNativeView(); - view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED); + view_id_util::SetID( + devToolsContents->GetNativeView(), VIEW_ID_DEV_TOOLS_DOCKED); CGFloat splitOffset = 0; if ([subviews count] == 1) { @@ -82,13 +98,11 @@ const int kMinWebHeight = 50; // Initial load, set to default value. splitOffset = kDefaultContentsSplitOffset; } - [splitView_ addSubview:devToolsView]; + [splitView_ addSubview:[contentsController_ view]]; } else { DCHECK_EQ([subviews count], 2u); // If devtools are already visible, keep the current size. - splitOffset = NSHeight([devToolsView frame]); - [splitView_ replaceSubview:[subviews objectAtIndex:1] - with:devToolsView]; + splitOffset = NSHeight([[subviews objectAtIndex:1] frame]); } // Make sure |splitOffset| isn't too large or too small. @@ -107,8 +121,11 @@ const int kMinWebHeight = 50; g_browser_process->local_state()->SetInteger( prefs::kDevToolsSplitLocation, splitOffset); [oldDevToolsContentsView removeFromSuperview]; + [splitView_ adjustSubviews]; } } + + [contentsController_ changeTabContents:devToolsContents]; } - (void)resizeDevToolsToNewHeight:(CGFloat)height { @@ -132,6 +149,16 @@ const int kMinWebHeight = 50; [splitView_ adjustSubviews]; } - +// NSSplitViewDelegate protocol. +- (BOOL)splitView:(NSSplitView *)splitView + shouldAdjustSizeOfSubview:(NSView *)subview { + // Return NO for the devTools view to indicate that it should not be resized + // automatically. It preserves the height set by the user and also keeps + // view height the same while changing tabs when one of the tabs shows infobar + // and others are not. + if ([[splitView_ subviews] indexOfObject:subview] == 1) + return NO; + return YES; +} @end diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.h b/chrome/browser/cocoa/extension_installed_bubble_controller.h index e5f50a3..7d0417f 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller.h +++ b/chrome/browser/cocoa/extension_installed_bubble_controller.h @@ -33,8 +33,9 @@ const int kInnerVerticalMargin = 10; // We use a different kind of notification for each of these extension types. typedef enum { kBrowserAction, - kPageAction, - kGeneric + kGeneric, + kOmniboxKeyword, + kPageAction } ExtensionType; } @@ -68,7 +69,8 @@ typedef enum { IBOutlet HoverCloseButton* closeButton_; IBOutlet NSImageView* iconImage_; IBOutlet NSTextField* extensionInstalledMsg_; - IBOutlet NSTextField* pageActionInfoMsg_; // Only shown for page actions. + // Only shown for page actions and omnibox keywords. + IBOutlet NSTextField* extraInfoMsg_; IBOutlet NSTextField* extensionInstalledInfoMsg_; } @@ -102,7 +104,7 @@ typedef enum { - (int)calculateWindowHeight; - (void)setMessageFrames:(int)newWindowHeight; - (NSRect)getExtensionInstalledMsgFrame; -- (NSRect)getPageActionInfoMsgFrame; +- (NSRect)getExtraInfoMsgFrame; - (NSRect)getExtensionInstalledInfoMsgFrame; @end // ExtensionInstalledBubbleController(ExposedForTesting) diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.mm b/chrome/browser/cocoa/extension_installed_bubble_controller.mm index b1263fd..d45ba74 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller.mm +++ b/chrome/browser/cocoa/extension_installed_bubble_controller.mm @@ -90,7 +90,9 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { icon_.reset([gfx::SkBitmapToNSImage(icon) retain]); pageActionRemoved_ = NO; - if (extension->browser_action()) { + if (!extension->omnibox_keyword().empty()) { + type_ = extension_installed_bubble::kOmniboxKeyword; + } else if (extension->browser_action()) { type_ = extension_installed_bubble::kBrowserAction; } else if (extension->page_action() && !extension->page_action()->default_icon_path().empty()) { @@ -174,6 +176,12 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { NSPoint arrowPoint = NSZeroPoint; switch(type_) { + case extension_installed_bubble::kOmniboxKeyword: { + LocationBarViewMac* locationBarView = + [window->cocoa_controller() locationBarBridge]; + arrowPoint = locationBarView->GetPageInfoBubblePoint(); + break; + } case extension_installed_bubble::kBrowserAction: { BrowserActionsController* controller = [[window->cocoa_controller() toolbarController] @@ -235,7 +243,8 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + info_bubble::kBubbleArrowWidth / 2.0, 0); offsets = [[window contentView] convertSize:offsets toView:nil]; - origin.x -= NSWidth([window frame]) - offsets.width; + if ([infoBubbleView_ arrowLocation] == info_bubble::kTopRight) + origin.x -= NSWidth([window frame]) - offsets.width; origin.y -= NSHeight([window frame]); [window setFrameOrigin:origin]; @@ -248,7 +257,12 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { // function is exposed for unit testing. - (NSWindow*)initializeWindow { NSWindow* window = [self window]; // completes nib load - [infoBubbleView_ setArrowLocation:info_bubble::kTopRight]; + + if (type_ == extension_installed_bubble::kOmniboxKeyword) { + [infoBubbleView_ setArrowLocation:info_bubble::kTopLeft]; + } else { + [infoBubbleView_ setArrowLocation:info_bubble::kTopRight]; + } // Set appropriate icon, resizing if necessary. if ([icon_ size].width > extension_installed_bubble::kIconSize) { @@ -278,12 +292,26 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { // If type is page action, include a special message about page actions. if (type_ == extension_installed_bubble::kPageAction) { - [pageActionInfoMsg_ setHidden:NO]; - [[pageActionInfoMsg_ cell] + [extraInfoMsg_ setHidden:NO]; + [[extraInfoMsg_ cell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [GTMUILocalizerAndLayoutTweaker - sizeToFitFixedWidthTextField:pageActionInfoMsg_]; - newWindowHeight += [pageActionInfoMsg_ frame].size.height + + sizeToFitFixedWidthTextField:extraInfoMsg_]; + newWindowHeight += [extraInfoMsg_ frame].size.height + + extension_installed_bubble::kInnerVerticalMargin; + } + + // If type is omnibox keyword, include a special message about the keyword. + if (type_ == extension_installed_bubble::kOmniboxKeyword) { + [extraInfoMsg_ setStringValue:l10n_util::GetNSStringF( + IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO, + UTF8ToUTF16(extension_->omnibox_keyword()))]; + [extraInfoMsg_ setHidden:NO]; + [[extraInfoMsg_ cell] + setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; + [GTMUILocalizerAndLayoutTweaker + sizeToFitFixedWidthTextField:extraInfoMsg_]; + newWindowHeight += [extraInfoMsg_ frame].size.height + extension_installed_bubble::kInnerVerticalMargin; } @@ -307,14 +335,15 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { extensionMessageFrame1.size.height + extension_installed_bubble::kOuterVerticalMargin); [extensionInstalledMsg_ setFrame:extensionMessageFrame1]; - if (type_ == extension_installed_bubble::kPageAction) { - // The page action message is only shown when appropriate. - NSRect pageActionMessageFrame = [pageActionInfoMsg_ frame]; - pageActionMessageFrame.origin.y = extensionMessageFrame1.origin.y - ( - pageActionMessageFrame.size.height + + if (type_ == extension_installed_bubble::kPageAction || + type_ == extension_installed_bubble::kOmniboxKeyword) { + // The extra message is only shown when appropriate. + NSRect extraMessageFrame = [extraInfoMsg_ frame]; + extraMessageFrame.origin.y = extensionMessageFrame1.origin.y - ( + extraMessageFrame.size.height + extension_installed_bubble::kInnerVerticalMargin); - [pageActionInfoMsg_ setFrame:pageActionMessageFrame]; - extensionMessageFrame2.origin.y = pageActionMessageFrame.origin.y - ( + [extraInfoMsg_ setFrame:extraMessageFrame]; + extensionMessageFrame2.origin.y = extraMessageFrame.origin.y - ( extensionMessageFrame2.size.height + extension_installed_bubble::kInnerVerticalMargin); } else { @@ -330,8 +359,8 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { return [extensionInstalledMsg_ frame]; } -- (NSRect)getPageActionInfoMsgFrame { - return [pageActionInfoMsg_ frame]; +- (NSRect)getExtraInfoMsgFrame { + return [extraInfoMsg_ frame]; } - (NSRect)getExtensionInstalledInfoMsgFrame { diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller_unittest.mm b/chrome/browser/cocoa/extension_installed_bubble_controller_unittest.mm index ad68c85..9113960 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller_unittest.mm +++ b/chrome/browser/cocoa/extension_installed_bubble_controller_unittest.mm @@ -141,7 +141,7 @@ TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) { 2 * extension_installed_bubble::kInnerVerticalMargin + [controller getExtensionInstalledMsgFrame].size.height + [controller getExtensionInstalledInfoMsgFrame].size.height + - [controller getPageActionInfoMsgFrame].size.height; + [controller getExtraInfoMsgFrame].size.height; EXPECT_EQ(height, correctHeight); [controller setMessageFrames:height]; @@ -149,7 +149,7 @@ TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) { // Bottom message should be kOuterVerticalMargin pixels above window edge. EXPECT_EQ(msg3Frame.origin.y, extension_installed_bubble::kOuterVerticalMargin); - NSRect msg2Frame = [controller getPageActionInfoMsgFrame]; + NSRect msg2Frame = [controller getExtraInfoMsgFrame]; // Pageaction message should be kInnerVerticalMargin pixels above bottom msg. EXPECT_EQ(msg2Frame.origin.y, msg3Frame.origin.y + msg3Frame.size.height + diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h index 687cb1a..91993f6 100644 --- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h +++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h @@ -140,6 +140,7 @@ class LocationBarViewMac : public AutocompleteEditController, PageTransition::Type transition, const GURL& alternate_nav_url); virtual void OnChanged(); + virtual void OnSelectionBoundsChanged(); virtual void OnInputInProgress(bool in_progress); virtual void OnKillFocus(); virtual void OnSetFocus(); diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm index f469b80..9ff22ee 100644 --- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm +++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm @@ -325,6 +325,10 @@ void LocationBarViewMac::OnChanged() { } } +void LocationBarViewMac::OnSelectionBoundsChanged() { + NOTIMPLEMENTED(); +} + void LocationBarViewMac::OnInputInProgress(bool in_progress) { toolbar_model_->set_input_in_progress(in_progress); Update(NULL, false); diff --git a/chrome/browser/cocoa/page_info_bubble_controller.mm b/chrome/browser/cocoa/page_info_bubble_controller.mm index c2c2d36..c11b3e4 100644 --- a/chrome/browser/cocoa/page_info_bubble_controller.mm +++ b/chrome/browser/cocoa/page_info_bubble_controller.mm @@ -17,7 +17,9 @@ #import "chrome/browser/cocoa/info_bubble_view.h" #import "chrome/browser/cocoa/info_bubble_window.h" #import "chrome/browser/cocoa/location_bar/location_bar_view_mac.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/profile.h" +#include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "net/base/cert_status_flags.h" @@ -195,7 +197,8 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, } - (IBAction)showHelpPage:(id)sender { - GURL url = GURL(l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER)); + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kPageInfoHelpCenterURL)); Browser* browser = BrowserList::GetLastActive(); browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); } diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm index a323233..7dbc2fc 100644 --- a/chrome/browser/cocoa/preferences_window_controller.mm +++ b/chrome/browser/cocoa/preferences_window_controller.mm @@ -34,6 +34,7 @@ #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/net/url_fixer_upper.h" @@ -1497,11 +1498,11 @@ const int kDisabledIndex = 1; } - (IBAction)privacyLearnMore:(id)sender { + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kPrivacyLearnMoreURL)); // We open a new browser window so the Options dialog doesn't get lost // behind other windows. - browser::ShowOptionsURL( - profile_, - GURL(l10n_util::GetStringUTF16(IDS_LEARN_MORE_PRIVACY_URL))); + browser::ShowOptionsURL(profile_, url); } - (IBAction)backgroundModeLearnMore:(id)sender { diff --git a/chrome/browser/cocoa/previewable_contents_controller.h b/chrome/browser/cocoa/previewable_contents_controller.h index 9b9b775..c4cc84e 100644 --- a/chrome/browser/cocoa/previewable_contents_controller.h +++ b/chrome/browser/cocoa/previewable_contents_controller.h @@ -26,9 +26,6 @@ class TabContents; // Container view for the "active" contents. IBOutlet NSView* activeContainer_; - // The close preview button. - IBOutlet NSButton* closeButton_; - // The preview TabContents. Will be NULL if no preview is currently showing. TabContents* previewContents_; // weak } @@ -45,9 +42,6 @@ class TabContents; // Returns YES if the preview contents is currently showing. - (BOOL)isShowingPreview; -// Simply calls |-hidePreview|. Convenience method for use by the close button. -- (IBAction)closePreview:(id)sender; - @end #endif // CHROME_BROWSER_COCOA_PREVIEWABLE_CONTENTS_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/previewable_contents_controller.mm b/chrome/browser/cocoa/previewable_contents_controller.mm index fc738c4..8ce042d 100644 --- a/chrome/browser/cocoa/previewable_contents_controller.mm +++ b/chrome/browser/cocoa/previewable_contents_controller.mm @@ -8,12 +8,6 @@ #include "base/mac_util.h" #include "chrome/browser/tab_contents/tab_contents.h" -@interface PreviewableContentsController(PrivateMethods) -// Shows or hides the "close preview" button. Adds the button to the view -// hierarchy, if needed. -- (void)showCloseButton:(BOOL)show; -@end - @implementation PreviewableContentsController @synthesize activeContainer = activeContainer_; @@ -36,54 +30,23 @@ NSView* previewView = previewContents_->GetNativeView(); [previewView setFrame:[[self view] bounds]]; - // Hide the active container, add the preview contents, and show the tear - // image. + // Hide the active container and add the preview contents. [activeContainer_ setHidden:YES]; [[self view] addSubview:previewView]; - [self showCloseButton:YES]; } - (void)hidePreview { DCHECK(previewContents_); - // Remove the preview contents, hide the tear image, and reshow the active - // container. - [self showCloseButton:NO]; + // Remove the preview contents and reshow the active container. [previewContents_->GetNativeView() removeFromSuperview]; [activeContainer_ setHidden:NO]; previewContents_ = nil; } -- (IBAction)closePreview:(id)sender { - // Hiding right now leads to crashes. - // TODO(rohitrao): Actually hide the preview. -} - - (BOOL)isShowingPreview { return previewContents_ != nil; } @end - -@implementation PreviewableContentsController(PrivateMethods) - -- (void)showCloseButton:(BOOL)show { - if (!show) { - [closeButton_ removeFromSuperview]; - return; - } - - if ([closeButton_ superview]) - return; // Already in the view hierarchy. - - // Add the close button to the upper left corner. - NSView* view = [self view]; - NSRect frame = [closeButton_ frame]; - frame.origin.x = NSMinX([view bounds]); - frame.origin.y = NSMaxY([view bounds]) - NSHeight(frame); - [closeButton_ setFrame:frame]; - [view addSubview:closeButton_]; -} - -@end diff --git a/chrome/browser/cocoa/previewable_contents_controller_unittest.mm b/chrome/browser/cocoa/previewable_contents_controller_unittest.mm index c72f113..85e5c09 100644 --- a/chrome/browser/cocoa/previewable_contents_controller_unittest.mm +++ b/chrome/browser/cocoa/previewable_contents_controller_unittest.mm @@ -11,16 +11,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -@interface PreviewableContentsController (ExposedForTesting) -- (NSButton*)closeButton; -@end - -@implementation PreviewableContentsController (ExposedForTesting) -- (NSButton*)closeButton { - return closeButton_; -} -@end - namespace { class PreviewableContentsControllerTest : public CocoaTest { @@ -36,11 +26,6 @@ class PreviewableContentsControllerTest : public CocoaTest { TEST_VIEW(PreviewableContentsControllerTest, [controller_ view]) -// Adds the view to a window and displays it. -TEST_F(PreviewableContentsControllerTest, TestImagesLoadedProperly) { - EXPECT_TRUE([[[controller_ closeButton] image] isValid]); -} - // TODO(rohitrao): Test showing and hiding the preview. This may require // changing the interface to take in a TabContentsView* instead of a // TabContents*. diff --git a/chrome/browser/cocoa/reload_button.h b/chrome/browser/cocoa/reload_button.h index edb6e9c..6432943 100644 --- a/chrome/browser/cocoa/reload_button.h +++ b/chrome/browser/cocoa/reload_button.h @@ -27,6 +27,11 @@ // Returns YES if the mouse is currently inside the bounds. - (BOOL)isMouseInside; +// Update the tag, and the image and tooltip to match. If |anInt| +// matches the current tag, no action is taken. |anInt| must be +// either |IDC_STOP| or |IDC_RELOAD|. +- (void)updateTag:(NSInteger)anInt; + // Update the button to be a reload button or stop button depending on // |isLoading|. If |force|, always sets the indicated mode. If // |!force|, and the mouse is over the button, defer the transition diff --git a/chrome/browser/cocoa/reload_button.mm b/chrome/browser/cocoa/reload_button.mm index 9975db7..56cb3d7 100644 --- a/chrome/browser/cocoa/reload_button.mm +++ b/chrome/browser/cocoa/reload_button.mm @@ -60,21 +60,36 @@ NSTimeInterval kPendingReloadTimeout = 1.35; [self setIgnoresMultiClick:YES]; } +- (void)updateTag:(NSInteger)anInt { + if ([self tag] == anInt) + return; + + // Forcibly remove any stale tooltip which is being displayed. + [self removeAllToolTips]; + + [self setTag:anInt]; + if (anInt == IDC_RELOAD) { + [self setImage:nsimage_cache::ImageNamed(kReloadImageName)]; + [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_RELOAD)]; + } else if (anInt == IDC_STOP) { + [self setImage:nsimage_cache::ImageNamed(kStopImageName)]; + [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STOP)]; + } else { + NOTREACHED(); + } +} + - (void)setIsLoading:(BOOL)isLoading force:(BOOL)force { // Can always transition to stop mode. Only transition to reload // mode if forced or if the mouse isn't hovering. Otherwise, note // that reload mode is desired and disable the button. if (isLoading) { pendingReloadTimer_.reset(); - [self setImage:nsimage_cache::ImageNamed(kStopImageName)]; - [self setTag:IDC_STOP]; - [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STOP)]; + [self updateTag:IDC_STOP]; [self setEnabled:YES]; } else if (force || ![self isMouseInside]) { pendingReloadTimer_.reset(); - [self setImage:nsimage_cache::ImageNamed(kReloadImageName)]; - [self setTag:IDC_RELOAD]; - [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_RELOAD)]; + [self updateTag:IDC_RELOAD]; // This button's cell may not have received a mouseExited event, and // therefore it could still think that the mouse is inside the button. Make diff --git a/chrome/browser/cocoa/reload_button_unittest.mm b/chrome/browser/cocoa/reload_button_unittest.mm index 19fde82..617503f 100644 --- a/chrome/browser/cocoa/reload_button_unittest.mm +++ b/chrome/browser/cocoa/reload_button_unittest.mm @@ -10,7 +10,7 @@ #include "chrome/app/chrome_command_ids.h" #import "chrome/browser/cocoa/cocoa_test_helper.h" #import "chrome/browser/cocoa/test_event_utils.h" -#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" @@ -72,74 +72,95 @@ TEST_F(ReloadButtonTest, IgnoredMultiClick) { [button_ setTarget:nil]; } +TEST_F(ReloadButtonTest, UpdateTag) { + [button_ setTag:IDC_STOP]; + + [button_ updateTag:IDC_RELOAD]; + EXPECT_EQ(IDC_RELOAD, [button_ tag]); + NSImage* reloadImage = [button_ image]; + NSString* const reloadToolTip = [button_ toolTip]; + + [button_ updateTag:IDC_STOP]; + EXPECT_EQ(IDC_STOP, [button_ tag]); + NSImage* stopImage = [button_ image]; + NSString* const stopToolTip = [button_ toolTip]; + EXPECT_NSNE(reloadImage, stopImage); + EXPECT_NSNE(reloadToolTip, stopToolTip); + + [button_ updateTag:IDC_RELOAD]; + EXPECT_EQ(IDC_RELOAD, [button_ tag]); + EXPECT_NSEQ(reloadImage, [button_ image]); + EXPECT_NSEQ(reloadToolTip, [button_ toolTip]); +} + // Test that when forcing the mode, it takes effect immediately, // regardless of whether the mouse is hovering. TEST_F(ReloadButtonTest, SetIsLoadingForce) { EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); // Changes to stop immediately. [button_ setIsLoading:YES force:YES]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); // Changes to reload immediately. [button_ setIsLoading:NO force:YES]; - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); // Changes to stop immediately when the mouse is hovered, and // doesn't change when the mouse exits. [button_ mouseEntered:nil]; EXPECT_TRUE([button_ isMouseInside]); [button_ setIsLoading:YES force:YES]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); [button_ mouseExited:nil]; EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); // Changes to reload immediately when the mouse is hovered, and // doesn't change when the mouse exits. [button_ mouseEntered:nil]; EXPECT_TRUE([button_ isMouseInside]); [button_ setIsLoading:NO force:YES]; - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); [button_ mouseExited:nil]; EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); } // Test that without force, stop mode is set immediately, but reload // is affected by the hover status. TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) { EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); // Changes to stop immediately when the mouse is not hovering. [button_ setIsLoading:YES force:NO]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); // Changes to reload immediately when the mouse is not hovering. [button_ setIsLoading:NO force:NO]; - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); // Changes to stop immediately when the mouse is hovered, and // doesn't change when the mouse exits. [button_ mouseEntered:nil]; EXPECT_TRUE([button_ isMouseInside]); [button_ setIsLoading:YES force:NO]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); [button_ mouseExited:nil]; EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); // Does not change to reload immediately when the mouse is hovered, // changes when the mouse exits. [button_ mouseEntered:nil]; EXPECT_TRUE([button_ isMouseInside]); [button_ setIsLoading:NO force:NO]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); [button_ mouseExited:nil]; EXPECT_FALSE([button_ isMouseInside]); - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); } // Test that without force, stop mode is set immediately, and reload @@ -201,7 +222,7 @@ TEST_F(ReloadButtonTest, StopAfterReloadSet) { // Get to stop mode. [button_ setIsLoading:YES force:YES]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); EXPECT_TRUE([button_ isEnabled]); // Expect the action once. @@ -213,12 +234,12 @@ TEST_F(ReloadButtonTest, StopAfterReloadSet) { test_event_utils::MouseClickInView(button_, 1); [NSApp postEvent:click.second atStart:YES]; [button_ mouseDown:click.first]; - EXPECT_EQ([button_ tag], IDC_RELOAD); + EXPECT_EQ(IDC_RELOAD, [button_ tag]); EXPECT_TRUE([button_ isEnabled]); // Get back to stop mode. [button_ setIsLoading:YES force:YES]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); EXPECT_TRUE([button_ isEnabled]); // If hover prevented reload mode immediately taking effect, clicks should do @@ -226,11 +247,11 @@ TEST_F(ReloadButtonTest, StopAfterReloadSet) { [button_ mouseEntered:nil]; EXPECT_TRUE([button_ isMouseInside]); [button_ setIsLoading:NO force:NO]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); EXPECT_FALSE([button_ isEnabled]); [NSApp postEvent:click.second atStart:YES]; [button_ mouseDown:click.first]; - EXPECT_EQ([button_ tag], IDC_STOP); + EXPECT_EQ(IDC_STOP, [button_ tag]); [button_ setTarget:nil]; } diff --git a/chrome/browser/cocoa/shell_dialogs_mac.mm b/chrome/browser/cocoa/shell_dialogs_mac.mm index 46f5ea2..8dcaebe 100644 --- a/chrome/browser/cocoa/shell_dialogs_mac.mm +++ b/chrome/browser/cocoa/shell_dialogs_mac.mm @@ -19,6 +19,7 @@ #include "base/mac/scoped_cftyperef.h" #import "base/scoped_nsobject.h" #include "base/sys_string_conversions.h" +#include "base/thread_restrictions.h" #include "grit/generated_resources.h" static const int kFileTypePopupTag = 1234; @@ -166,6 +167,9 @@ void SelectFileDialogImpl::SelectFile( NSString* default_dir = nil; NSString* default_filename = nil; if (!default_path.empty()) { + // The file dialog is going to do a ton of stats anyway. Not much + // point in eliminating this one. + base::ThreadRestrictions::ScopedAllowIO allow_io; if (file_util::DirectoryExists(default_path)) { default_dir = base::SysUTF8ToNSString(default_path.value()); } else { @@ -210,6 +214,11 @@ void SelectFileDialogImpl::SelectFile( type_map_[dialog] = type; SheetContext* context = new SheetContext; + + // |context| should never be NULL, but we are seeing indications otherwise. + // |This CHECK is here to confirm if we are actually getting NULL + // ||context|s. http://crbug.com/58959 + CHECK(context); context->type = type; context->owning_window = owning_window; @@ -353,6 +362,11 @@ bool SelectFileDialogImpl::ShouldEnableFilename(NSSavePanel* dialog, - (void)endedPanel:(NSSavePanel*)panel withReturn:(int)returnCode context:(void *)context { + // |context| should never be NULL, but we are seeing indications otherwise. + // |This CHECK is here to confirm if we are actually getting NULL + // ||context|s. http://crbug.com/58959 + CHECK(context); + int index = 0; SelectFileDialogImpl::SheetContext* context_struct = (SelectFileDialogImpl::SheetContext*)context; diff --git a/chrome/browser/cocoa/sidebar_controller.h b/chrome/browser/cocoa/sidebar_controller.h index f3c4a30..00c272a 100644 --- a/chrome/browser/cocoa/sidebar_controller.h +++ b/chrome/browser/cocoa/sidebar_controller.h @@ -9,6 +9,7 @@ #import #include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/tab_contents_controller.h" @class NSSplitView; @class NSView; @@ -23,11 +24,11 @@ class TabContents; // A view hosting sidebar contents. scoped_nsobject splitView_; - // Currently displayed sidebar contents. - TabContents* sidebarContents_; // weak. + // Manages currently displayed sidebar contents. + scoped_nsobject contentsController_; } -- (id)init; +- (id)initWithDelegate:(id)delegate; // This controller's view. - (NSSplitView*)view; @@ -41,6 +42,10 @@ class TabContents; // the actual resize). - (void)updateSidebarForTabContents:(TabContents*)contents; +// Call when the sidebar view is properly sized and the render widget host view +// should be put into the view hierarchy. +- (void)ensureContentsVisible; + @end #endif // CHROME_BROWSER_COCOA_SIDEBAR_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/sidebar_controller.mm b/chrome/browser/cocoa/sidebar_controller.mm index b78570e..77ec323 100644 --- a/chrome/browser/cocoa/sidebar_controller.mm +++ b/chrome/browser/cocoa/sidebar_controller.mm @@ -36,14 +36,17 @@ const int kMinWebWidth = 50; @implementation SidebarController -- (id)init { +- (id)initWithDelegate:(id)delegate { if ((self = [super init])) { splitView_.reset([[NSSplitView alloc] initWithFrame:NSZeroRect]); [splitView_ setDividerStyle:NSSplitViewDividerStyleThin]; [splitView_ setVertical:YES]; [splitView_ setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; [splitView_ setDelegate:self]; - sidebarContents_ = NULL; + + contentsController_.reset( + [[TabContentsController alloc] initWithContents:NULL + delegate:delegate]); } return self; } @@ -73,11 +76,10 @@ const int kMinWebWidth = 50; if (activeSidebar) sidebarContents = activeSidebar->sidebar_contents(); } - if (sidebarContents_ == sidebarContents) - return; - TabContents* oldSidebarContents = sidebarContents_; - sidebarContents_ = sidebarContents; + TabContents* oldSidebarContents = [contentsController_ tabContents]; + if (oldSidebarContents == sidebarContents) + return; // Adjust sidebar view. [self showSidebarContents:sidebarContents]; @@ -87,16 +89,22 @@ const int kMinWebWidth = 50; oldSidebarContents, sidebarContents); } +- (void)ensureContentsVisible { + [contentsController_ ensureContentsVisible]; +} + - (void)showSidebarContents:(TabContents*)sidebarContents { + [contentsController_ ensureContentsSizeDoesNotChange]; + NSArray* subviews = [splitView_ subviews]; if (sidebarContents) { DCHECK_GE([subviews count], 1u); - // |sidebarView| is a TabContentsViewCocoa object, whose ViewID was + // Native view is a TabContentsViewCocoa object, whose ViewID was // set to VIEW_ID_TAB_CONTAINER initially, so change it to // VIEW_ID_SIDE_BAR_CONTAINER here. - NSView* sidebarView = sidebarContents->GetNativeView(); - view_id_util::SetID(sidebarView, VIEW_ID_SIDE_BAR_CONTAINER); + view_id_util::SetID( + sidebarContents->GetNativeView(), VIEW_ID_SIDE_BAR_CONTAINER); CGFloat sidebarWidth = 0; if ([subviews count] == 1) { @@ -108,12 +116,10 @@ const int kMinWebWidth = 50; sidebarWidth = NSWidth([splitView_ frame]) * kDefaultSidebarWidthRatio; } - [splitView_ addSubview:sidebarView]; + [splitView_ addSubview:[contentsController_ view]]; } else { DCHECK_EQ([subviews count], 2u); sidebarWidth = NSWidth([[subviews objectAtIndex:1] frame]); - [splitView_ replaceSubview:[subviews objectAtIndex:1] - with:sidebarView]; } // Make sure |sidebarWidth| isn't too large or too small. @@ -132,8 +138,11 @@ const int kMinWebWidth = 50; g_browser_process->local_state()->SetInteger( prefs::kExtensionSidebarWidth, sidebarWidth); [oldSidebarContentsView removeFromSuperview]; + [splitView_ adjustSubviews]; } } + + [contentsController_ changeTabContents:sidebarContents]; } - (void)resizeSidebarToNewWidth:(CGFloat)width { diff --git a/chrome/browser/cocoa/tab_contents_controller.h b/chrome/browser/cocoa/tab_contents_controller.h index cf5405a..46a1ca5 100644 --- a/chrome/browser/cocoa/tab_contents_controller.h +++ b/chrome/browser/cocoa/tab_contents_controller.h @@ -8,9 +8,23 @@ #include +#include "base/scoped_ptr.h" + class TabContents; +class TabContentsNotificationBridge; +@class TabContentsController; + +// The interface for the tab contents view controller's delegate. + +@protocol TabContentsControllerDelegate + +// Tells the delegate when the tab contents view's frame is about to change. +- (void)tabContentsViewFrameWillChange:(TabContentsController*)source + frameRect:(NSRect)frameRect; + +@end -// A class that controls the web contents of a tab. It manages displaying the +// A class that controls the TabContents view. It manages displaying the // native view for a given TabContents. // Note that just creating the class does not display the view. We defer // inserting it until the box is the correct size to avoid multiple resize @@ -20,11 +34,27 @@ class TabContents; @interface TabContentsController : NSViewController { @private TabContents* contents_; // weak + // Delegate to be notified about size changes. + id delegate_; // weak + scoped_ptr tabContentsBridge_; } @property(readonly, nonatomic) TabContents* tabContents; -// Create the contents of a tab represented by |contents|. -- (id)initWithContents:(TabContents*)contents; +- (id)initWithContents:(TabContents*)contents + delegate:(id)delegate; + +// Call when the tab contents is about to be replaced with the currently +// selected tab contents to do not trigger unnecessary content relayout. +- (void)ensureContentsSizeDoesNotChange; + +// Call when the tab view is properly sized and the render widget host view +// should be put into the view hierarchy. +- (void)ensureContentsVisible; + +// Call to change the underlying tab contents object. View is not changed, +// call |-ensureContentsVisible| to display the |newContents|'s render widget +// host view. +- (void)changeTabContents:(TabContents*)newContents; // Called when the tab contents is the currently selected tab and is about to be // removed from the view hierarchy. @@ -35,14 +65,6 @@ class TabContents; // enabled. - (void)willBecomeSelectedTab; -// Call when the tab contents is about to be replaced with the currently -// selected tab contents to do not trigger unnecessary content relayout. -- (void)ensureContentsSizeDoesNotChange; - -// Call when the tab view is properly sized and the render widget host view -// should be put into the view hierarchy. -- (void)ensureContentsVisible; - // Called when the tab contents is updated in some non-descript way (the // notification from the model isn't specific). |updatedContents| could reflect // an entirely new tab contents object. diff --git a/chrome/browser/cocoa/tab_contents_controller.mm b/chrome/browser/cocoa/tab_contents_controller.mm index 1ff7721..4a5cd43 100644 --- a/chrome/browser/cocoa/tab_contents_controller.mm +++ b/chrome/browser/cocoa/tab_contents_controller.mm @@ -8,15 +8,105 @@ #include "base/scoped_nsobject.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/notification_details.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" + + +@interface TabContentsController(Private) +// Forwards frame update to |delegate_| (ResizeNotificationView calls it). +- (void)tabContentsViewFrameWillChange:(NSRect)frameRect; +// Notification from TabContents (forwarded by TabContentsNotificationBridge). +- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost + newHost:(RenderViewHost*)newHost; +@end + + +// A supporting C++ bridge object to register for TabContents notifications. + +class TabContentsNotificationBridge : public NotificationObserver { + public: + explicit TabContentsNotificationBridge(TabContentsController* controller); + + // Overriden from NotificationObserver. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + // Register for |contents|'s notifications, remove all prior registrations. + void ChangeTabContents(TabContents* contents); + private: + NotificationRegistrar registrar_; + TabContentsController* controller_; // weak, owns us +}; + +TabContentsNotificationBridge::TabContentsNotificationBridge( + TabContentsController* controller) + : controller_(controller) { +} + +void TabContentsNotificationBridge::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::RENDER_VIEW_HOST_CHANGED) { + RenderViewHostSwitchedDetails* switched_details = + Details(details).ptr(); + [controller_ tabContentsRenderViewHostChanged:switched_details->old_host + newHost:switched_details->new_host]; + } else { + NOTREACHED(); + } +} + +void TabContentsNotificationBridge::ChangeTabContents(TabContents* contents) { + registrar_.RemoveAll(); + if (contents) { + registrar_.Add(this, + NotificationType::RENDER_VIEW_HOST_CHANGED, + Source(&contents->controller())); + } +} + + +// A custom view that notifies |controller| that view's frame is changing. + +@interface ResizeNotificationView : NSView { + TabContentsController* controller_; +} +- (id)initWithController:(TabContentsController*)controller; +@end + +@implementation ResizeNotificationView + +- (id)initWithController:(TabContentsController*)controller { + if ((self = [super initWithFrame:NSZeroRect])) { + controller_ = controller; + } + return self; +} + +- (void)setFrame:(NSRect)frameRect { + [controller_ tabContentsViewFrameWillChange:frameRect]; + [super setFrame:frameRect]; +} + +@end @implementation TabContentsController @synthesize tabContents = contents_; -- (id)initWithContents:(TabContents*)contents { +- (id)initWithContents:(TabContents*)contents + delegate:(id)delegate { if ((self = [super initWithNibName:nil bundle:nil])) { contents_ = contents; + delegate_ = delegate; + tabContentsBridge_.reset(new TabContentsNotificationBridge(self)); + tabContentsBridge_->ChangeTabContents(contents); } return self; } @@ -28,47 +118,76 @@ } - (void)loadView { - scoped_nsobject view([[NSView alloc] initWithFrame:NSZeroRect]); + scoped_nsobject view( + [[ResizeNotificationView alloc] initWithController:self]); [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable]; [self setView:view]; } - (void)ensureContentsSizeDoesNotChange { - NSView* contentsContainer = [self view]; - NSArray* subviews = [contentsContainer subviews]; - if ([subviews count] > 0) - [contents_->GetNativeView() setAutoresizingMask:NSViewNotSizable]; + if (contents_) { + NSView* contentsContainer = [self view]; + NSArray* subviews = [contentsContainer subviews]; + if ([subviews count] > 0) + [contents_->GetNativeView() setAutoresizingMask:NSViewNotSizable]; + } } // Call when the tab view is properly sized and the render widget host view // should be put into the view hierarchy. - (void)ensureContentsVisible { + if (!contents_) + return; NSView* contentsContainer = [self view]; NSArray* subviews = [contentsContainer subviews]; NSView* contentsNativeView = contents_->GetNativeView(); - [contentsNativeView setFrame:[contentsContainer frame]]; + + NSRect contentsNativeViewFrame = [contentsContainer frame]; + contentsNativeViewFrame.origin = NSZeroPoint; + + [delegate_ tabContentsViewFrameWillChange:self + frameRect:contentsNativeViewFrame]; + + // Native view is resized to the actual size before it becomes visible + // to avoid flickering. + [contentsNativeView setFrame:contentsNativeViewFrame]; if ([subviews count] == 0) { [contentsContainer addSubview:contentsNativeView]; } else if ([subviews objectAtIndex:0] != contentsNativeView) { [contentsContainer replaceSubview:[subviews objectAtIndex:0] with:contentsNativeView]; } + // Restore autoresizing properties possibly stripped by + // ensureContentsSizeDoesNotChange call. [contentsNativeView setAutoresizingMask:NSViewWidthSizable| NSViewHeightSizable]; } -// Returns YES if the tab represented by this controller is the front-most. -- (BOOL)isCurrentTab { - // We're the current tab if we're in the view hierarchy, otherwise some other - // tab is. - return [[self view] superview] ? YES : NO; +- (void)changeTabContents:(TabContents*)newContents { + contents_ = newContents; + tabContentsBridge_->ChangeTabContents(contents_); +} + +- (void)tabContentsViewFrameWillChange:(NSRect)frameRect { + [delegate_ tabContentsViewFrameWillChange:self frameRect:frameRect]; +} + +- (void)tabContentsRenderViewHostChanged:(RenderViewHost*)oldHost + newHost:(RenderViewHost*)newHost { + if (oldHost && newHost && oldHost->view() && newHost->view()) { + newHost->view()->set_reserved_contents_rect( + oldHost->view()->reserved_contents_rect()); + } else { + [delegate_ tabContentsViewFrameWillChange:self + frameRect:[[self view] frame]]; + } } - (void)willBecomeUnselectedTab { // The RWHV is ripped out of the view hierarchy on tab switches, so it never // formally resigns first responder status. Handle this by explicitly sending // a Blur() message to the renderer, but only if the RWHV currently has focus. - RenderViewHost* rvh = contents_->render_view_host(); + RenderViewHost* rvh = [self tabContents]->render_view_host(); if (rvh && rvh->view() && rvh->view()->HasFocus()) rvh->Blur(); } @@ -83,9 +202,10 @@ // Calling setContentView: here removes any first responder status // the view may have, so avoid changing the view hierarchy unless // the view is different. - if (contents_ != updatedContents) { - contents_ = updatedContents; - [self ensureContentsVisible]; + if ([self tabContents] != updatedContents) { + [self changeTabContents:updatedContents]; + if ([self tabContents]) + [self ensureContentsVisible]; } } diff --git a/chrome/browser/cocoa/tab_strip_controller.h b/chrome/browser/cocoa/tab_strip_controller.h index 85de319..b063d9a 100644 --- a/chrome/browser/cocoa/tab_strip_controller.h +++ b/chrome/browser/cocoa/tab_strip_controller.h @@ -10,6 +10,7 @@ #include "base/scoped_nsobject.h" #include "base/scoped_ptr.h" +#import "chrome/browser/cocoa/tab_contents_controller.h" #import "chrome/browser/cocoa/tab_controller_target.h" #import "chrome/browser/cocoa/url_drop_target.h" #import "third_party/GTM/AppKit/GTMWindowSheetController.h" @@ -26,12 +27,10 @@ class TabStripModel; class TabContents; class ToolbarModel; -// The interface for the tab strip controller's delegate. Currently, the -// delegate is the BWC and is responsible for subviews layout and forwarding -// these events to InfoBarContainerController. -// Delegating TabStripModelObserverBridge's events (in lieu of subscrining -// BWC and InfoBarContainerController to TabStripModelObserverBridge events) -// is necessary to guarantee a proper order of subviews layout updates, +// The interface for the tab strip controller's delegate. +// Delegating TabStripModelObserverBridge's events (in lieu of directly +// subscribing to TabStripModelObserverBridge events, as TabStripController +// does) is necessary to guarantee a proper order of subviews layout updates, // otherwise it might trigger unnesessary content relayout, UI flickering etc. @protocol TabStripControllerDelegate @@ -59,7 +58,8 @@ class ToolbarModel; @interface TabStripController : NSObject { + GTMWindowSheetControllerDelegate, + TabContentsControllerDelegate> { @protected // YES if tabs are to be laid out vertically instead of horizontally. BOOL verticalLayout_; diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm index 8d06213..3ccdf3f 100644 --- a/chrome/browser/cocoa/tab_strip_controller.mm +++ b/chrome/browser/cocoa/tab_strip_controller.mm @@ -16,7 +16,6 @@ #include "base/sys_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/find_bar.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/metrics/user_metrics.h" @@ -39,6 +38,7 @@ #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/browser/ui/browser_navigator.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -469,7 +469,7 @@ private: // New content is in place, delegate should adjust itself accordingly. [delegate_ onSelectTabWithContents:[controller tabContents]]; - // It also resores content autoresizing properties. + // It also restores content autoresizing properties. [controller ensureContentsVisible]; // Make sure the new tabs's sheets are visible (necessary when a background @@ -973,7 +973,7 @@ private: // Make a new tab. Load the contents of this tab from the nib and associate // the new controller with |contents| so it can be looked up later. scoped_nsobject contentsController( - [[TabContentsController alloc] initWithContents:contents]); + [[TabContentsController alloc] initWithContents:contents delegate:self]); [tabContentsArray_ insertObject:contentsController atIndex:index]; // Make a new tab and add it to the strip. Keep track of its controller. @@ -1080,7 +1080,8 @@ private: // into the array, replacing |oldContents|. A TabSelectedAt notification will // follow, at which point we will install the new view. scoped_nsobject newController( - [[TabContentsController alloc] initWithContents:newContents]); + [[TabContentsController alloc] initWithContents:newContents + delegate:self]); // Bye bye, |oldController|. [tabContentsArray_ replaceObjectAtIndex:index withObject:newController]; @@ -1787,6 +1788,14 @@ private: sheetController_.reset(); } +// TabContentsControllerDelegate protocol. +- (void)tabContentsViewFrameWillChange:(TabContentsController*)source + frameRect:(NSRect)frameRect { + id controller = + [[switchView_ window] windowController]; + [controller tabContentsViewFrameWillChange:source frameRect:frameRect]; +} + - (TabContentsController*)activeTabContentsController { int modelIndex = tabStripModel_->selected_index(); if (modelIndex < 0) diff --git a/chrome/browser/content_setting_bubble_model.cc b/chrome/browser/content_setting_bubble_model.cc index 2cc5d91..f7e89d4 100644 --- a/chrome/browser/content_setting_bubble_model.cc +++ b/chrome/browser/content_setting_bubble_model.cc @@ -297,16 +297,11 @@ class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup { private: void SetLoadPluginsLinkTitle() { - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableClickToPlay)) { - set_load_plugins_link_title( - l10n_util::GetStringUTF8(IDS_BLOCKED_PLUGINS_LOAD_ALL)); - } + set_load_plugins_link_title( + l10n_util::GetStringUTF8(IDS_BLOCKED_PLUGINS_LOAD_ALL)); } virtual void OnLoadPluginsLinkClicked() { - DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableClickToPlay)); UserMetrics::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble")); if (tab_contents()) { tab_contents()->render_view_host()->LoadBlockedPlugins(); diff --git a/chrome/browser/content_setting_bubble_model_unittest.cc b/chrome/browser/content_setting_bubble_model_unittest.cc index ac956b2..d9590e0 100644 --- a/chrome/browser/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/content_setting_bubble_model_unittest.cc @@ -109,6 +109,7 @@ TEST_F(ContentSettingBubbleModelTest, MultiplePlugins) { CommandLine* cmd = CommandLine::ForCurrentProcess(); AutoReset auto_reset(cmd, *cmd); cmd->AppendSwitch(switches::kEnableResourceContentSettings); + cmd->AppendSwitch(switches::kEnableClickToPlay); HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); std::string fooPlugin = "foo"; diff --git a/chrome/browser/content_setting_combo_model.cc b/chrome/browser/content_setting_combo_model.cc index ec39a13..3606587 100644 --- a/chrome/browser/content_setting_combo_model.cc +++ b/chrome/browser/content_setting_combo_model.cc @@ -36,7 +36,8 @@ ContentSettingComboModel::~ContentSettingComboModel() { } int ContentSettingComboModel::GetItemCount() { - if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) + if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS && + CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableClickToPlay)) return arraysize(kAskSettings); if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) return arraysize(kSessionSettings); @@ -60,7 +61,8 @@ string16 ContentSettingComboModel::GetItemAt(int index) { } ContentSetting ContentSettingComboModel::SettingForIndex(int index) { - if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) + if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS && + CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableClickToPlay)) return kAskSettings[index]; if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) return kSessionSettings[index]; diff --git a/chrome/browser/crash_handler_host_linux.cc b/chrome/browser/crash_handler_host_linux.cc index 4e71017..a941cdd 100644 --- a/chrome/browser/crash_handler_host_linux.cc +++ b/chrome/browser/crash_handler_host_linux.cc @@ -35,7 +35,10 @@ using google_breakpad::ExceptionHandler; namespace { // Handles the crash dump and frees the allocated BreakpadInfo struct. -void CrashDumpTask(BreakpadInfo* info) { +void CrashDumpTask(CrashHandlerHostLinux* handler, BreakpadInfo* info) { + if (handler->IsShuttingDown()) + return; + HandleCrashDump(*info); delete[] info->filename; delete[] info->process_type; @@ -52,7 +55,8 @@ void CrashDumpTask(BreakpadInfo* info) { // the lifetime of the IO message loop. DISABLE_RUNNABLE_METHOD_REFCOUNT(CrashHandlerHostLinux); -CrashHandlerHostLinux::CrashHandlerHostLinux() { +CrashHandlerHostLinux::CrashHandlerHostLinux() + : shutting_down_(false) { int fds[2]; // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from // sending datagrams to other sockets on the system. The sandbox may prevent @@ -77,9 +81,6 @@ CrashHandlerHostLinux::CrashHandlerHostLinux() { CrashHandlerHostLinux::~CrashHandlerHostLinux() { HANDLE_EINTR(close(process_socket_)); HANDLE_EINTR(close(browser_socket_)); - - // If we are quitting and there are crash dumps in the queue, discard them. - uploader_thread_->message_loop()->QuitNow(); } void CrashHandlerHostLinux::Init() { @@ -255,8 +256,8 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { // /proc/[pid]/syscall is formatted as follows: // syscall_number arg1 ... arg6 sp pc // but we just check syscall_number through arg3. - StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", - SYS_read, tid_fd, tid_buf_addr); + base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", + SYS_read, tid_fd, tid_buf_addr); pid_t crashing_tid = base::FindThreadIDWithSyscall(crashing_pid, expected_syscall_data); if (crashing_tid == -1) { @@ -330,11 +331,20 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { uploader_thread_->message_loop()->PostTask( FROM_HERE, - NewRunnableFunction(&CrashDumpTask, info)); + NewRunnableFunction(&CrashDumpTask, this, info)); } void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() { file_descriptor_watcher_.StopWatchingFileDescriptor(); + + // If we are quitting and there are crash dumps in the queue, turn them into + // no-ops. + shutting_down_ = true; + uploader_thread_->Stop(); +} + +bool CrashHandlerHostLinux::IsShuttingDown() const { + return shutting_down_; } PluginCrashHandlerHostLinux::PluginCrashHandlerHostLinux() { diff --git a/chrome/browser/crash_handler_host_linux.h b/chrome/browser/crash_handler_host_linux.h index 0e7bf6e..bc2214b 100644 --- a/chrome/browser/crash_handler_host_linux.h +++ b/chrome/browser/crash_handler_host_linux.h @@ -42,6 +42,11 @@ class CrashHandlerHostLinux : public MessageLoopForIO::Watcher, // MessageLoop::DestructionObserver impl: virtual void WillDestroyCurrentMessageLoop(); +#if defined(USE_LINUX_BREAKPAD) + // Whether we are shutting down or not. + bool IsShuttingDown() const; +#endif + protected: CrashHandlerHostLinux(); virtual ~CrashHandlerHostLinux(); @@ -67,6 +72,7 @@ class CrashHandlerHostLinux : public MessageLoopForIO::Watcher, #if defined(USE_LINUX_BREAKPAD) MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_; scoped_ptr uploader_thread_; + bool shutting_down_; #endif DISALLOW_COPY_AND_ASSIGN(CrashHandlerHostLinux); diff --git a/chrome/browser/crash_recovery_browsertest.cc b/chrome/browser/crash_recovery_browsertest.cc index 71d6a5d..feaf61d 100644 --- a/chrome/browser/crash_recovery_browsertest.cc +++ b/chrome/browser/crash_recovery_browsertest.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "base/file_path.h" -#include "chrome/browser/browser.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_type.h" #include "chrome/common/page_transition_types.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/custom_home_pages_table_model.cc b/chrome/browser/custom_home_pages_table_model.cc index 59b9ca4..53fd565 100644 --- a/chrome/browser/custom_home_pages_table_model.cc +++ b/chrome/browser/custom_home_pages_table_model.cc @@ -9,11 +9,11 @@ #include "app/table_model_observer.h" #include "base/i18n/rtl.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "gfx/codec/png_codec.h" diff --git a/chrome/browser/debugger/devtools_http_protocol_handler.cc b/chrome/browser/debugger/devtools_http_protocol_handler.cc index 307aa84..24be8b6 100644 --- a/chrome/browser/debugger/devtools_http_protocol_handler.cc +++ b/chrome/browser/debugger/devtools_http_protocol_handler.cc @@ -10,7 +10,6 @@ #include "base/string_number_conversions.h" #include "base/thread.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/debugger/devtools_client_host.h" @@ -18,6 +17,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/devtools_messages.h" #include "chrome/common/net/url_request_context_getter.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/debugger/devtools_netlog_observer.cc b/chrome/browser/debugger/devtools_netlog_observer.cc index 83a7fbb..c92c0e1 100644 --- a/chrome/browser/debugger/devtools_netlog_observer.cc +++ b/chrome/browser/debugger/devtools_netlog_observer.cc @@ -54,7 +54,13 @@ void DevToolsNetLogObserver::OnAddEntry(net::NetLog::EventType type, request_to_info_.clear(); } scoped_refptr new_record(new ResourceInfo()); - request_to_info_.insert(std::make_pair(source.id, new_record)); + // We may encounter multiple PHASE_BEGIN for same resource in case of + // redirect -- if so, replace the old record to avoid keeping headers + // from different requests. + std::pair inserted = + request_to_info_.insert(std::make_pair(source.id, new_record)); + if (!inserted.second) + inserted.first->second = new_record; return; } if (type == net::NetLog::TYPE_REQUEST_ALIVE && diff --git a/chrome/browser/debugger/devtools_sanity_unittest.cc b/chrome/browser/debugger/devtools_sanity_unittest.cc index a246b3c..815e433 100644 --- a/chrome/browser/debugger/devtools_sanity_unittest.cc +++ b/chrome/browser/debugger/devtools_sanity_unittest.cc @@ -6,7 +6,6 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/debugger/devtools_client_host.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/debugger/devtools_window.h" @@ -15,6 +14,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_registrar.h" diff --git a/chrome/browser/debugger/devtools_window.cc b/chrome/browser/debugger/devtools_window.cc index b4a3181..5b2d265 100644 --- a/chrome/browser/debugger/devtools_window.cc +++ b/chrome/browser/debugger/devtools_window.cc @@ -7,7 +7,6 @@ #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" @@ -25,6 +24,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/debugger/inspectable_tab_proxy.cc b/chrome/browser/debugger/inspectable_tab_proxy.cc index ce8fd7f..eb9e4bc 100644 --- a/chrome/browser/debugger/inspectable_tab_proxy.cc +++ b/chrome/browser/debugger/inspectable_tab_proxy.cc @@ -6,13 +6,13 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/debugger/debugger_remote_service.h" #include "chrome/browser/debugger/devtools_client_host.h" #include "chrome/browser/sessions/session_id.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/devtools_messages.h" DevToolsClientHostImpl::DevToolsClientHostImpl( diff --git a/chrome/browser/defaults.cc b/chrome/browser/defaults.cc index 48ad842..4bb5288 100644 --- a/chrome/browser/defaults.cc +++ b/chrome/browser/defaults.cc @@ -31,6 +31,7 @@ const bool kSizeTabButtonToTopOfTabStrip = true; const bool kBootstrapSyncAuthentication = true; const bool kShowOtherBrowsersInAboutMemory = false; const bool kAlwaysOpenIncognitoWindow = true; +const bool kShowCancelButtonInTaskManager = true; #elif defined(TOOLKIT_USES_GTK) @@ -72,6 +73,7 @@ const bool kSizeTabButtonToTopOfTabStrip = false; const bool kBootstrapSyncAuthentication = false; const bool kShowOtherBrowsersInAboutMemory = true; const bool kAlwaysOpenIncognitoWindow = false; +const bool kShowCancelButtonInTaskManager = false; #endif #if defined(OS_MACOSX) @@ -82,4 +84,6 @@ const bool kBrowserAliveWithNoWindows = false; bool bookmarks_enabled = true; +bool skip_restore = false; + } // namespace browser_defaults diff --git a/chrome/browser/defaults.h b/chrome/browser/defaults.h index 6e64fe6..b20cc12 100644 --- a/chrome/browser/defaults.h +++ b/chrome/browser/defaults.h @@ -71,6 +71,9 @@ extern const bool kShowOtherBrowsersInAboutMemory; // Should always open incognito windows when started with --incognito switch? extern const bool kAlwaysOpenIncognitoWindow; +// Should the close button be shown in the Task Manager dialog? +extern const bool kShowCancelButtonInTaskManager; + //============================================================================= // Runtime "const" - set only once after parsing command line option and should // never be modified after that. @@ -78,6 +81,9 @@ extern const bool kAlwaysOpenIncognitoWindow; // Are bookmark enabled? True by default. extern bool bookmarks_enabled; +// Should we skip the user's preference for restore. False by default. +extern bool skip_restore; + } // namespace browser_defaults #endif // CHROME_BROWSER_DEFAULTS_H_ diff --git a/chrome/browser/device_orientation/device_orientation_browsertest.cc b/chrome/browser/device_orientation/device_orientation_browsertest.cc index 6fe92ea..2c99b85 100644 --- a/chrome/browser/device_orientation/device_orientation_browsertest.cc +++ b/chrome/browser/device_orientation/device_orientation_browsertest.cc @@ -5,10 +5,10 @@ #include "base/command_line.h" #include "base/file_path.h" #include "base/ref_counted.h" -#include "chrome/browser/browser.h" #include "chrome/browser/device_orientation/orientation.h" #include "chrome/browser/device_orientation/provider.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/dock_info_win.cc b/chrome/browser/dock_info_win.cc index 68b3c17..b6fd04f 100644 --- a/chrome/browser/dock_info_win.cc +++ b/chrome/browser/dock_info_win.cc @@ -5,9 +5,9 @@ #include "chrome/browser/dock_info.h" #include "base/basictypes.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/tab.h" diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc index 9bc27d2..77e3ee0 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.cc +++ b/chrome/browser/dom_ui/app_launcher_handler.cc @@ -5,19 +5,21 @@ #include "chrome/browser/dom_ui/app_launcher_handler.h" #include "app/animation.h" +#include "base/metrics/histogram.h" #include "base/string_number_conversions.h" +#include "base/string_split.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/app_launched_animation.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/default_apps.h" #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" @@ -32,6 +34,11 @@ namespace { +// The URL prefixes used by the NTP to signal when the web store or an app +// has launched. These are used for histogram purposes. +const char* kLaunchAppPingURL = "record-app-launch"; +const char* kLaunchWebStorePingURL = "record-webstore-launch"; + // This extracts an int from a ListValue at the given |index|. bool ExtractInt(const ListValue* list, size_t index, int* out_int) { std::string string_value; @@ -53,14 +60,67 @@ std::string GetIconURL(const Extension* extension, Extension::Icons icon, return default_val; } +// Extracts the promo parameter from the |path| generated by a ping on the NTP. +bool IsPromoActive(const std::string& path) { + std::vector params; + base::SplitString(path, '+', ¶ms); + + CHECK(params.size() == 2); + + return params.at(1) == "true"; +} + } // namespace AppLauncherHandler::AppLauncherHandler(ExtensionsService* extension_service) - : extensions_service_(extension_service) { + : extensions_service_(extension_service), + promo_active_(false) { } AppLauncherHandler::~AppLauncherHandler() {} +// static +void AppLauncherHandler::CreateAppInfo(const Extension* extension, + ExtensionPrefs* extension_prefs, + DictionaryValue* value) { + value->Clear(); + value->SetString("id", extension->id()); + value->SetString("name", extension->name()); + value->SetString("description", extension->description()); + value->SetString("launch_url", extension->GetFullLaunchURL().spec()); + value->SetString("options_url", extension->options_url().spec()); + value->SetString("icon_big", GetIconURL( + extension, Extension::EXTENSION_ICON_LARGE, + "chrome://theme/IDR_APP_DEFAULT_ICON")); + value->SetString("icon_small", GetIconURL( + extension, Extension::EXTENSION_ICON_BITTY, + std::string("chrome://favicon/") + extension->GetFullLaunchURL().spec())); + value->SetInteger("launch_container", extension->launch_container()); + value->SetInteger("launch_type", + extension_prefs->GetLaunchType(extension->id())); + + int app_launch_index = extension_prefs->GetAppLaunchIndex(extension->id()); + if (app_launch_index == -1) { + // Make sure every app has a launch index (some predate the launch index). + app_launch_index = extension_prefs->GetNextAppLaunchIndex(); + extension_prefs->SetAppLaunchIndex(extension->id(), app_launch_index); + } + value->SetInteger("app_launch_index", app_launch_index); +} + +// static +bool AppLauncherHandler::HandlePing(const std::string& path) { + if (path.find(kLaunchWebStorePingURL) != std::string::npos) { + RecordWebStoreLaunch(IsPromoActive(path)); + return true; + } else if (path.find(kLaunchAppPingURL) != std::string::npos) { + RecordAppLaunch(IsPromoActive(path)); + return true; + } + + return false; +} + DOMMessageHandler* AppLauncherHandler::Attach(DOMUI* dom_ui) { // TODO(arv): Add initialization code to the Apps store etc. return DOMMessageHandler::Attach(dom_ui); @@ -102,35 +162,6 @@ void AppLauncherHandler::Observe(NotificationType type, } } -// static -void AppLauncherHandler::CreateAppInfo(const Extension* extension, - ExtensionPrefs* extension_prefs, - DictionaryValue* value) { - value->Clear(); - value->SetString("id", extension->id()); - value->SetString("name", extension->name()); - value->SetString("description", extension->description()); - value->SetString("launch_url", extension->GetFullLaunchURL().spec()); - value->SetString("options_url", extension->options_url().spec()); - value->SetString("icon_big", GetIconURL( - extension, Extension::EXTENSION_ICON_LARGE, - "chrome://theme/IDR_APP_DEFAULT_ICON")); - value->SetString("icon_small", GetIconURL( - extension, Extension::EXTENSION_ICON_BITTY, - std::string("chrome://favicon/") + extension->GetFullLaunchURL().spec())); - value->SetInteger("launch_container", extension->launch_container()); - value->SetInteger("launch_type", - extension_prefs->GetLaunchType(extension->id())); - - int app_launch_index = extension_prefs->GetAppLaunchIndex(extension->id()); - if (app_launch_index == -1) { - // Make sure every app has a launch index (some predate the launch index). - app_launch_index = extension_prefs->GetNextAppLaunchIndex(); - extension_prefs->SetAppLaunchIndex(extension->id(), app_launch_index); - } - value->SetInteger("app_launch_index", app_launch_index); -} - void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { ListValue* list = new ListValue(); const ExtensionList* extensions = extensions_service_->extensions(); @@ -150,8 +181,10 @@ void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { if (default_apps->ShouldShowPromo(extensions_service_->GetAppIds())) { dictionary->SetBoolean("showPromo", true); default_apps->DidShowPromo(); + promo_active_ = true; } else { dictionary->SetBoolean("showPromo", false); + promo_active_ = false; } bool showLauncher = @@ -220,6 +253,9 @@ void AppLauncherHandler::HandleLaunchApp(const ListValue* args) { if (new_contents != old_contents && browser->tab_count() > 1) browser->CloseTabContents(old_contents); + + if (extension_id != extension_misc::kWebStoreAppId) + RecordAppLaunch(promo_active_); } void AppLauncherHandler::HandleSetLaunchType(const ListValue* args) { @@ -240,19 +276,6 @@ void AppLauncherHandler::HandleSetLaunchType(const ListValue* args) { static_cast(launch_type)); } -void AppLauncherHandler::AnimateAppIcon(const Extension* extension, - const gfx::Rect& rect) { - // We make this check for the case of minimized windows, unit tests, etc. - if (platform_util::IsVisible(dom_ui_->tab_contents()->GetNativeView()) && - Animation::ShouldRenderRichAnimation()) { -#if defined(OS_WIN) - AppLaunchedAnimation::Show(extension, rect); -#else - NOTIMPLEMENTED(); -#endif - } -} - void AppLauncherHandler::HandleUninstallApp(const ListValue* args) { std::string extension_id = WideToUTF8(ExtractStringValue(args)); const Extension* extension = extensions_service_->GetExtensionById( @@ -271,6 +294,9 @@ void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { // If the user has intentionally hidden the promotion, we'll uninstall all the // default apps (we know the user hasn't installed any apps on their own at // this point, or the promotion wouldn't have been shown). + UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, + extension_misc::PROMO_CLOSE, + extension_misc::PROMO_BUCKET_BOUNDARY); DefaultApps* default_apps = extensions_service_->default_apps(); const ExtensionIdSet* app_ids = default_apps->GetDefaultApps(); DCHECK(*app_ids == extensions_service_->GetAppIds()); @@ -284,10 +310,25 @@ void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { extensions_service_->default_apps()->SetPromoHidden(); } -ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() { - if (!install_ui_.get()) - install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile())); - return install_ui_.get(); +//static +void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) { + if (!promo_active) return; + + UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, + extension_misc::PROMO_LAUNCH_WEB_STORE, + extension_misc::PROMO_BUCKET_BOUNDARY); +} + +//static +void AppLauncherHandler::RecordAppLaunch(bool promo_active) { + // TODO(jstritar): record app launches that occur when the promo is not + // active using a different histogram. + + if (!promo_active) return; + + UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, + extension_misc::PROMO_LAUNCH_APP, + extension_misc::PROMO_BUCKET_BOUNDARY); } void AppLauncherHandler::InstallUIProceed() { @@ -308,3 +349,22 @@ void AppLauncherHandler::InstallUIProceed() { void AppLauncherHandler::InstallUIAbort() { extension_id_prompting_ = ""; } + +ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() { + if (!install_ui_.get()) + install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile())); + return install_ui_.get(); +} + +void AppLauncherHandler::AnimateAppIcon(const Extension* extension, + const gfx::Rect& rect) { + // We make this check for the case of minimized windows, unit tests, etc. + if (platform_util::IsVisible(dom_ui_->tab_contents()->GetNativeView()) && + Animation::ShouldRenderRichAnimation()) { +#if defined(OS_WIN) + AppLaunchedAnimation::Show(extension, rect); +#else + NOTIMPLEMENTED(); +#endif + } +} diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h index 5a3478e..1ebeaf7 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.h +++ b/chrome/browser/dom_ui/app_launcher_handler.h @@ -32,6 +32,14 @@ class AppLauncherHandler explicit AppLauncherHandler(ExtensionsService* extension_service); virtual ~AppLauncherHandler(); + // Populate a dictionary with the information from an extension. + static void CreateAppInfo(const Extension* extension, + ExtensionPrefs* extension_prefs, + DictionaryValue* value); + + // Callback for pings related to launching apps on the NTP. + static bool HandlePing(const std::string& path); + // DOMMessageHandler implementation. virtual DOMMessageHandler* Attach(DOMUI* dom_ui); virtual void RegisterMessages(); @@ -41,11 +49,6 @@ class AppLauncherHandler const NotificationSource& source, const NotificationDetails& details); - // Populate a dictionary with the information from an extension. - static void CreateAppInfo(const Extension* extension, - ExtensionPrefs* extension_prefs, - DictionaryValue* value); - // Populate the given dictionary with all installed app info. void FillAppDictionary(DictionaryValue* value); @@ -65,6 +68,14 @@ class AppLauncherHandler void HandleHideAppsPromo(const ListValue* args); private: + // Records a web store launch in the appropriate histograms. |promo_active| + // specifies if the web store promotion was active. + static void RecordWebStoreLaunch(bool promo_active); + + // Records an app launch in the appropriate histograms. |promo_active| + // specifies if the web store promotion was active. + static void RecordAppLaunch(bool promo_active); + // ExtensionInstallUI::Delegate implementation, used for receiving // notification about uninstall confirmation dialog selections. virtual void InstallUIProceed(); @@ -94,6 +105,9 @@ class AppLauncherHandler // The id of the extension we are prompting the user about. std::string extension_id_prompting_; + // Whether the promo is currently being shown. + bool promo_active_; + DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler); }; diff --git a/chrome/browser/dom_ui/bug_report_ui.cc b/chrome/browser/dom_ui/bug_report_ui.cc index bfe841c..8652619 100644 --- a/chrome/browser/dom_ui/bug_report_ui.cc +++ b/chrome/browser/dom_ui/bug_report_ui.cc @@ -19,13 +19,13 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "base/weak_ptr.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/bug_report_data.h" #include "chrome/browser/bug_report_util.h" #include "chrome/browser/dom_ui/dom_ui_screenshot_source.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/url_constants.h" @@ -148,7 +148,7 @@ void ShowHtmlBugReportView(views::Window* parent, Browser* browser) { "#" + base::IntToString(browser->selected_index()); RefreshLastScreenshot(parent); - browser->ShowSingletonTab(GURL(bug_report_url)); + browser->ShowSingletonTab(GURL(bug_report_url), false); } } // namespace browser diff --git a/chrome/browser/dom_ui/conflicts_ui.cc b/chrome/browser/dom_ui/conflicts_ui.cc index a93257a..45a6f18 100644 --- a/chrome/browser/dom_ui/conflicts_ui.cc +++ b/chrome/browser/dom_ui/conflicts_ui.cc @@ -207,7 +207,7 @@ ConflictsUI::ConflictsUI(TabContents* contents) : DOMUI(contents) { // static RefCountedMemory* ConflictsUI::GetFaviconResourceBytes() { return ResourceBundle::GetSharedInstance(). - LoadDataResourceBytes(IDR_CONFLICTS); + LoadDataResourceBytes(IDR_CONFLICT_MENU); } #endif diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc index fbdb42b..d27329e 100644 --- a/chrome/browser/dom_ui/dom_ui_factory.cc +++ b/chrome/browser/dom_ui/dom_ui_factory.cc @@ -234,6 +234,20 @@ bool DOMUIFactory::UseDOMUIForURL(Profile* profile, const GURL& url) { } // static +bool DOMUIFactory::IsURLAcceptableForDOMUI(Profile* profile, const GURL& url) { + return UseDOMUIForURL(profile, url) || + // javacsript: URLs are allowed to run in DOM UI pages + url.SchemeIs(chrome::kJavaScriptScheme) || + // It's possible to load about:blank in a DOM UI renderer. + // See http://crbug.com/42547 + url.spec() == chrome::kAboutBlankURL || + // about:crash, about:hang, and about:shorthang are allowed. + url.spec() == chrome::kAboutCrashURL || + url.spec() == chrome::kAboutHangURL || + url.spec() == chrome::kAboutShorthangURL; +} + +// static DOMUI* DOMUIFactory::CreateDOMUIForURL(TabContents* tab_contents, const GURL& url) { DOMUIFactoryFunction function = GetDOMUIFactoryFunction( diff --git a/chrome/browser/dom_ui/dom_ui_factory.h b/chrome/browser/dom_ui/dom_ui_factory.h index 3a7bfc6..1e1ed87 100644 --- a/chrome/browser/dom_ui/dom_ui_factory.h +++ b/chrome/browser/dom_ui/dom_ui_factory.h @@ -35,9 +35,14 @@ class DOMUIFactory { // to determine security policy. static bool HasDOMUIScheme(const GURL& url); - // Returns true if the given URL will use the DOM UI system. + // Returns true if the given URL must use the DOM UI system. static bool UseDOMUIForURL(Profile* profile, const GURL& url); + // Returns true if the given URL can be loaded by DOM UI system. This + // includes URLs that can be loaded by normal tabs as well, such as + // javascript: URLs or about:hang. + static bool IsURLAcceptableForDOMUI(Profile* profile, const GURL& url); + // Allocates a new DOMUI object for the given URL, and returns it. If the URL // is not a DOM UI URL, then it will return NULL. When non-NULL, ownership of // the returned pointer is passed to the caller. diff --git a/chrome/browser/dom_ui/filebrowse_ui.cc b/chrome/browser/dom_ui/filebrowse_ui.cc index 9ea95b3..52efa81 100644 --- a/chrome/browser/dom_ui/filebrowse_ui.cc +++ b/chrome/browser/dom_ui/filebrowse_ui.cc @@ -7,6 +7,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/callback.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/logging.h" #include "base/message_loop.h" @@ -20,11 +21,7 @@ #include "base/values.h" #include "base/weak_ptr.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/dom_ui/dom_ui_favicon_source.h" #include "chrome/browser/dom_ui/mediaplayer_ui.h" #include "chrome/browser/download/download_item.h" @@ -32,14 +29,17 @@ #include "chrome/browser/download/download_util.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/net/url_fetcher.h" -#include "chrome/common/pref_names.h" #include "chrome/common/time_format.h" #include "chrome/common/url_constants.h" #include "grit/browser_resources.h" @@ -640,16 +640,10 @@ void FilebrowseHandler::EnqueueMediaFile(const ListValue* args) { void FilebrowseHandler::HandleIsAdvancedEnabled(const ListValue* args) { #if defined(OS_CHROMEOS) - Browser* browser = BrowserList::GetLastActive(); - bool is_enabled = false; - bool mp_enabled = false; - if (browser) { - Profile* profile = browser->profile(); - PrefService* pref_service = profile->GetPrefs(); - is_enabled = pref_service->GetBoolean( - prefs::kLabsAdvancedFilesystemEnabled); - mp_enabled = pref_service->GetBoolean(prefs::kLabsMediaplayerEnabled); - } + bool is_enabled = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableAdvancedFileSystem); + bool mp_enabled = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableMediaPlayer); DictionaryValue info_value; info_value.SetBoolean("enabled", is_enabled); info_value.SetBoolean("mpEnabled", mp_enabled); @@ -1163,14 +1157,8 @@ Browser* FileBrowseUI::GetPopupForPath(const std::string& path, Profile* profile) { std::string current_path = path; if (current_path.empty()) { - Browser* browser = BrowserList::GetLastActive(); - if (browser == NULL) { - return NULL; - } - Profile* profile = browser->profile(); - PrefService* pref_service = profile->GetPrefs(); - bool is_enabled = pref_service->GetBoolean( - prefs::kLabsAdvancedFilesystemEnabled); + bool is_enabled = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableAdvancedFileSystem); if (!is_enabled) { FilePath default_download_path; if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, diff --git a/chrome/browser/dom_ui/foreign_session_handler.cc b/chrome/browser/dom_ui/foreign_session_handler.cc index d0ceabc..4583234 100644 --- a/chrome/browser/dom_ui/foreign_session_handler.cc +++ b/chrome/browser/dom_ui/foreign_session_handler.cc @@ -6,13 +6,13 @@ #include "base/scoped_vector.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/dom_ui/value_helper.h" #include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/sync/engine/syncapi.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/dom_ui/history2_ui.cc b/chrome/browser/dom_ui/history2_ui.cc index 383cae3..5b20af5 100644 --- a/chrome/browser/dom_ui/history2_ui.cc +++ b/chrome/browser/dom_ui/history2_ui.cc @@ -18,8 +18,6 @@ #include "base/time.h" #include "base/values.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/dom_ui/dom_ui_favicon_source.h" #include "chrome/browser/metrics/user_metrics.h" @@ -27,6 +25,8 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/notification_service.h" #include "chrome/common/time_format.h" diff --git a/chrome/browser/dom_ui/history_ui.cc b/chrome/browser/dom_ui/history_ui.cc index b636ad5..859a101 100644 --- a/chrome/browser/dom_ui/history_ui.cc +++ b/chrome/browser/dom_ui/history_ui.cc @@ -18,15 +18,15 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/dom_ui/dom_ui_favicon_source.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/notification_service.h" #include "chrome/common/time_format.h" diff --git a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc index cc8ae07..20da920 100644 --- a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc +++ b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate.cc @@ -4,11 +4,11 @@ #include "chrome/browser/dom_ui/html_dialog_tab_contents_delegate.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator.h" // Incognito profiles are not long-lived, so we always want to store a // non-incognito profile. diff --git a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc index d49bfdd..d8af35d 100644 --- a/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc +++ b/chrome/browser/dom_ui/html_dialog_tab_contents_delegate_unittest.cc @@ -8,10 +8,10 @@ #include "base/logging.h" #include "base/scoped_ptr.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/tab_contents/test_tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/url_constants.h" #include "chrome/test/browser_with_test_window_test.h" #include "chrome/test/test_browser_window.h" diff --git a/chrome/browser/dom_ui/mediaplayer_browsertest.cc b/chrome/browser/dom_ui/mediaplayer_browsertest.cc index 1dcbfae..896bf20 100644 --- a/chrome/browser/dom_ui/mediaplayer_browsertest.cc +++ b/chrome/browser/dom_ui/mediaplayer_browsertest.cc @@ -2,16 +2,16 @@ // 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/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/dom_ui/mediaplayer_ui.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/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" @@ -22,6 +22,10 @@ class MediaPlayerBrowserTest : public InProcessBrowserTest { public: MediaPlayerBrowserTest() {} + virtual void SetUpCommandLine(CommandLine* command_line) { + command_line->AppendSwitch(switches::kEnableMediaPlayer); + } + GURL GetMusicTestURL() { return GURL("http://localhost:1337/files/plugin/sample_mp3.mp3"); } @@ -66,9 +70,6 @@ IN_PROC_BROWSER_TEST_F(MediaPlayerBrowserTest, Popup) { ui_test_utils::NavigateToURL(browser(), GURL("chrome://downloads")); - PrefService* pref_service = browser()->profile()->GetPrefs(); - pref_service->SetBoolean(prefs::kLabsMediaplayerEnabled, true); - MediaPlayer* player = MediaPlayer::Get(); // Check that its not currently visible ASSERT_FALSE(IsPlayerVisible()); @@ -85,9 +86,6 @@ IN_PROC_BROWSER_TEST_F(MediaPlayerBrowserTest, PopupPlaylist) { GURL("chrome://downloads")); - PrefService* pref_service = browser()->profile()->GetPrefs(); - pref_service->SetBoolean(prefs::kLabsMediaplayerEnabled, true); - MediaPlayer* player = MediaPlayer::Get(); player->EnqueueMediaURL(GetMusicTestURL(), NULL); diff --git a/chrome/browser/dom_ui/mediaplayer_ui.cc b/chrome/browser/dom_ui/mediaplayer_ui.cc index ca9b78b..79d656f 100644 --- a/chrome/browser/dom_ui/mediaplayer_ui.cc +++ b/chrome/browser/dom_ui/mediaplayer_ui.cc @@ -5,6 +5,7 @@ #include "chrome/browser/dom_ui/mediaplayer_ui.h" #include "app/resource_bundle.h" +#include "base/command_line.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/path_service.h" @@ -16,23 +17,22 @@ #include "base/values.h" #include "base/weak_ptr.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/dom_ui/dom_ui_favicon_source.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_util.h" -#include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/history/history_types.h" -#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/net/url_fetcher.h" -#include "chrome/common/pref_names.h" #include "chrome/common/time_format.h" #include "chrome/common/url_constants.h" #include "grit/browser_resources.h" @@ -381,9 +381,8 @@ void MediaPlayer::ForcePlayMediaURL(const GURL& url, Browser* creator) { bool MediaPlayer::Enabled() { #if defined(OS_CHROMEOS) - Profile* profile = BrowserList::GetLastActive()->profile(); - PrefService* pref_service = profile->GetPrefs(); - return pref_service->GetBoolean(prefs::kLabsMediaplayerEnabled); + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableMediaPlayer); #else return true; #endif diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index a662102..e1e09b7 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -17,7 +17,6 @@ #include "base/string_number_conversions.h" #include "base/thread.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/dom_ui/app_launcher_handler.h" #include "chrome/browser/dom_ui/dom_ui_theme_source.h" @@ -38,6 +37,7 @@ #include "chrome/browser/sessions/tab_restore_service_observer.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" @@ -620,7 +620,9 @@ void NewTabUI::NewTabHTMLSource::StartDataRequest(const std::string& path, int request_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!path.empty() && path[0] != '#') { + if (AppLauncherHandler::HandlePing(path)) { + return; + } else if (!path.empty() && path[0] != '#') { // A path under new-tab was requested; it's likely a bad relative // URL from the new tab page, but in any case it's an error. NOTREACHED(); diff --git a/chrome/browser/dom_ui/new_tab_ui_uitest.cc b/chrome/browser/dom_ui/new_tab_ui_uitest.cc index 5be42f5..f50e179 100644 --- a/chrome/browser/dom_ui/new_tab_ui_uitest.cc +++ b/chrome/browser/dom_ui/new_tab_ui_uitest.cc @@ -11,6 +11,7 @@ #include "chrome/browser/sync/signin_manager.h" #include "chrome/common/json_pref_store.h" #include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/automation/window_proxy.h" @@ -83,6 +84,30 @@ TEST_F(NewTabUITest, NTPHasLoginName) { EXPECT_EQ(L"user@gmail.com", displayed_username); } +// Loads about:hang into two NTP tabs, ensuring we don't crash. +// See http://crbug.com/59859. +TEST_F(NewTabUITest, AboutHangInNTP) { + scoped_refptr window(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(window.get()); + + // Bring up a new tab page. + ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB)); + int load_time; + ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time)); + scoped_refptr tab = window->GetActiveTab(); + ASSERT_TRUE(tab.get()); + + // Navigate to about:hang to stall the process. + ASSERT_TRUE(tab->NavigateToURLAsync(GURL(chrome::kAboutHangURL))); + + // Visit about:hang again in another NTP. Don't bother waiting for the + // NTP to load, because it's hung. + ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB)); + scoped_refptr tab2 = window->GetActiveTab(); + ASSERT_TRUE(tab2.get()); + ASSERT_TRUE(tab2->NavigateToURLAsync(GURL(chrome::kAboutHangURL))); +} + // Fails about ~5% of the time on all platforms. http://crbug.com/45001 TEST_F(NewTabUITest, FLAKY_ChromeInternalLoadsNTP) { scoped_refptr window(automation()->GetBrowserWindow(0)); diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc index c2e7add..7d0a5d4 100644 --- a/chrome/browser/dom_ui/ntp_resource_cache.cc +++ b/chrome/browser/dom_ui/ntp_resource_cache.cc @@ -11,6 +11,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "app/theme_provider.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/ref_counted_memory.h" #include "base/string16.h" @@ -54,7 +55,15 @@ namespace { // The URL for the the Learn More page shown on incognito new tab. const char kLearnMoreIncognitoUrl[] = +#if defined(OS_CHROMEOS) + "http://www.google.com/support/chromeos/bin/answer.py?answer=95464"; +#else "http://www.google.com/support/chrome/bin/answer.py?answer=95464"; +#endif + +// The URL for the Learn More page shown on guest session new tab. +const char kLearnMoreGuestSessionUrl[] = + "http://www.google.com/support/chromeos/bin/answer.py?answer=1057090"; // The URL for bookmark sync service help. const char kSyncServiceHelpUrl[] = @@ -196,9 +205,20 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() { DictionaryValue localized_strings; localized_strings.SetString("title", l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE)); + int new_tab_message_ids = IDS_NEW_TAB_OTR_MESSAGE; + int new_tab_html_idr = IDR_INCOGNITO_TAB_HTML; + const char* new_tab_link = kLearnMoreIncognitoUrl; + // TODO(altimofeev): consider implementation without 'if def' usage. +#if defined(OS_CHROMEOS) + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) { + new_tab_message_ids = IDS_NEW_TAB_GUEST_SESSION_MESSAGE; + new_tab_html_idr = IDR_GUEST_SESSION_TAB_HTML; + new_tab_link = kLearnMoreGuestSessionUrl; + } +#endif localized_strings.SetString("content", - l10n_util::GetStringFUTF16(IDS_NEW_TAB_OTR_MESSAGE, - GetUrlWithLang(GURL(kLearnMoreIncognitoUrl)))); + l10n_util::GetStringFUTF16(new_tab_message_ids, + GetUrlWithLang(GURL(new_tab_link)))); localized_strings.SetString("extensionsmessage", l10n_util::GetStringFUTF16(IDS_NEW_TAB_OTR_EXTENSIONS_MESSAGE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), @@ -212,7 +232,7 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() { static const base::StringPiece incognito_tab_html( ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_INCOGNITO_TAB_HTML)); + new_tab_html_idr)); std::string full_html = jstemplate_builder::GetI18nTemplateHtml( incognito_tab_html, &localized_strings); @@ -271,8 +291,6 @@ void NTPResourceCache::CreateNewTabHTML() { l10n_util::GetStringUTF16(IDS_NEW_TAB_FIRST_RUN_NOTIFICATION)); localized_strings.SetString("closefirstrunnotification", l10n_util::GetStringUTF16(IDS_NEW_TAB_CLOSE_FIRST_RUN_NOTIFICATION)); - localized_strings.SetString("tips", - l10n_util::GetStringUTF16(IDS_NEW_TAB_TIPS)); localized_strings.SetString("close", l10n_util::GetStringUTF16(IDS_CLOSE)); localized_strings.SetString("history", l10n_util::GetStringUTF16(IDS_NEW_TAB_HISTORY)); diff --git a/chrome/browser/dom_ui/options/about_page_handler.cc b/chrome/browser/dom_ui/options/about_page_handler.cc index 8bb2353..cb24290 100644 --- a/chrome/browser/dom_ui/options/about_page_handler.cc +++ b/chrome/browser/dom_ui/options/about_page_handler.cc @@ -80,6 +80,7 @@ const LocalizeEntry localize_table[] = { { "release", IDS_ABOUT_PAGE_CHANNEL_RELEASE }, { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA }, { "development", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT }, + { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY }, { "user_agent", IDS_ABOUT_VERSION_USER_AGENT }, { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE }, { "aboutPage", IDS_ABOUT_PAGE_TITLE } diff --git a/chrome/browser/dom_ui/options/advanced_options_handler.cc b/chrome/browser/dom_ui/options/advanced_options_handler.cc index bb7bb88..4434551 100644 --- a/chrome/browser/dom_ui/options/advanced_options_handler.cc +++ b/chrome/browser/dom_ui/options/advanced_options_handler.cc @@ -14,6 +14,7 @@ #include "chrome/browser/dom_ui/options/options_managed_banner_handler.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/options_util.h" #include "chrome/browser/options_window.h" @@ -24,10 +25,11 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" -#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -57,7 +59,8 @@ void AdvancedOptionsHandler::GetLocalizedValues( DCHECK(localized_strings); localized_strings->SetString("privacyLearnMoreURL", - l10n_util::GetStringUTF16(IDS_LEARN_MORE_PRIVACY_URL)); + google_util::AppendGoogleLocaleParam( + GURL(chrome::kPrivacyLearnMoreURL)).spec()); localized_strings->SetString("downloadLocationGroupName", l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME)); localized_strings->SetString("downloadLocationBrowseButton", @@ -263,10 +266,10 @@ void AdvancedOptionsHandler::RegisterMessages() { dom_ui_->RegisterMessageCallback("showCloudPrintManagePage", NewCallback(this, &AdvancedOptionsHandler::ShowCloudPrintManagePage)); - dom_ui_->RegisterMessageCallback("showNetworkProxySettings", - NewCallback(this, - &AdvancedOptionsHandler::ShowNetworkProxySettings)); } + dom_ui_->RegisterMessageCallback("showNetworkProxySettings", + NewCallback(this, + &AdvancedOptionsHandler::ShowNetworkProxySettings)); #endif #if defined(OS_WIN) diff --git a/chrome/browser/dom_ui/options/content_settings_handler.cc b/chrome/browser/dom_ui/options/content_settings_handler.cc index bfb463d..662fc7d 100644 --- a/chrome/browser/dom_ui/options/content_settings_handler.cc +++ b/chrome/browser/dom_ui/options/content_settings_handler.cc @@ -356,6 +356,7 @@ void ContentSettingsHandler::Observe(NotificationType type, UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION); else if (pref_name == prefs::kGeolocationContentSettings) UpdateGeolocationExceptionsView(); + break; } case NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED: { diff --git a/chrome/browser/dom_ui/options/options_ui.cc b/chrome/browser/dom_ui/options/options_ui.cc index 0ee7188..44d3b5d 100644 --- a/chrome/browser/dom_ui/options/options_ui.cc +++ b/chrome/browser/dom_ui/options/options_ui.cc @@ -58,7 +58,6 @@ #include "chrome/browser/chromeos/dom_ui/core_chromeos_options_handler.h" #include "chrome/browser/chromeos/dom_ui/cros_personal_options_handler.h" #include "chrome/browser/chromeos/dom_ui/internet_options_handler.h" -#include "chrome/browser/chromeos/dom_ui/labs_handler.h" #include "chrome/browser/chromeos/dom_ui/language_chewing_options_handler.h" #include "chrome/browser/chromeos/dom_ui/language_customize_modifier_keys_handler.h" #include "chrome/browser/chromeos/dom_ui/language_hangul_options_handler.h" @@ -162,7 +161,6 @@ OptionsUI::OptionsUI(TabContents* contents) : DOMUI(contents) { AddOptionsPageUIHandler(localized_strings, new chromeos::AccountsOptionsHandler()); AddOptionsPageUIHandler(localized_strings, new InternetOptionsHandler()); - AddOptionsPageUIHandler(localized_strings, new LabsHandler()); AddOptionsPageUIHandler(localized_strings, new chromeos::LanguageChewingOptionsHandler()); AddOptionsPageUIHandler(localized_strings, @@ -240,6 +238,8 @@ RefCountedMemory* OptionsUI::GetFaviconResourceBytes() { } void OptionsUI::InitializeHandlers() { + DCHECK(!GetProfile()->IsOffTheRecord()); + std::vector::iterator iter; for (iter = handlers_.begin(); iter != handlers_.end(); ++iter) { (static_cast(*iter))->Initialize(); diff --git a/chrome/browser/dom_ui/options/personal_options_handler.cc b/chrome/browser/dom_ui/options/personal_options_handler.cc index 4c776b9..6b24e00 100644 --- a/chrome/browser/dom_ui/options/personal_options_handler.cc +++ b/chrome/browser/dom_ui/options/personal_options_handler.cc @@ -47,8 +47,6 @@ void PersonalOptionsHandler::GetLocalizedValues( DictionaryValue* localized_strings) { DCHECK(localized_strings); - localized_strings->SetString("sync_disabled_info", - l10n_util::GetStringUTF16(IDS_SYNC_IS_DISABLED_INFO)); localized_strings->SetString("sync_section", l10n_util::GetStringUTF16(IDS_SYNC_OPTIONS_GROUP_NAME)); localized_strings->SetString("sync_not_setup_info", @@ -89,6 +87,11 @@ void PersonalOptionsHandler::GetLocalizedValues( localized_strings->SetString("import_data", l10n_util::GetStringUTF16(IDS_OPTIONS_IMPORT_DATA_BUTTON)); + localized_strings->SetString("themes_gallery", + l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON)); + localized_strings->SetString("themes_gallery_url", + l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_URL)); + #if defined(TOOLKIT_GTK) localized_strings->SetString("appearance", l10n_util::GetStringUTF16(IDS_APPEARANCE_GROUP_NAME)); @@ -100,15 +103,11 @@ void PersonalOptionsHandler::GetLocalizedValues( l10n_util::GetStringUTF16(IDS_SHOW_WINDOW_DECORATIONS_RADIO)); localized_strings->SetString("hideWindow_decorations_radio", l10n_util::GetStringUTF16(IDS_HIDE_WINDOW_DECORATIONS_RADIO)); - localized_strings->SetString("themes_gallery", - l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON)); #else localized_strings->SetString("themes", l10n_util::GetStringUTF16(IDS_THEMES_GROUP_NAME)); localized_strings->SetString("themes_reset", l10n_util::GetStringUTF16(IDS_THEMES_RESET_BUTTON)); - localized_strings->SetString("themes_gallery", - l10n_util::GetStringUTF16(IDS_THEMES_GALLERY_BUTTON)); localized_strings->SetString("themes_default", l10n_util::GetStringUTF16(IDS_THEMES_DEFAULT_THEME_LABEL)); #endif @@ -120,15 +119,8 @@ void PersonalOptionsHandler::RegisterMessages() { "showSyncLoginDialog", NewCallback(this, &PersonalOptionsHandler::ShowSyncLoginDialog)); dom_ui_->RegisterMessageCallback( - "openPrivacyDashboardTabAndActivate", - NewCallback(this, - &PersonalOptionsHandler::OpenPrivacyDashboardTabAndActivate)); - dom_ui_->RegisterMessageCallback( "themesReset", NewCallback(this, &PersonalOptionsHandler::ThemesReset)); - dom_ui_->RegisterMessageCallback( - "themesGallery", - NewCallback(this, &PersonalOptionsHandler::ThemesGallery)); #if defined(TOOLKIT_GTK) dom_ui_->RegisterMessageCallback( "themesSetGTK", @@ -270,6 +262,8 @@ void PersonalOptionsHandler::Initialize() { if (sync_service) { sync_service->AddObserver(this); OnStateChanged(); + } else { + dom_ui_->CallJavascriptFunction(L"options.PersonalOptions.hideSyncSection"); } } @@ -279,21 +273,11 @@ void PersonalOptionsHandler::ShowSyncLoginDialog(const ListValue* args) { ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS); } -void PersonalOptionsHandler::OpenPrivacyDashboardTabAndActivate( - const ListValue* args) { - BrowserList::GetLastActive()->OpenPrivacyDashboardTabAndActivate(); -} - void PersonalOptionsHandler::ThemesReset(const ListValue* args) { UserMetricsRecordAction(UserMetricsAction("Options_ThemesReset")); dom_ui_->GetProfile()->ClearTheme(); } -void PersonalOptionsHandler::ThemesGallery(const ListValue* args) { - UserMetricsRecordAction(UserMetricsAction("Options_ThemesGallery")); - BrowserList::GetLastActive()->OpenThemeGalleryTabAndActivate(); -} - #if defined(TOOLKIT_GTK) void PersonalOptionsHandler::ThemesSetGTK(const ListValue* args) { UserMetricsRecordAction(UserMetricsAction("Options_GtkThemeSet")); diff --git a/chrome/browser/dom_ui/options/personal_options_handler.h b/chrome/browser/dom_ui/options/personal_options_handler.h index 6c6f080..8ee3649 100644 --- a/chrome/browser/dom_ui/options/personal_options_handler.h +++ b/chrome/browser/dom_ui/options/personal_options_handler.h @@ -36,9 +36,7 @@ class PersonalOptionsHandler : public OptionsPageUIHandler, private: void ObserveThemeChanged(); void ShowSyncLoginDialog(const ListValue* args); - void OpenPrivacyDashboardTabAndActivate(const ListValue* args); void ThemesReset(const ListValue* args); - void ThemesGallery(const ListValue* args); #if defined(TOOLKIT_GTK) void ThemesSetGTK(const ListValue* args); #endif diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc index 73fdbc0..1834332 100644 --- a/chrome/browser/dom_ui/plugins_ui.cc +++ b/chrome/browser/dom_ui/plugins_ui.cc @@ -15,14 +15,14 @@ #include "base/singleton.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/plugin_updater.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/dom_ui/shown_sections_handler.cc b/chrome/browser/dom_ui/shown_sections_handler.cc index 189c1c3..93a672f 100644 --- a/chrome/browser/dom_ui/shown_sections_handler.cc +++ b/chrome/browser/dom_ui/shown_sections_handler.cc @@ -14,7 +14,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_details.h" -#include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" @@ -55,9 +54,6 @@ ShownSectionsHandler::ShownSectionsHandler(PrefService* pref_service) } void ShownSectionsHandler::RegisterMessages() { - notification_registrar_.Add(this, NotificationType::EXTENSION_INSTALLED, - Source(dom_ui_->GetProfile())); - dom_ui_->RegisterMessageCallback("getShownSections", NewCallback(this, &ShownSectionsHandler::HandleGetShownSections)); dom_ui_->RegisterMessageCallback("setShownSections", @@ -73,21 +69,6 @@ void ShownSectionsHandler::Observe(NotificationType type, int sections = pref_service_->GetInteger(prefs::kNTPShownSections); FundamentalValue sections_value(sections); dom_ui_->CallJavascriptFunction(L"setShownSections", sections_value); - } else if (type == NotificationType::EXTENSION_INSTALLED) { - if (Details(details).ptr()->is_app()) { - int mode = pref_service_->GetInteger(prefs::kNTPShownSections); - - // De-minimize the apps section. - mode &= ~MINIMIZED_APPS; - - // Hide any open sections. - mode &= ~ALL_SECTIONS_MASK; - - // Show the apps section. - mode |= APPS; - - pref_service_->SetInteger(prefs::kNTPShownSections, mode); - } } else { NOTREACHED(); } @@ -137,3 +118,22 @@ void ShownSectionsHandler::MigrateUserPrefs(PrefService* pref_service, if (changed) pref_service->SetInteger(prefs::kNTPShownSections, shown_sections); } + +// static +void ShownSectionsHandler::OnExtensionInstalled(PrefService* prefs, + const Extension* extension) { + if (extension->is_app()) { + int mode = prefs->GetInteger(prefs::kNTPShownSections); + + // De-minimize the apps section. + mode &= ~MINIMIZED_APPS; + + // Hide any open sections. + mode &= ~ALL_SECTIONS_MASK; + + // Show the apps section. + mode |= APPS; + + prefs->SetInteger(prefs::kNTPShownSections, mode); + } +} diff --git a/chrome/browser/dom_ui/shown_sections_handler.h b/chrome/browser/dom_ui/shown_sections_handler.h index e82c3fb..ad227b4 100644 --- a/chrome/browser/dom_ui/shown_sections_handler.h +++ b/chrome/browser/dom_ui/shown_sections_handler.h @@ -8,10 +8,10 @@ #include "chrome/browser/dom_ui/dom_ui.h" #include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" #include "chrome/browser/prefs/pref_change_registrar.h" class DOMUI; +class Extension; class Value; class PrefService; @@ -63,10 +63,12 @@ class ShownSectionsHandler : public DOMMessageHandler, int old_pref_version, int new_pref_version); + static void OnExtensionInstalled(PrefService* prefs, + const Extension* extension); + private: PrefService* pref_service_; PrefChangeRegistrar pref_registrar_; - NotificationRegistrar notification_registrar_; DISALLOW_COPY_AND_ASSIGN(ShownSectionsHandler); }; diff --git a/chrome/browser/download/download_item.cc b/chrome/browser/download/download_item.cc index 7b4b134..3781877 100644 --- a/chrome/browser/download/download_item.cc +++ b/chrome/browser/download/download_item.cc @@ -11,6 +11,7 @@ #include "base/utf_string_conversions.h" #include "net/base/net_util.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/download/download_file_manager.h" #include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_prefs.h" @@ -324,6 +325,8 @@ bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const { } int64 DownloadItem::CurrentSpeed() const { + if (is_paused_) + return 0; base::TimeDelta diff = base::TimeTicks::Now() - start_tick_; int64 diff_ms = diff.InMilliseconds(); return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms; @@ -359,6 +362,34 @@ void DownloadItem::OnNameFinalized() { NotifyObserversDownloadFileCompleted(); } +void DownloadItem::OnSafeDownloadFinished(DownloadFileManager* file_manager) { + DCHECK_EQ(SAFE, safety_state()); + DCHECK(file_manager); + if (NeedsRename()) { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + NewRunnableMethod( + file_manager, &DownloadFileManager::OnFinalDownloadName, + id(), GetTargetFilePath(), false, download_manager_)); + return; + } + + download_manager_->DownloadFinished(this); +} + +void DownloadItem::OnDownloadRenamedToFinalName(const FilePath& full_path) { + bool needed_rename = NeedsRename(); + + Rename(full_path); + OnNameFinalized(); + + if (needed_rename && safety_state() == SAFE) { + // This was called from OnSafeDownloadFinished; continue to call + // DownloadFinished. + download_manager_->DownloadFinished(this); + } +} + bool DownloadItem::MatchesQuery(const string16& query) const { if (query.empty()) return true; diff --git a/chrome/browser/download/download_item.h b/chrome/browser/download/download_item.h index 4bc2b39..a9b736e 100644 --- a/chrome/browser/download/download_item.h +++ b/chrome/browser/download/download_item.h @@ -27,6 +27,7 @@ #include "base/timer.h" #include "googleurl/src/gurl.h" +class DownloadFileManager; class DownloadManager; struct DownloadCreateInfo; @@ -159,6 +160,14 @@ class DownloadItem { // Called when the name of the download is finalized. void OnNameFinalized(); + // Called when the download is finished for safe downloads. + // This may perform final rename if necessary and will eventually call + // DownloadManager::DownloadFinished(). + void OnSafeDownloadFinished(DownloadFileManager* file_manager); + + // Called when the file name for the download is renamed to its final name. + void OnDownloadRenamedToFinalName(const FilePath& full_path); + // Returns true if this item matches |query|. |query| must be lower-cased. bool MatchesQuery(const string16& query) const; diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 59476b4..a451d41 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -17,7 +17,6 @@ #include "base/task.h" #include "base/utf_string_conversions.h" #include "build/build_config.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" @@ -37,6 +36,7 @@ #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" @@ -531,16 +531,7 @@ void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) { return; } - if (download->NeedsRename()) { - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - NewRunnableMethod( - file_manager_, &DownloadFileManager::OnFinalDownloadName, - download->id(), download->GetTargetFilePath(), false, this)); - return; - } - - ContinueDownloadFinished(download); + download->OnSafeDownloadFinished(file_manager_); } void DownloadManager::DownloadRenamedToFinalName(int download_id, @@ -549,20 +540,10 @@ void DownloadManager::DownloadRenamedToFinalName(int download_id, DownloadItem* item = GetDownloadItem(download_id); if (!item) return; - - bool needed_rename = item->NeedsRename(); - item->Rename(full_path); - - item->OnNameFinalized(); - - if (needed_rename) { - // This was called from OnAllDataSaved; continue to call - // ContinueDownloadFinished. - ContinueDownloadFinished(item); - } + item->OnDownloadRenamedToFinalName(full_path); } -void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { +void DownloadManager::DownloadFinished(DownloadItem* download) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // If this was a dangerous download, it has now been approved and must be @@ -622,7 +603,7 @@ void DownloadManager::DangerousDownloadRenamed(int64 download_handle, } // Continue the download finished sequence. - ContinueDownloadFinished(download); + DownloadFinished(download); } void DownloadManager::DownloadCancelled(int32 download_id) { @@ -918,7 +899,7 @@ void DownloadManager::OnQueryDownloadEntriesComplete( // service, we associate the DownloadItem with the db handle, update our // 'downloads_' map and inform observers. void DownloadManager::OnCreateDownloadEntryComplete( - const DownloadCreateInfo& info, + DownloadCreateInfo info, int64 db_handle) { DownloadMap::iterator it = in_progress_.find(info.download_id); DCHECK(it != in_progress_.end()); diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h index 6608af2..a6cdd90 100644 --- a/chrome/browser/download/download_manager.h +++ b/chrome/browser/download/download_manager.h @@ -168,7 +168,7 @@ class DownloadManager void OnQueryDownloadEntriesComplete( std::vector* entries); void OnCreateDownloadEntryComplete( - const DownloadCreateInfo& info, int64 db_handle); + DownloadCreateInfo info, int64 db_handle); // Display a new download in the appropriate browser UI. void ShowDownloadInBrowser(const DownloadCreateInfo& info, @@ -204,6 +204,13 @@ class DownloadManager // Called when the user has validated the download of a dangerous file. void DangerousDownloadValidated(DownloadItem* download); + // Performs the last steps required when a download has been completed. + // It is necessary to break down the flow when a download is finished as + // dangerous downloads are downloaded to temporary files that need to be + // renamed on the file thread first. + // Invoked on the UI thread. + void DownloadFinished(DownloadItem* download); + private: // This class is used to let an incognito DownloadManager observe changes to // a normal DownloadManager, to propagate ModelChanged() calls from the parent @@ -253,13 +260,6 @@ class DownloadManager int render_process_id, int request_id); - // Performs the last steps required when a download has been completed. - // It is necessary to break down the flow when a download is finished as - // dangerous downloads are downloaded to temporary files that need to be - // renamed on the file thread first. - // Invoked on the UI thread. - void ContinueDownloadFinished(DownloadItem* download); - // Renames a finished dangerous download from its temporary file name to its // real file name. // Invoked on the file thread. @@ -353,7 +353,7 @@ class DownloadManager // destination, so that observers are appropriately notified of completion // after this determination is made. // The map is of download_id->remaining size (bytes), both of which are - // required when calling DownloadFinished. + // required when calling OnAllDataSaved. typedef std::map PendingFinishedMap; PendingFinishedMap pending_finished_downloads_; diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc index dc69d02..8d11e9a 100644 --- a/chrome/browser/download/download_shelf.cc +++ b/chrome/browser/download/download_shelf.cc @@ -6,13 +6,13 @@ #include "app/l10n_util.h" #include "base/file_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/dom_ui/downloads_ui.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/download/download_uitest.cc b/chrome/browser/download/download_uitest.cc index f5bae1f..e37bfb4 100644 --- a/chrome/browser/download/download_uitest.cc +++ b/chrome/browser/download/download_uitest.cc @@ -17,6 +17,7 @@ #include "base/string_util.h" #include "base/test/test_file_util.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/download/download_util.h" #include "chrome/browser/net/url_request_mock_http_job.h" #include "chrome/browser/net/url_request_slow_download_job.h" #include "chrome/common/chrome_constants.h" @@ -85,6 +86,12 @@ class DownloadTest : public UITest { CheckDownload(file, file); } + void CleanupDownloadFiles(const FilePath& prefix) { + FilePath path_prefix(download_prefix_); + path_prefix = path_prefix.Append(prefix); + download_util::EraseUniqueDownloadFiles(path_prefix); + } + virtual void SetUp() { UITest::SetUp(); download_prefix_ = GetDownloadDirectory(); @@ -94,6 +101,11 @@ class DownloadTest : public UITest { void RunSizeTest(const GURL& url, const std::wstring& expected_title_in_progress, const std::wstring& expected_title_finished) { + FilePath filename; + net::FileURLToFilePath(url, &filename); + filename = filename.BaseName(); + CleanupDownloadFiles(filename); + { EXPECT_EQ(1, GetTabCount()); @@ -115,9 +127,6 @@ class DownloadTest : public UITest { EXPECT_TRUE(WaitForDownloadShelfVisible(window.get())); } - FilePath filename; - net::FileURLToFilePath(url, &filename); - filename = filename.BaseName(); FilePath download_path = download_prefix_.Append(filename); EXPECT_TRUE(file_util::PathExists(download_path)); @@ -177,6 +186,7 @@ class DownloadTest : public UITest { // Additionally, there is Windows-specific flake, http://crbug.com/20809. TEST_F(DownloadTest, DISABLED_DownloadMimeType) { FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); EXPECT_EQ(1, GetTabCount()); @@ -199,9 +209,7 @@ TEST_F(DownloadTest, DISABLED_DownloadMimeType) { TEST_F(DownloadTest, FLAKY_NoDownload) { FilePath file(FILE_PATH_LITERAL("download-test2.html")); FilePath file_path = download_prefix_.Append(file); - - if (file_util::PathExists(file_path)) - ASSERT_TRUE(file_util::Delete(file_path, false)); + CleanupDownloadFiles(file); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); WaitUntilTabCount(1); @@ -227,6 +235,7 @@ TEST_F(DownloadTest, FLAKY_NoDownload) { TEST_F(DownloadTest, DISABLED_ContentDisposition) { FilePath file(FILE_PATH_LITERAL("download-test3.gif")); FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif")); + CleanupDownloadFiles(file); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); WaitUntilTabCount(1); @@ -249,6 +258,7 @@ TEST_F(DownloadTest, DISABLED_ContentDisposition) { TEST_F(DownloadTest, DISABLED_PerWindowShelf) { FilePath file(FILE_PATH_LITERAL("download-test3.gif")); FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif")); + CleanupDownloadFiles(download_file); NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file)); WaitUntilTabCount(1); @@ -339,6 +349,7 @@ TEST_F(DownloadTest, DISABLED_IncognitoDownload) { // Download something. FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); scoped_refptr tab(incognito->GetTab(0)); ASSERT_TRUE(tab.get()); ASSERT_TRUE(tab->NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file))); @@ -396,6 +407,7 @@ TEST_F(DownloadTest, FLAKY_CloseNewTab1) { ASSERT_TRUE(tab_proxy.get()); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsyncWithDisposition( URLRequestMockHTTPJob::GetMockUrl(file), NEW_BACKGROUND_TAB)); @@ -425,6 +437,7 @@ TEST_F(DownloadTest, FLAKY_DontCloseNewTab2) { FilePath(FILE_PATH_LITERAL("download_page1.html"))))); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsync(GURL("javascript:openNew()"))); ASSERT_TRUE(WaitForDownloadShelfVisible(browser)); @@ -454,6 +467,7 @@ TEST_F(DownloadTest, FLAKY_DontCloseNewTab3) { ASSERT_TRUE(tab_proxy->NavigateToURLAsync(GURL("javascript:openNew()"))); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsync( URLRequestMockHTTPJob::GetMockUrl(file))); @@ -482,6 +496,7 @@ TEST_F(DownloadTest, FLAKY_CloseNewTab2) { FilePath(FILE_PATH_LITERAL("download_page3.html"))))); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsync(GURL("javascript:openNew()"))); ASSERT_TRUE(WaitForDownloadShelfVisible(browser)); @@ -509,6 +524,7 @@ TEST_F(DownloadTest, FLAKY_CloseNewTab3) { FilePath(FILE_PATH_LITERAL("download_page4.html"))))); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsync( GURL("javascript:document.getElementById('form').submit()"))); @@ -533,6 +549,7 @@ TEST_F(DownloadTest, DISABLED_DontCloseNewWindow) { ASSERT_TRUE(tab_proxy.get()); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsyncWithDisposition( URLRequestMockHTTPJob::GetMockUrl(file), NEW_WINDOW)); @@ -558,6 +575,7 @@ TEST_F(DownloadTest, DISABLED_NewWindow) { ASSERT_TRUE(tab_proxy.get()); FilePath file(FILE_PATH_LITERAL("download-test1.lib")); + CleanupDownloadFiles(file); ASSERT_TRUE(tab_proxy->NavigateToURLAsyncWithDisposition( URLRequestMockHTTPJob::GetMockUrl(file), NEW_WINDOW)); diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index 1235285..c7a261f 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -26,7 +26,6 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "base/win/windows_version.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" @@ -42,6 +41,7 @@ #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_service.h" #include "chrome/common/time_format.h" @@ -86,6 +86,13 @@ namespace download_util { // so that the animation ends faded out. static const int kCompleteAnimationCycles = 5; +// The maximum number of 'uniquified' files we will try to create. +// This is used when the filename we're trying to download is already in use, +// so we create a new unique filename by appending " (nnn)" before the +// extension, where 1 <= nnn <= kMaxUniqueFiles. +// Also used by code that cleans up said files. +static const int kMaxUniqueFiles = 100; + // Download temporary file creation -------------------------------------------- class DefaultDownloadDirectory { @@ -223,52 +230,35 @@ void OpenChromeExtension(Profile* profile, DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(download_item.is_extension_install()); - // We don't support extensions in OTR mode. ExtensionsService* service = profile->GetExtensionsService(); - if (service) { - NotificationService* nservice = NotificationService::current(); - GURL nonconst_download_url = download_item.url(); - nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL, - Source(download_manager), - Details(&nonconst_download_url)); - - scoped_refptr installer( - new CrxInstaller(service->install_directory(), - service, - new ExtensionInstallUI(profile))); - installer->set_delete_source(true); - - if (UserScript::HasUserScriptFileExtension(download_item.url())) { - installer->InstallUserScript(download_item.full_path(), - download_item.url()); - } else { - bool is_gallery_download = service->IsDownloadFromGallery( - download_item.url(), download_item.referrer_url()); - installer->set_original_mime_type(download_item.original_mime_type()); - installer->set_apps_require_extension_mime_type(true); - installer->set_allow_privilege_increase(true); - installer->set_original_url(download_item.url()); - installer->set_is_gallery_install(is_gallery_download); - installer->InstallCrx(download_item.full_path()); - installer->set_allow_silent_install(is_gallery_download); - } - } else { - TabContents* contents = NULL; - // Get last active normal browser of profile. - Browser* last_active = - BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, true); - if (last_active) - contents = last_active->GetSelectedTabContents(); - if (contents) { - contents->AddInfoBar( - new SimpleAlertInfoBarDelegate(contents, - l10n_util::GetStringUTF16( - IDS_EXTENSION_INCOGNITO_INSTALL_INFOBAR_LABEL), - ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_PLUGIN_INSTALL), - true)); - } + CHECK(service); + NotificationService* nservice = NotificationService::current(); + GURL nonconst_download_url = download_item.url(); + nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL, + Source(download_manager), + Details(&nonconst_download_url)); + + scoped_refptr installer( + new CrxInstaller(service->install_directory(), + service, + new ExtensionInstallUI(profile))); + installer->set_delete_source(true); + + if (UserScript::HasUserScriptFileExtension(download_item.url())) { + installer->InstallUserScript(download_item.full_path(), + download_item.url()); + return; } + + bool is_gallery_download = service->IsDownloadFromGallery( + download_item.url(), download_item.referrer_url()); + installer->set_original_mime_type(download_item.original_mime_type()); + installer->set_apps_require_extension_mime_type(true); + installer->set_allow_privilege_increase(true); + installer->set_original_url(download_item.url()); + installer->set_is_gallery_install(is_gallery_download); + installer->InstallCrx(download_item.full_path()); + installer->set_allow_silent_install(is_gallery_download); } // Download progress painting -------------------------------------------------- @@ -575,10 +565,10 @@ std::wstring GetProgressStatusText(DownloadItem* download) { } else { amount.assign(received_size); } - amount_units = GetByteDisplayUnits(download->CurrentSpeed()); - std::wstring speed_text = - UTF16ToWideHack(FormatSpeed(download->CurrentSpeed(), amount_units, - true)); + int64 current_speed = download->CurrentSpeed(); + amount_units = GetByteDisplayUnits(current_speed); + std::wstring speed_text = UTF16ToWideHack(FormatSpeed(current_speed, + amount_units, true)); std::wstring speed_text_localized; if (base::i18n::AdjustStringForLocaleDirection(speed_text, &speed_text_localized)) @@ -647,13 +637,11 @@ void AppendNumberToPath(FilePath* path, int number) { // unique. If |path| does not exist, 0 is returned. If it fails to find such // a number, -1 is returned. int GetUniquePathNumber(const FilePath& path) { - const int kMaxAttempts = 100; - if (!file_util::PathExists(path)) return 0; FilePath new_path; - for (int count = 1; count <= kMaxAttempts; ++count) { + for (int count = 1; count <= kMaxUniqueFiles; ++count) { new_path = FilePath(path); AppendNumberToPath(&new_path, count); @@ -695,14 +683,12 @@ void CancelDownloadRequest(ResourceDispatcherHost* rdh, } int GetUniquePathNumberWithCrDownload(const FilePath& path) { - const int kMaxAttempts = 100; - if (!file_util::PathExists(path) && !file_util::PathExists(GetCrDownloadPath(path))) return 0; FilePath new_path; - for (int count = 1; count <= kMaxAttempts; ++count) { + for (int count = 1; count <= kMaxUniqueFiles; ++count) { new_path = FilePath(path); AppendNumberToPath(&new_path, count); @@ -714,6 +700,27 @@ int GetUniquePathNumberWithCrDownload(const FilePath& path) { return -1; } +namespace { + +// NOTE: If index is 0, deletes files that do not have the " (nnn)" appended. +void DeleteUniqueDownloadFile(const FilePath& path, int index) { + FilePath new_path(path); + if (index > 0) + AppendNumberToPath(&new_path, index); + file_util::Delete(new_path, false); +} + +} + +void EraseUniqueDownloadFiles(const FilePath& path) { + FilePath cr_path = GetCrDownloadPath(path); + + for (int index = 0; index <= kMaxUniqueFiles; ++index) { + DeleteUniqueDownloadFile(path, index); + DeleteUniqueDownloadFile(cr_path, index); + } +} + FilePath GetCrDownloadPath(const FilePath& suggested_path) { FilePath::StringType file_name; base::SStringPrintf( diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h index a32f171..0224a26 100644 --- a/chrome/browser/download/download_util.h +++ b/chrome/browser/download/download_util.h @@ -210,6 +210,10 @@ void CancelDownloadRequest(ResourceDispatcherHost* rdh, // a number, -1 is returned. int GetUniquePathNumberWithCrDownload(const FilePath& path); +// Erases all downloaded files with the specified path and name prefix. +// Used by download UI tests to clean up the download directory. +void EraseUniqueDownloadFiles(const FilePath& path_prefix); + // Returns a .crdownload intermediate path for the |suggested_path|. FilePath GetCrDownloadPath(const FilePath& suggested_path); diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc index fe777e4..d312c2e 100644 --- a/chrome/browser/download/save_page_browsertest.cc +++ b/chrome/browser/download/save_page_browsertest.cc @@ -7,10 +7,10 @@ #include "base/path_service.h" #include "base/scoped_temp_dir.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/net/url_request_mock_http_job.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/enumerate_modules_model_win.cc b/chrome/browser/enumerate_modules_model_win.cc index 0fbd575..27feaf4 100644 --- a/chrome/browser/enumerate_modules_model_win.cc +++ b/chrome/browser/enumerate_modules_model_win.cc @@ -61,13 +61,6 @@ Lock* lock = NULL; // Entries without any Description, Signer info, or Location will never be // marked as confirmed bad (only as suspicious). const ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = { - // Test DLLs, to demonstrate the feature. Will be removed soon. - { // apphelp.dll, "%systemroot%\\system32\\" - "f5fda581", "23d01d5b", "", "", "", NONE - }, { // rsaenh.dll, "%systemroot%\\system32\\", "Microsoft Windows" - "6af212cb", "23d01d5b", "7b47bf79", "", "", - static_cast(UPDATE | DISABLE | SEE_LINK) - }, // NOTE: Please keep this list sorted by dll name, then location. @@ -211,7 +204,7 @@ ModuleEnumerator::ModuleStatus ModuleEnumerator::Match( } ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer) -: observer_(observer) { + : observer_(observer) { CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_)); DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); } @@ -561,14 +554,14 @@ ListValue* EnumerateModulesModel::GetModuleList() { } EnumerateModulesModel::EnumerateModulesModel() -: scanning_(false), -confirmed_bad_modules_detected_(0), -suspected_bad_modules_detected_(0) { + : scanning_(false), + confirmed_bad_modules_detected_(0), + suspected_bad_modules_detected_(0) { const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); if (cmd_line.HasSwitch(switches::kConflictingModulesCheck)) { check_modules_timer_.Start( - base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs), - this, &EnumerateModulesModel::ScanNow); + base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs), + this, &EnumerateModulesModel::ScanNow); } lock = new Lock(); diff --git a/chrome/browser/enumerate_modules_model_win.h b/chrome/browser/enumerate_modules_model_win.h index 54684d0..bdbf989 100644 --- a/chrome/browser/enumerate_modules_model_win.h +++ b/chrome/browser/enumerate_modules_model_win.h @@ -112,7 +112,7 @@ class ModuleEnumerator : public base::RefCountedThreadSafe { const BlacklistEntry& blacklisted); explicit ModuleEnumerator(EnumerateModulesModel* observer); - virtual ~ModuleEnumerator(); + ~ModuleEnumerator(); // Start scanning the loaded module list (if a scan is not already in // progress). This function does not block while reading the module list, but diff --git a/chrome/browser/extensions/alert_apitest.cc b/chrome/browser/extensions/alert_apitest.cc index 8e70fdb..292e1bd 100644 --- a/chrome/browser/extensions/alert_apitest.cc +++ b/chrome/browser/extensions/alert_apitest.cc @@ -3,12 +3,12 @@ // found in the LICENSE file. #include "chrome/browser/app_modal_dialog.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/ui_test_utils.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AlertBasic) { diff --git a/chrome/browser/extensions/all_urls_apitest.cc b/chrome/browser/extensions/all_urls_apitest.cc index 9b56a89..d06d917 100644 --- a/chrome/browser/extensions/all_urls_apitest.cc +++ b/chrome/browser/extensions/all_urls_apitest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc index 80d2218..89a19a1 100644 --- a/chrome/browser/extensions/app_background_page_apitest.cc +++ b/chrome/browser/extensions/app_background_page_apitest.cc @@ -3,8 +3,8 @@ // found in the LICENSE file. #include "base/string_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ui_test_utils.h" #include "net/base/mock_host_resolver.h" diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index d540038..65bfe9c 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_host.h" @@ -11,6 +10,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ui_test_utils.h" #include "net/base/mock_host_resolver.h" diff --git a/chrome/browser/extensions/browser_action_apitest.cc b/chrome/browser/extensions/browser_action_apitest.cc index 5e76310..59e56ca 100644 --- a/chrome/browser/extensions/browser_action_apitest.cc +++ b/chrome/browser/extensions/browser_action_apitest.cc @@ -8,7 +8,6 @@ #include #endif -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/browser_action_test_util.h" #include "chrome/browser/extensions/extension_apitest.h" @@ -17,6 +16,7 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/extensions/browser_action_test_util_gtk.cc b/chrome/browser/extensions/browser_action_test_util_gtk.cc index 8318dce..3781bd6 100644 --- a/chrome/browser/extensions/browser_action_test_util_gtk.cc +++ b/chrome/browser/extensions/browser_action_test_util_gtk.cc @@ -6,11 +6,11 @@ #include -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/gtk/extension_popup_gtk.h" #include "chrome/browser/gtk/extension_view_gtk.h" #include "chrome/browser/gtk/view_id_util.h" +#include "chrome/browser/ui/browser.h" namespace { diff --git a/chrome/browser/extensions/browser_action_test_util_views.cc b/chrome/browser/extensions/browser_action_test_util_views.cc index 85f20a5..0a384c5 100644 --- a/chrome/browser/extensions/browser_action_test_util_views.cc +++ b/chrome/browser/extensions/browser_action_test_util_views.cc @@ -5,8 +5,8 @@ #include "chrome/browser/extensions/browser_action_test_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/views/browser_actions_container.h" #include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/views/toolbar_view.h" diff --git a/chrome/browser/extensions/content_script_extension_process_apitest.cc b/chrome/browser/extensions/content_script_extension_process_apitest.cc index 64574a0..f6748de 100644 --- a/chrome/browser/extensions/content_script_extension_process_apitest.cc +++ b/chrome/browser/extensions/content_script_extension_process_apitest.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/extensions/convert_user_script.h b/chrome/browser/extensions/convert_user_script.h index d779de0..678c6eb 100644 --- a/chrome/browser/extensions/convert_user_script.h +++ b/chrome/browser/extensions/convert_user_script.h @@ -19,6 +19,8 @@ class GURL; // should take ownership on success, or NULL and |error| on failure. // // NOTE: This function does file IO and should not be called on the UI thread. +// NOTE: The caller takes ownership of the directory at extension->path() on the +// returned object. scoped_refptr ConvertUserScriptToExtension( const FilePath& user_script, const GURL& original_url, std::string* error); diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc new file mode 100644 index 0000000..47a9143 --- /dev/null +++ b/chrome/browser/extensions/convert_web_app.cc @@ -0,0 +1,172 @@ +// 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/extensions/convert_web_app.h" + +#include +#include +#include +#include + +#include "base/base64.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/scoped_temp_dir.h" +#include "base/sha2.h" +#include "base/stringprintf.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/json_value_serializer.h" +#include "chrome/common/web_apps.h" +#include "gfx/codec/png_codec.h" +#include "googleurl/src/gurl.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace keys = extension_manifest_keys; + +using base::Time; + +namespace { + +const char kIconsDirName[] = "_icons"; + +// Create the public key for the converted web app. +// +// Web apps are not signed, but the public key for an extension doubles as +// its unique identity, and we need one of those. A web app's unique identity +// is its manifest URL, so we hash that to create a public key. There will be +// no corresponding private key, which means that these extensions cannot be +// auto-updated using ExtensionUpdater. But Chrome does notice updates to the +// manifest and regenerates these extensions. +std::string GenerateKey(const GURL& manifest_url) { + char raw[base::SHA256_LENGTH] = {0}; + std::string key; + base::SHA256HashString(manifest_url.spec().c_str(), + raw, + base::SHA256_LENGTH); + base::Base64Encode(std::string(raw, base::SHA256_LENGTH), &key); + return key; +} + +} + + +// Generates a version for the converted app using the current date. This isn't +// really needed, but it seems like useful information. +std::string ConvertTimeToExtensionVersion(const Time& create_time) { + Time::Exploded create_time_exploded; + create_time.UTCExplode(&create_time_exploded); + + double micros = static_cast( + (create_time_exploded.millisecond * Time::kMicrosecondsPerMillisecond) + + (create_time_exploded.second * Time::kMicrosecondsPerSecond) + + (create_time_exploded.minute * Time::kMicrosecondsPerMinute) + + (create_time_exploded.hour * Time::kMicrosecondsPerHour)); + double day_fraction = micros / Time::kMicrosecondsPerDay; + double stamp = day_fraction * std::numeric_limits::max(); + + // Ghetto-round, since VC++ doesn't have round(). + stamp = stamp >= (floor(stamp) + 0.5) ? (stamp + 1) : stamp; + + return base::StringPrintf("%i.%i.%i.%i", + create_time_exploded.year, + create_time_exploded.month, + create_time_exploded.day_of_month, + static_cast(stamp)); +} + +scoped_refptr ConvertWebAppToExtension( + const WebApplicationInfo& web_app, + const Time& create_time) { + FilePath user_data_temp_dir; + CHECK(PathService::Get(chrome::DIR_USER_DATA_TEMP, &user_data_temp_dir)); + + ScopedTempDir temp_dir; + if (!temp_dir.CreateUniqueTempDirUnderPath(user_data_temp_dir)) { + LOG(ERROR) << "Could not create temporary directory."; + return NULL; + } + + // Create the manifest + scoped_ptr root(new DictionaryValue); + root->SetString(keys::kPublicKey, GenerateKey(web_app.manifest_url)); + root->SetString(keys::kName, UTF16ToUTF8(web_app.title)); + root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time)); + root->SetString(keys::kDescription, UTF16ToUTF8(web_app.description)); + root->SetString(keys::kLaunchWebURL, web_app.app_url.spec()); + + // Add the icons. + DictionaryValue* icons = new DictionaryValue(); + root->Set(keys::kIcons, icons); + for (size_t i = 0; i < web_app.icons.size(); ++i) { + std::string size = StringPrintf("%i", web_app.icons[i].width); + std::string icon_path = StringPrintf("%s/%s.png", kIconsDirName, + size.c_str()); + icons->SetString(size, icon_path); + } + + // Add the permissions. + ListValue* permissions = new ListValue(); + root->Set(keys::kPermissions, permissions); + for (size_t i = 0; i < web_app.permissions.size(); ++i) { + permissions->Append(Value::CreateStringValue(web_app.permissions[i])); + } + + // Add the URLs. + ListValue* urls = new ListValue(); + root->Set(keys::kWebURLs, urls); + for (size_t i = 0; i < web_app.urls.size(); ++i) { + urls->Append(Value::CreateStringValue(web_app.urls[i].spec())); + } + + // Write the manifest. + FilePath manifest_path = temp_dir.path().Append( + Extension::kManifestFilename); + JSONFileValueSerializer serializer(manifest_path); + if (!serializer.Serialize(*root)) { + LOG(ERROR) << "Could not serialize manifest."; + return NULL; + } + + // Write the icon files. + FilePath icons_dir = temp_dir.path().AppendASCII(kIconsDirName); + if (!file_util::CreateDirectory(icons_dir)) { + LOG(ERROR) << "Could not create icons directory."; + return NULL; + } + for (size_t i = 0; i < web_app.icons.size(); ++i) { + FilePath icon_file = icons_dir.AppendASCII( + StringPrintf("%i.png", web_app.icons[i].width)); + std::vector image_data; + if (!gfx::PNGCodec::EncodeBGRASkBitmap(web_app.icons[i].data, + false, + &image_data)) { + LOG(ERROR) << "Could not create icon file."; + return NULL; + } + + const char* image_data_ptr = reinterpret_cast(&image_data[0]); + if (!file_util::WriteFile(icon_file, image_data_ptr, image_data.size())) { + LOG(ERROR) << "Could not write icon file."; + return NULL; + } + } + + // Finally, create the extension object to represent the unpacked directory. + std::string error; + scoped_refptr extension = Extension::Create( + temp_dir.path(), Extension::INTERNAL, *root, false, &error); + if (!extension) { + LOG(ERROR) << error; + return NULL; + } + + temp_dir.Take(); // The caller takes ownership of the directory. + return extension; +} diff --git a/chrome/browser/extensions/convert_web_app.h b/chrome/browser/extensions/convert_web_app.h new file mode 100644 index 0000000..4037265 --- /dev/null +++ b/chrome/browser/extensions/convert_web_app.h @@ -0,0 +1,43 @@ +// 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_EXTENSIONS_CONVERT_WEB_APP_H_ +#define CHROME_BROWSER_EXTENSIONS_CONVERT_WEB_APP_H_ +#pragma once + +#include + +#include "base/ref_counted.h" + +class Extension; + +namespace base { +class Time; +} + +struct WebApplicationInfo; + +// Generates a version number for an extension from a time. The goal is to make +// use of the version number to communicate the date in a human readable form, +// while maintaining high enough resolution to change each time an app is +// reinstalled. The version that is returned has the format: +// +// ... +// +// fraction is represented as a number between 0 and 2^16-1. Each unit is +// ~1.32 seconds. +std::string ConvertTimeToExtensionVersion(const base::Time& time); + +// Wraps the specified web app in an extension. The extension is created +// unpacked in the system temp dir. Returns a valid extension that the caller +// should take ownership on success, or NULL and |error| on failure. +// +// NOTE: This function does file IO and should not be called on the UI thread. +// NOTE: The caller takes ownership of the directory at extension->path() on the +// returned object. +scoped_refptr ConvertWebAppToExtension( + const WebApplicationInfo& web_app_info, + const base::Time& create_time); + +#endif // CHROME_BROWSER_EXTENSIONS_CONVERT_WEB_APP_H_ diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc new file mode 100644 index 0000000..fc10347 --- /dev/null +++ b/chrome/browser/extensions/convert_web_app_unittest.cc @@ -0,0 +1,174 @@ +// 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/extensions/convert_web_app.h" + +#include +#include + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/scoped_temp_dir.h" +#include "base/stringprintf.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "base/version.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_icon_set.h" +#include "chrome/common/extensions/extension_resource.h" +#include "chrome/common/extensions/url_pattern.h" +#include "chrome/common/web_apps.h" +#include "gfx/codec/png_codec.h" +#include "googleurl/src/gurl.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/image_decoder.h" + +namespace { + +// Returns an icon info corresponding to a canned icon. +WebApplicationInfo::IconInfo GetIconInfo(const GURL& url, int size) { + WebApplicationInfo::IconInfo result; + + FilePath icon_file; + if (!PathService::Get(chrome::DIR_TEST_DATA, &icon_file)) { + ADD_FAILURE() << "Could not get test data directory."; + return result; + } + + icon_file = icon_file.AppendASCII("extensions") + .AppendASCII("convert_web_app") + .AppendASCII(StringPrintf("%i.png", size)); + + result.url = url; + result.width = size; + result.height = size; + + std::string icon_data; + if (!file_util::ReadFileToString(icon_file, &icon_data)) { + ADD_FAILURE() << "Could not read test icon."; + return result; + } + + webkit_glue::ImageDecoder decoder; + result.data = decoder.Decode( + reinterpret_cast(icon_data.c_str()), + icon_data.size()); + EXPECT_FALSE(result.data.isNull()) << "Could not decode test icon."; + + return result; +} + +base::Time GetTestTime(int year, int month, int day, int hour, int minute, + int second, int millisecond) { + base::Time::Exploded exploded = {0}; + exploded.year = year; + exploded.month = month; + exploded.day_of_month = day; + exploded.hour = hour; + exploded.minute = minute; + exploded.second = second; + exploded.millisecond = millisecond; + return base::Time::FromUTCExploded(exploded); +} + +} // namespace + + +TEST(ExtensionFromWebApp, GenerateVersion) { + EXPECT_EQ("2010.1.1.0", + ConvertTimeToExtensionVersion( + GetTestTime(2010, 1, 1, 0, 0, 0, 0))); + EXPECT_EQ("2010.12.31.22111", + ConvertTimeToExtensionVersion( + GetTestTime(2010, 12, 31, 8, 5, 50, 500))); + EXPECT_EQ("2010.10.1.65535", + ConvertTimeToExtensionVersion( + GetTestTime(2010, 10, 1, 23, 59, 59, 999))); +} + +TEST(ExtensionFromWebApp, Basic) { + WebApplicationInfo web_app; + web_app.manifest_url = GURL("http://aaronboodman.com/gearpad/manifest.json"); + web_app.title = ASCIIToUTF16("Gearpad"); + web_app.description = ASCIIToUTF16("The best text editor in the universe!"); + web_app.app_url = GURL("http://aaronboodman.com/gearpad/"); + web_app.permissions.push_back("geolocation"); + web_app.permissions.push_back("notifications"); + web_app.urls.push_back(GURL("http://aaronboodman.com/gearpad/")); + + const int sizes[] = {16, 48, 128}; + for (size_t i = 0; i < arraysize(sizes); ++i) { + GURL icon_url(web_app.app_url.Resolve(StringPrintf("%i.png", sizes[i]))); + web_app.icons.push_back(GetIconInfo(icon_url, sizes[i])); + } + + scoped_refptr extension = ConvertWebAppToExtension( + web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0)); + ASSERT_TRUE(extension.get()); + + ScopedTempDir extension_dir; + extension_dir.Set(extension->path()); + + EXPECT_TRUE(extension->is_app()); + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_FALSE(extension->is_packaged_app()); + + EXPECT_EQ("lJqm1+jncOHClAuwif1QxNJKfeV9Fbl9IBZx7FkNwkA=", + extension->public_key()); + EXPECT_EQ("ncnbaadanljoanockmphfdkimpdedemj", extension->id()); + EXPECT_EQ("1978.12.11.0", extension->version()->GetString()); + EXPECT_EQ(UTF16ToUTF8(web_app.title), extension->name()); + EXPECT_EQ(UTF16ToUTF8(web_app.description), extension->description()); + EXPECT_EQ(web_app.app_url, extension->GetFullLaunchURL()); + EXPECT_EQ(2u, extension->api_permissions().size()); + EXPECT_TRUE(extension->HasApiPermission("geolocation")); + EXPECT_TRUE(extension->HasApiPermission("notifications")); + ASSERT_EQ(1u, extension->web_extent().patterns().size()); + EXPECT_EQ("http://aaronboodman.com/gearpad/*", + extension->web_extent().patterns()[0].GetAsString()); + + EXPECT_EQ(web_app.icons.size(), extension->icons().map().size()); + for (size_t i = 0; i < web_app.icons.size(); ++i) { + EXPECT_EQ(StringPrintf("_icons/%i.png", web_app.icons[i].width), + extension->icons().Get(web_app.icons[i].width, + ExtensionIconSet::MATCH_EXACTLY)); + ExtensionResource resource = extension->GetIconResource( + web_app.icons[i].width, ExtensionIconSet::MATCH_EXACTLY); + ASSERT_TRUE(!resource.empty()); + EXPECT_TRUE(file_util::PathExists(resource.GetFilePath())); + } +} + +TEST(ExtensionFromWebApp, Minimal) { + WebApplicationInfo web_app; + web_app.manifest_url = GURL("http://aaronboodman.com/gearpad/manifest.json"); + web_app.title = ASCIIToUTF16("Gearpad"); + web_app.app_url = GURL("http://aaronboodman.com/gearpad/"); + + scoped_refptr extension = ConvertWebAppToExtension( + web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0)); + ASSERT_TRUE(extension.get()); + + ScopedTempDir extension_dir; + extension_dir.Set(extension->path()); + + EXPECT_TRUE(extension->is_app()); + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_FALSE(extension->is_packaged_app()); + + EXPECT_EQ("lJqm1+jncOHClAuwif1QxNJKfeV9Fbl9IBZx7FkNwkA=", + extension->public_key()); + EXPECT_EQ("ncnbaadanljoanockmphfdkimpdedemj", extension->id()); + EXPECT_EQ("1978.12.11.0", extension->version()->GetString()); + EXPECT_EQ(UTF16ToUTF8(web_app.title), extension->name()); + EXPECT_EQ("", extension->description()); + EXPECT_EQ(web_app.app_url, extension->GetFullLaunchURL()); + EXPECT_EQ(0u, extension->icons().map().size()); + EXPECT_EQ(0u, extension->api_permissions().size()); + ASSERT_EQ(1u, extension->web_extent().patterns().size()); + EXPECT_EQ("*://aaronboodman.com/*", + extension->web_extent().patterns()[0].GetAsString()); +} diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index b2c60e3..d90bbbd 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -4,7 +4,7 @@ #include "chrome/browser/extensions/crx_installer.h" -#include +#include #include "app/l10n_util.h" #include "app/resource_bundle.h" @@ -12,6 +12,7 @@ #include "base/path_service.h" #include "base/scoped_temp_dir.h" #include "base/singleton.h" +#include "base/stl_util-inl.h" #include "base/stringprintf.h" #include "base/task.h" #include "base/thread_restrictions.h" @@ -45,7 +46,7 @@ static void DeleteFileHelper(const FilePath& path, bool recursive) { struct WhitelistedInstallData { WhitelistedInstallData() {} - std::list ids; + std::set ids; }; } // namespace @@ -53,25 +54,24 @@ struct WhitelistedInstallData { // static void CrxInstaller::SetWhitelistedInstallId(const std::string& id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - Singleton::get()->ids.push_back(id); + Singleton::get()->ids.insert(id); } // static -bool CrxInstaller::ClearWhitelistedInstallId(const std::string& id) { +bool CrxInstaller::IsIdWhitelisted(const std::string& id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::list& ids = Singleton::get()->ids; - std::list::iterator iter = ids.begin(); - for (; iter != ids.end(); ++iter) { - if (*iter == id) { - break; - } - } + std::set& ids = Singleton::get()->ids; + return ContainsKey(ids, id); +} - if (iter != ids.end()) { - ids.erase(iter); +// static +bool CrxInstaller::ClearWhitelistedInstallId(const std::string& id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::set& ids = Singleton::get()->ids; + if (ContainsKey(ids, id)) { + ids.erase(id); return true; } - return false; } @@ -204,10 +204,7 @@ bool CrxInstaller::AllowInstall(const Extension* extension, // For apps with a gallery update URL, require that they be installed // from the gallery. // TODO(erikkay) Apply this rule for paid extensions and themes as well. - if ((extension->update_url() == - GURL(extension_urls::kGalleryUpdateHttpsUrl)) || - (extension->update_url() == - GURL(extension_urls::kGalleryUpdateHttpUrl))) { + if (extension->UpdatesFromGallery()) { *error = l10n_util::GetStringFUTF8( IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS, l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); @@ -299,7 +296,7 @@ void CrxInstaller::ConfirmInstall() { frontend_->extension_prefs()->GetVersionString(extension_->id()); bool whitelisted = ClearWhitelistedInstallId(extension_->id()) && - extension_->plugins().empty(); + extension_->plugins().empty() && is_gallery_install_; if (client_ && (!allow_silent_install_ || !whitelisted)) { diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h index 349b225..5426b1a 100644 --- a/chrome/browser/extensions/crx_installer.h +++ b/chrome/browser/extensions/crx_installer.h @@ -53,6 +53,9 @@ class CrxInstaller // crbug.com/54916 static void SetWhitelistedInstallId(const std::string& id); + // Returns whether |id| is whitelisted - only call this on the UI thread. + static bool IsIdWhitelisted(const std::string& id); + // Returns whether |id| was found and removed (was whitelisted). This should // only be called on the UI thread. static bool ClearWhitelistedInstallId(const std::string& id); diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc index 535efc9..c4adb21 100644 --- a/chrome/browser/extensions/crx_installer_browsertest.cc +++ b/chrome/browser/extensions/crx_installer_browsertest.cc @@ -2,12 +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/browser.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/ui_test_utils.h" namespace { @@ -55,6 +55,7 @@ class ExtensionCrxInstallerTest : public ExtensionBrowserTest { mock_install_ui /* ownership transferred */)); installer->set_allow_silent_install(true); + installer->set_is_gallery_install(true); CrxInstaller::SetWhitelistedInstallId(id); FilePath crx_path = test_data_dir_.AppendASCII(crx_relpath); @@ -73,5 +74,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Whitelisting) { // An extension with NPAPI should give a prompt. EXPECT_TRUE(DidWhitelistInstallPrompt("uitest/plugins.crx", "hdgllgikmikobbofgnabhfimcfoopgnd")); -#endif // !defined(OS_CHROMEOS +#endif // !defined(OS_CHROMEOS) } diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc index 1dff210..9dae119 100644 --- a/chrome/browser/extensions/default_apps.cc +++ b/chrome/browser/extensions/default_apps.cc @@ -5,6 +5,7 @@ #include "chrome/browser/extensions/default_apps.h" #include "base/command_line.h" +#include "base/metrics/histogram.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -53,6 +54,10 @@ void DefaultApps::DidInstallApp(const ExtensionIdSet& installed_ids) { } bool DefaultApps::ShouldShowPromo(const ExtensionIdSet& installed_ids) { +#if defined(OS_CHROMEOS) + // Don't show the promo at all on Chrome OS. + return false; +#endif if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kForceAppsPromoVisible)) { return true; @@ -84,10 +89,15 @@ void DefaultApps::DidShowPromo() { return; } - if (promo_counter < kAppsPromoCounterMax) + if (promo_counter < kAppsPromoCounterMax) { + if (promo_counter + 1 == kAppsPromoCounterMax) + UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, + extension_misc::PROMO_EXPIRE, + extension_misc::PROMO_BUCKET_BOUNDARY); SetPromoCounter(++promo_counter); - else + } else { SetPromoHidden(); + } } void DefaultApps::SetPromoHidden() { diff --git a/chrome/browser/extensions/default_apps_unittest.cc b/chrome/browser/extensions/default_apps_unittest.cc index 24a9d70..381e679 100644 --- a/chrome/browser/extensions/default_apps_unittest.cc +++ b/chrome/browser/extensions/default_apps_unittest.cc @@ -7,7 +7,8 @@ #include "chrome/test/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" -// TODO(dpolukhin): On Chrome OS all apps are installed via external extensions +// TODO(dpolukhin): On Chrome OS all apps are installed via external extensions, +// and the web store promo is never shown. #if !defined(OS_CHROMEOS) TEST(DefaultApps, Basics) { TestingPrefService pref_service; @@ -61,7 +62,6 @@ TEST(DefaultApps, Basics) { EXPECT_FALSE(default_apps.ShouldShowPromo(default_app_ids)); EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter()); } -#endif // OS_CHROMEOS TEST(DefaultApps, HidePromo) { TestingPrefService pref_service; @@ -100,8 +100,6 @@ TEST(DefaultApps, InstallingAnAppHidesPromo) { EXPECT_EQ(DefaultApps::kAppsPromoCounterMax, default_apps.GetPromoCounter()); } -// TODO(dpolukhin): On Chrome OS all apps are installed via external extensions -#if !defined(OS_CHROMEOS) TEST(DefaultApps, ManualAppInstalledWhileInstallingDefaultApps) { // It is possible to have apps manually installed while the default apps are // being installed. The network or server might be down, causing the default diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc index 8021e6c..52bf74f 100644 --- a/chrome/browser/extensions/execute_code_in_tab_function.cc +++ b/chrome/browser/extensions/execute_code_in_tab_function.cc @@ -7,13 +7,13 @@ #include "base/callback.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extension_tabs_module_constants.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/file_reader.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_error_utils.h" diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc index 4c60b5e..3dd0345 100644 --- a/chrome/browser/extensions/extension_accessibility_api.cc +++ b/chrome/browser/extensions/extension_accessibility_api.cc @@ -8,7 +8,6 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_accessibility_api.h" @@ -17,6 +16,7 @@ #include "chrome/browser/extensions/extension_function_dispatcher.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index 07668b3..f65d8eb 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc @@ -6,10 +6,10 @@ #include "base/string_util.h" #include "base/stringprintf.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_test_api.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_registrar.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/extensions/extension_browser_actions_api.cc b/chrome/browser/extensions/extension_browser_actions_api.cc index 1986d28..8e17a35 100644 --- a/chrome/browser/extensions/extension_browser_actions_api.cc +++ b/chrome/browser/extensions/extension_browser_actions_api.cc @@ -5,8 +5,8 @@ #include "chrome/browser/extensions/extension_browser_actions_api.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc index dcf9b9d..ce0d673 100644 --- a/chrome/browser/extensions/extension_browser_event_router.cc +++ b/chrome/browser/extensions/extension_browser_event_router.cc @@ -6,17 +6,17 @@ #include "base/json/json_writer.h" #include "base/values.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension_event_names.h" #include "chrome/browser/extensions/extension_event_router.h" -#include "chrome/browser/extensions/extension_tabs_module_constants.h" #include "chrome/browser/extensions/extension_page_actions_module_constants.h" +#include "chrome/browser/extensions/extension_tabs_module_constants.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/common/extensions/extension.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" namespace events = extension_event_names; diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index af8a6de..bea1c5e 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -10,17 +10,17 @@ #include "base/file_path.h" #include "base/path_service.h" #include "base/string_number_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" -#include "chrome/browser/location_bar.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" -#include "chrome/common/chrome_switches.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc index 3b1780d..224c1f8 100644 --- a/chrome/browser/extensions/extension_browsertests_misc.cc +++ b/chrome/browser/extensions/extension_browsertests_misc.cc @@ -5,9 +5,7 @@ #include "base/file_util.h" #include "base/ref_counted.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/extensions/autoupdate_interceptor.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_browsertest.h" @@ -18,9 +16,11 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc index da83124..2397aa7 100644 --- a/chrome/browser/extensions/extension_context_menu_browsertest.cc +++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc @@ -4,7 +4,6 @@ #include "app/menus/menu_model.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_test_message_listener.h" @@ -12,6 +11,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/render_view_context_menu.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ui_test_utils.h" #include "net/base/mock_host_resolver.h" diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc index 404241e..1325b5e 100644 --- a/chrome/browser/extensions/extension_context_menu_model.cc +++ b/chrome/browser/extensions/extension_context_menu_model.cc @@ -5,15 +5,15 @@ #include "chrome/browser/extensions/extension_context_menu_model.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" -#include "chrome/common/extensions/extension.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/extensions/extension_cookies_helpers.cc b/chrome/browser/extensions/extension_cookies_helpers.cc index ac00183..cef1d1e 100644 --- a/chrome/browser/extensions/extension_cookies_helpers.cc +++ b/chrome/browser/extensions/extension_cookies_helpers.cc @@ -8,11 +8,11 @@ #include "base/logging.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_cookies_api_constants.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/profile.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc index 3ad8813..898de6b 100644 --- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc +++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/process_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/crashed_extension_infobar.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_host.h" @@ -14,6 +13,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/ui_test_utils.h" class ExtensionCrashRecoveryTest : public ExtensionBrowserTest { diff --git a/chrome/browser/extensions/extension_devtools_browsertests.cc b/chrome/browser/extensions/extension_devtools_browsertests.cc index c195aa7..3bfd134 100644 --- a/chrome/browser/extensions/extension_devtools_browsertests.cc +++ b/chrome/browser/extensions/extension_devtools_browsertests.cc @@ -4,11 +4,9 @@ #include "base/ref_counted.h" #include "base/stringprintf.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/debugger/devtools_client_host.h" +#include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/extensions/extension_devtools_browsertest.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_host.h" @@ -16,9 +14,11 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/devtools_messages.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc index af38e4f..d66a448 100644 --- a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc @@ -78,8 +78,9 @@ class ExtensionDisabledInfobarDelegate virtual ~ExtensionDisabledInfobarDelegate() { } virtual string16 GetMessageText() const { - return l10n_util::GetStringFUTF16(IDS_EXTENSION_DISABLED_INFOBAR_LABEL, - UTF8ToUTF16(extension_->name())); + return l10n_util::GetStringFUTF16(extension_->is_app() ? + IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL, + UTF8ToUTF16(extension_->name())); } virtual SkBitmap* GetIcon() const { return NULL; diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc index 602ad6a..c0522f0 100644 --- a/chrome/browser/extensions/extension_dom_ui.cc +++ b/chrome/browser/extensions/extension_dom_ui.cc @@ -9,7 +9,6 @@ #include "net/base/file_stream.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/extension_bookmark_manager_api.h" @@ -19,13 +18,14 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/page_transition_types.h" -#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_icon_set.h" #include "chrome/common/extensions/extension_resource.h" +#include "chrome/common/page_transition_types.h" #include "chrome/common/url_constants.h" #include "gfx/codec/png_codec.h" #include "gfx/favicon_size.h" @@ -185,9 +185,14 @@ void ExtensionDOMUI::ProcessDOMUIMessage( } Browser* ExtensionDOMUI::GetBrowser() const { - // TODO(beng): This is an improper direct dependency on Browser. Route this - // through some sort of delegate. - return BrowserList::FindBrowserWithProfile(DOMUI::GetProfile()); + TabContents* contents = tab_contents(); + TabContentsIterator tab_iterator; + for (; !tab_iterator.done(); ++tab_iterator) { + if (contents == *tab_iterator) + return tab_iterator.browser(); + } + + return NULL; } TabContents* ExtensionDOMUI::associated_tab_contents() const { diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index beb96e8..47531f4 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -36,6 +36,7 @@ #include "chrome/browser/extensions/extension_management_api.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_metrics_module.h" +#include "chrome/browser/extensions/extension_module.h" #include "chrome/browser/extensions/extension_omnibox_api.h" #include "chrome/browser/extensions/extension_page_actions_module.h" #include "chrome/browser/extensions/extension_popup_api.h" @@ -279,12 +280,16 @@ void FactoryRegistry::ResetFunctions() { RegisterFunction(); RegisterFunction(); + // Extension module. + RegisterFunction(); + // WebstorePrivate. RegisterFunction(); RegisterFunction(); - RegisterFunction(); RegisterFunction(); RegisterFunction(); + RegisterFunction(); + RegisterFunction(); } void FactoryRegistry::GetAllNames(std::vector* names) { diff --git a/chrome/browser/extensions/extension_gallery_install_apitest.cc b/chrome/browser/extensions/extension_gallery_install_apitest.cc index cf10ed4..820d9ef 100644 --- a/chrome/browser/extensions/extension_gallery_install_apitest.cc +++ b/chrome/browser/extensions/extension_gallery_install_apitest.cc @@ -16,6 +16,22 @@ class ExtensionGalleryInstallApiTest : public ExtensionApiTest { command_line->AppendSwitchASCII(switches::kAppsGalleryURL, "http://www.example.com"); } + + bool RunInstallTest(const std::string& page) { + std::string base_url = base::StringPrintf( + "http://www.example.com:%u/files/extensions/", + test_server()->host_port_pair().port()); + + std::string testing_install_base_url = base_url; + testing_install_base_url += "good.crx"; + CompleteInstallFunction::SetTestingInstallBaseUrl( + testing_install_base_url.c_str()); + + std::string page_url = base_url; + page_url += "api_test/extension_gallery_install/" + page; + + return RunPageTest(page_url.c_str()); + } }; // http://crbug.com/55642 - failing on XP. @@ -29,15 +45,11 @@ IN_PROC_BROWSER_TEST_F(ExtensionGalleryInstallApiTest, host_resolver()->AddRule("www.example.com", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); - std::string base_url = base::StringPrintf( - "http://www.example.com:%u/files/extensions/", - test_server()->host_port_pair().port()); - - std::string testing_install_base_url = base_url; - testing_install_base_url += "good.crx"; - InstallFunction::SetTestingInstallBaseUrl(testing_install_base_url.c_str()); + BeginInstallFunction::SetIgnoreUserGestureForTests(true); + ASSERT_TRUE(RunInstallTest("test.html")); + ASSERT_TRUE(RunInstallTest("complete_without_begin.html")); + ASSERT_TRUE(RunInstallTest("invalid_begin.html")); - std::string page_url = base_url; - page_url += "api_test/extension_gallery_install/test.html"; - ASSERT_TRUE(RunPageTest(page_url.c_str())); + BeginInstallFunction::SetIgnoreUserGestureForTests(false); + ASSERT_TRUE(RunInstallTest("no_user_gesture.html")); } diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 09d30b7..4aea841 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -13,7 +13,6 @@ #include "base/singleton.h" #include "base/metrics/histogram.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/browser_window.h" @@ -38,6 +37,7 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" @@ -157,14 +157,6 @@ ExtensionHost::~ExtensionHost() { Details(this)); ProcessCreationQueue::get()->Remove(this); render_view_host_->Shutdown(); // deletes render_view_host - - if (recently_deleted()->size() >= 20) - recently_deleted()->pop_front(); - recently_deleted()->push_back(this); -} - -ExtensionHost::HostPointerList* ExtensionHost::recently_deleted() { - return Singleton::get(); } void ExtensionHost::CreateView(Browser* browser) { diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index bb96c5d..d121145 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -6,7 +6,6 @@ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_H_ #pragma once -#include #include #include @@ -48,9 +47,6 @@ class ExtensionHost : public RenderViewHostDelegate, // Enable DOM automation in created render view hosts. static void EnableDOMAutomation() { enable_dom_automation_ = true; } - typedef std::list HostPointerList; - static HostPointerList* recently_deleted(); - ExtensionHost(const Extension* extension, SiteInstance* site_instance, const GURL& url, ViewType::Type host_type); ~ExtensionHost(); diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc index 8af7d97..76144a4 100644 --- a/chrome/browser/extensions/extension_idle_api.cc +++ b/chrome/browser/extensions/extension_idle_api.cc @@ -14,12 +14,12 @@ #include "base/stl_util-inl.h" #include "base/task.h" #include "base/time.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_idle_api_constants.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc index 372b7a6..f4824ec 100644 --- a/chrome/browser/extensions/extension_incognito_apitest.cc +++ b/chrome/browser/extensions/extension_incognito_apitest.cc @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/browser_action_test_util.h" #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" @@ -91,8 +91,16 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) { ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile()); } +// TODO(kochi): Flaky at r65757 and after on buildbot for ChromiumOS. +// http://crosbug.com/9049 +#if defined(OS_CHROMEOS) +#define MAYBE_Incognito FLAKY_Incognito +#else +#define MAYBE_Incognito Incognito +#endif + // Tests that the APIs in an incognito-enabled extension work properly. -IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) { +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Incognito) { host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(StartTestServer()); diff --git a/chrome/browser/extensions/extension_infobar_delegate.cc b/chrome/browser/extensions/extension_infobar_delegate.cc index 0aea7ce..3f9b861 100644 --- a/chrome/browser/extensions/extension_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_infobar_delegate.cc @@ -4,11 +4,11 @@ #include "chrome/browser/extensions/extension_infobar_delegate.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" diff --git a/chrome/browser/extensions/extension_infobar_delegate.h b/chrome/browser/extensions/extension_infobar_delegate.h index 949b655..e929fee 100644 --- a/chrome/browser/extensions/extension_infobar_delegate.h +++ b/chrome/browser/extensions/extension_infobar_delegate.h @@ -54,7 +54,7 @@ class ExtensionInfoBarDelegate : public InfoBarDelegate, // The extension host we are showing the InfoBar for. The delegate needs to // own this since the InfoBar gets deleted and recreated when you switch tabs // and come back (and we don't want the user's interaction with the InfoBar to - // get lost at that point. + // get lost at that point). scoped_ptr extension_host_; // The observer monitoring when the delegate dies. diff --git a/chrome/browser/extensions/extension_infobar_module.cc b/chrome/browser/extensions/extension_infobar_module.cc index 6662bea..f86abd2 100644 --- a/chrome/browser/extensions/extension_infobar_module.cc +++ b/chrome/browser/extensions/extension_infobar_module.cc @@ -7,7 +7,6 @@ #include "base/string_util.h" #include "base/string_number_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_infobar_module_constants.h" #include "chrome/browser/extensions/extension_infobar_delegate.h" @@ -15,6 +14,7 @@ #include "chrome/browser/extensions/extension_tabs_module_constants.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_error_utils.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/extensions/extension_input_api.cc b/chrome/browser/extensions/extension_input_api.cc index c4ce3f6..850a344 100644 --- a/chrome/browser/extensions/extension_input_api.cc +++ b/chrome/browser/extensions/extension_input_api.cc @@ -8,11 +8,11 @@ #include "app/keyboard_code_conversion.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/common/native_web_keyboard_event.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc index 3c5f819..2f1efd5 100644 --- a/chrome/browser/extensions/extension_install_ui.cc +++ b/chrome/browser/extensions/extension_install_ui.cc @@ -155,6 +155,7 @@ void ExtensionInstallUI::OnInstallSuccess(const Extension* extension) { // Note that browser actions don't appear in incognito mode initially, // so fall back to the generic case. if ((extension->browser_action() && !browser->profile()->IsOffTheRecord()) || + !extension->omnibox_keyword().empty() || (extension->page_action() && !extension->page_action()->default_icon_path().empty())) { ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble( diff --git a/chrome/browser/extensions/extension_install_ui_browsertest.cc b/chrome/browser/extensions/extension_install_ui_browsertest.cc index 9a5a9f2..818c414 100644 --- a/chrome/browser/extensions/extension_install_ui_browsertest.cc +++ b/chrome/browser/extensions/extension_install_ui_browsertest.cc @@ -2,12 +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/browser.h" -#include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/ui_test_utils.h" namespace { diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc index 44fd63f..60edbc9 100644 --- a/chrome/browser/extensions/extension_management_api.cc +++ b/chrome/browser/extensions/extension_management_api.cc @@ -11,15 +11,15 @@ #include "base/json/json_writer.h" #include "base/string_number_conversions.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_event_names.h" #include "chrome/browser/extensions/extension_event_router.h" -#include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/profile.h" -#include "chrome/common/extensions/extension.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_error_utils.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_icon_set.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" diff --git a/chrome/browser/extensions/extension_management_apitest.cc b/chrome/browser/extensions/extension_management_apitest.cc index 75b0880..61a5d77 100644 --- a/chrome/browser/extensions/extension_management_apitest.cc +++ b/chrome/browser/extensions/extension_management_apitest.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" class ExtensionManagementApiTest : public ExtensionApiTest { public: diff --git a/chrome/browser/extensions/extension_management_browsertest.cc b/chrome/browser/extensions/extension_management_browsertest.cc index 7931e91..94eebdf 100644 --- a/chrome/browser/extensions/extension_management_browsertest.cc +++ b/chrome/browser/extensions/extension_management_browsertest.cc @@ -3,8 +3,6 @@ // found in the LICENSE file. #include "base/ref_counted.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/extensions/autoupdate_interceptor.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_host.h" @@ -12,6 +10,8 @@ #include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/extensions/extension_module.cc b/chrome/browser/extensions/extension_module.cc new file mode 100644 index 0000000..84c3789 --- /dev/null +++ b/chrome/browser/extensions/extension_module.cc @@ -0,0 +1,23 @@ +// 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/extensions/extension_module.h" + +#include + +#include "chrome/browser/extensions/extension_prefs.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" + +ExtensionPrefs* SetUpdateUrlDataFunction::extension_prefs() { + return profile()->GetExtensionsService()->extension_prefs(); +} + +bool SetUpdateUrlDataFunction::RunImpl() { + std::string data; + EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &data)); + + extension_prefs()->SetUpdateUrlData(extension_id(), data); + return true; +} diff --git a/chrome/browser/extensions/extension_module.h b/chrome/browser/extensions/extension_module.h new file mode 100644 index 0000000..21227a2 --- /dev/null +++ b/chrome/browser/extensions/extension_module.h @@ -0,0 +1,20 @@ +// 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_EXTENSIONS_EXTENSION_MODULE_H__ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__ +#pragma once + +#include "chrome/browser/extensions/extension_function.h" + +class ExtensionPrefs; + +class SetUpdateUrlDataFunction : public SyncExtensionFunction { + protected: + ExtensionPrefs* extension_prefs(); + virtual bool RunImpl(); + DECLARE_EXTENSION_FUNCTION_NAME("extension.setUpdateUrlData"); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__ diff --git a/chrome/browser/extensions/extension_module_apitest.cc b/chrome/browser/extensions/extension_module_apitest.cc new file mode 100644 index 0000000..718c422 --- /dev/null +++ b/chrome/browser/extensions/extension_module_apitest.cc @@ -0,0 +1,12 @@ +// 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/extensions/extension_apitest.h" + +class ExtensionModuleApiTest : public ExtensionApiTest { +}; + +IN_PROC_BROWSER_TEST_F(ExtensionModuleApiTest, Basics) { + ASSERT_TRUE(RunExtensionTest("extension_module")) << message_; +} diff --git a/chrome/browser/extensions/extension_omnibox_api.cc b/chrome/browser/extensions/extension_omnibox_api.cc index 93b44bd..c31233c 100644 --- a/chrome/browser/extensions/extension_omnibox_api.cc +++ b/chrome/browser/extensions/extension_omnibox_api.cc @@ -12,10 +12,10 @@ #include "chrome/common/notification_service.h" namespace events { -const char kOnInputStarted[] = "experimental.omnibox.onInputStarted"; -const char kOnInputChanged[] = "experimental.omnibox.onInputChanged"; -const char kOnInputEntered[] = "experimental.omnibox.onInputEntered"; -const char kOnInputCancelled[] = "experimental.omnibox.onInputCancelled"; +const char kOnInputStarted[] = "omnibox.onInputStarted"; +const char kOnInputChanged[] = "omnibox.onInputChanged"; +const char kOnInputEntered[] = "omnibox.onInputEntered"; +const char kOnInputCancelled[] = "omnibox.onInputCancelled"; }; // namespace events namespace { @@ -30,6 +30,7 @@ const char kSuggestionDescription[] = "description"; const char kSuggestionDescriptionStyles[] = "descriptionStyles"; const char kDescriptionStylesType[] = "type"; const char kDescriptionStylesOffset[] = "offset"; +const char kDescriptionStylesLength[] = "length"; }; // namespace // static @@ -103,47 +104,10 @@ bool OmniboxSendSuggestionsFunction::RunImpl() { ListValue* styles; EXTENSION_FUNCTION_VALIDATE( suggestion_value->GetList(kSuggestionDescriptionStyles, &styles)); - + EXTENSION_FUNCTION_VALIDATE(suggestion.ReadStylesFromValue(*styles)); + } else { suggestion.description_styles.clear(); - - int last_offset = -1; - for (size_t j = 0; j < styles->GetSize(); ++j) { - DictionaryValue* style; - std::string type; - int offset; - EXTENSION_FUNCTION_VALIDATE(styles->GetDictionary(j, &style)); - EXTENSION_FUNCTION_VALIDATE( - style->GetString(kDescriptionStylesType, &type)); - EXTENSION_FUNCTION_VALIDATE( - style->GetInteger(kDescriptionStylesOffset, &offset)); - - int type_class = - (type == "none") ? ACMatchClassification::NONE : - (type == "url") ? ACMatchClassification::URL : - (type == "match") ? ACMatchClassification::MATCH : - (type == "dim") ? ACMatchClassification::DIM : -1; - EXTENSION_FUNCTION_VALIDATE(type_class != -1); - - if (offset <= last_offset) { - error_ = kDescriptionStylesOrderError; - return false; - } - if (static_cast(offset) >= suggestion.description.length()) { - error_ = kDescriptionStylesLengthError; - return false; - } - - suggestion.description_styles.push_back( - ACMatchClassification(offset, type_class)); - last_offset = offset; - } - } - - // Ensure the styles cover the whole range of text. - if (suggestion.description_styles.empty() || - suggestion.description_styles[0].offset != 0) { - suggestion.description_styles.insert( - suggestion.description_styles.begin(), + suggestion.description_styles.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); } } @@ -160,7 +124,52 @@ ExtensionOmniboxSuggestion::ExtensionOmniboxSuggestion() {} ExtensionOmniboxSuggestion::~ExtensionOmniboxSuggestion() {} +bool ExtensionOmniboxSuggestion::ReadStylesFromValue( + const ListValue& styles_value) { + description_styles.clear(); + + // Step 1: Build a vector of styles, 1 per character of description text. + std::vector styles; + styles.resize(description.length()); // sets all styles to 0 + + for (size_t i = 0; i < styles_value.GetSize(); ++i) { + DictionaryValue* style; + std::string type; + int offset; + int length; + if (!styles_value.GetDictionary(i, &style)) + return false; + if (!style->GetString(kDescriptionStylesType, &type)) + return false; + if (!style->GetInteger(kDescriptionStylesOffset, &offset)) + return false; + if (!style->GetInteger(kDescriptionStylesLength, &length) || length < 0) + length = description.length(); + + if (offset < 0) + offset = std::max(0, static_cast(description.length()) + offset); + + int type_class = + (type == "url") ? ACMatchClassification::URL : + (type == "match") ? ACMatchClassification::MATCH : + (type == "dim") ? ACMatchClassification::DIM : -1; + if (type_class == -1) + return false; + + for (int j = offset; + j < offset + length && j < static_cast(styles.size()); ++j) + styles[j] |= type_class; + } + + // Step 2: Convert the vector into continous runs of common styles. + for (size_t i = 0; i < styles.size(); ++i) { + if (i == 0 || styles[i] != styles[i-1]) + description_styles.push_back(ACMatchClassification(i, styles[i])); + } + + return true; +} + ExtensionOmniboxSuggestions::ExtensionOmniboxSuggestions() : request_id(0) {} ExtensionOmniboxSuggestions::~ExtensionOmniboxSuggestions() {} - diff --git a/chrome/browser/extensions/extension_omnibox_api.h b/chrome/browser/extensions/extension_omnibox_api.h index 9d0dc99..7c4d44c 100644 --- a/chrome/browser/extensions/extension_omnibox_api.h +++ b/chrome/browser/extensions/extension_omnibox_api.h @@ -42,13 +42,17 @@ class ExtensionOmniboxEventRouter { class OmniboxSendSuggestionsFunction : public SyncExtensionFunction { public: virtual bool RunImpl(); - DECLARE_EXTENSION_FUNCTION_NAME("experimental.omnibox.sendSuggestions"); + DECLARE_EXTENSION_FUNCTION_NAME("omnibox.sendSuggestions"); }; struct ExtensionOmniboxSuggestion { ExtensionOmniboxSuggestion(); ~ExtensionOmniboxSuggestion(); + // Converts a list of style ranges from the extension into the format expected + // by the autocomplete system. + bool ReadStylesFromValue(const ListValue& value); + // The text that gets put in the edit box. string16 content; diff --git a/chrome/browser/extensions/extension_omnibox_apitest.cc b/chrome/browser/extensions/extension_omnibox_apitest.cc index 9f9c6a0..defa068 100644 --- a/chrome/browser/extensions/extension_omnibox_apitest.cc +++ b/chrome/browser/extensions/extension_omnibox_apitest.cc @@ -10,13 +10,13 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_type.h" #include "chrome/common/url_constants.h" @@ -76,9 +76,6 @@ class OmniboxApiTest : public ExtensionApiTest { }; IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) { - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableExperimentalExtensionApis); - ASSERT_TRUE(test_server()->Start()); ASSERT_TRUE(RunExtensionTest("omnibox")) << message_; @@ -93,7 +90,7 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) { // it. { autocomplete_controller->Start(L"keywor", std::wstring(), - true, false, false); + true, false, true, false); WaitForAutocompleteDone(autocomplete_controller); EXPECT_TRUE(autocomplete_controller->done()); @@ -118,7 +115,7 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) { // Test that our extension can send suggestions back to us. { autocomplete_controller->Start(L"keyword suggestio", std::wstring(), - true, false, false); + true, false, true, false); WaitForAutocompleteDone(autocomplete_controller); EXPECT_TRUE(autocomplete_controller->done()); @@ -135,30 +132,41 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) { EXPECT_EQ(L"keyword suggestion2", result.match_at(2).fill_into_edit); EXPECT_EQ(L"keyword suggestion3", result.match_at(3).fill_into_edit); - std::wstring description = L"Description with style: [dim], none"; + std::wstring description = + L"Description with style: , [dim], (url till end)"; EXPECT_EQ(description, result.match_at(1).contents); - ASSERT_EQ(5u, result.match_at(1).contents_class.size()); + ASSERT_EQ(6u, result.match_at(1).contents_class.size()); + EXPECT_EQ(0u, result.match_at(1).contents_class[0].offset); EXPECT_EQ(ACMatchClassification::NONE, result.match_at(1).contents_class[0].style); + EXPECT_EQ(description.find('<'), result.match_at(1).contents_class[1].offset); EXPECT_EQ(ACMatchClassification::MATCH, result.match_at(1).contents_class[1].style); + EXPECT_EQ(description.find('>'), result.match_at(1).contents_class[2].offset); EXPECT_EQ(ACMatchClassification::NONE, result.match_at(1).contents_class[2].style); + EXPECT_EQ(description.find('['), result.match_at(1).contents_class[3].offset); EXPECT_EQ(ACMatchClassification::DIM, result.match_at(1).contents_class[3].style); + EXPECT_EQ(description.find(']'), result.match_at(1).contents_class[4].offset); EXPECT_EQ(ACMatchClassification::NONE, result.match_at(1).contents_class[4].style); + EXPECT_EQ(description.find('('), + result.match_at(1).contents_class[5].offset); + EXPECT_EQ(ACMatchClassification::URL, + result.match_at(1).contents_class[5].style); + AutocompleteMatch match = result.match_at(4); EXPECT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, match.type); EXPECT_FALSE(match.deletable); @@ -167,7 +175,7 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) { { ResultCatcher catcher; autocomplete_controller->Start(L"keyword command", std::wstring(), - true, false, false); + true, false, true, false); location_bar->AcceptInput(); EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } diff --git a/chrome/browser/extensions/extension_omnibox_unittest.cc b/chrome/browser/extensions/extension_omnibox_unittest.cc new file mode 100644 index 0000000..a358b18 --- /dev/null +++ b/chrome/browser/extensions/extension_omnibox_unittest.cc @@ -0,0 +1,133 @@ +// 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 "base/values.h" +#include "chrome/browser/extensions/extension_omnibox_api.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +const int kNone = ACMatchClassification::NONE; +const int kUrl = ACMatchClassification::URL; +const int kMatch = ACMatchClassification::MATCH; +const int kDim = ACMatchClassification::DIM; + +void AppendStyle(const std::string& type, + int offset, int length, + ListValue* styles) { + DictionaryValue* style = new DictionaryValue; + style->SetString("type", type); + style->SetInteger("offset", offset); + style->SetInteger("length", length); + styles->Append(style); +} + +void CompareClassification(const ACMatchClassifications& expected, + const ACMatchClassifications& actual) { + EXPECT_EQ(expected.size(), actual.size()); + for (size_t i = 0; i < expected.size() && i < actual.size(); ++i) { + EXPECT_EQ(expected[i].offset, actual[i].offset) << "Index:" << i; + EXPECT_EQ(expected[i].style, actual[i].style) << "Index:" << i; + } +} + +} // namespace + +// Test output key: n = character with no styling, d = dim, m = match, u = url +// u = 1, m = 2, d = 4. u+d = 5, etc. + +// 0123456789 +// mmmm +// + ddd +// = nmmmmndddn +TEST(ExtensionOmniboxTest, DescriptionStylesSimple) { + ListValue styles_value; + AppendStyle("match", 1, 4, &styles_value); + AppendStyle("dim", 6, 3, &styles_value); + + ACMatchClassifications styles_expected; + styles_expected.push_back(ACMatchClassification(0, kNone)); + styles_expected.push_back(ACMatchClassification(1, kMatch)); + styles_expected.push_back(ACMatchClassification(5, kNone)); + styles_expected.push_back(ACMatchClassification(6, kDim)); + styles_expected.push_back(ACMatchClassification(9, kNone)); + + ExtensionOmniboxSuggestion suggestions; + suggestions.description.resize(10); + EXPECT_TRUE(suggestions.ReadStylesFromValue(styles_value)); + CompareClassification(styles_expected, suggestions.description_styles); + + // Same input, but swap the order. Ensure it still works. + styles_value.Clear(); + AppendStyle("dim", 6, 3, &styles_value); + AppendStyle("match", 1, 4, &styles_value); + EXPECT_TRUE(suggestions.ReadStylesFromValue(styles_value)); + CompareClassification(styles_expected, suggestions.description_styles); +} + +// 0123456789 +// uuuuu +// + dd +// + mm +// + mmmm +// + dd +// = 3773unnnn66 +TEST(ExtensionOmniboxTest, DescriptionStylesCombine) { + ListValue styles_value; + AppendStyle("url", 0, 5, &styles_value); + AppendStyle("dim", 9, 2, &styles_value); + AppendStyle("match", 9, 2, &styles_value); + AppendStyle("match", 0, 4, &styles_value); + AppendStyle("dim", 1, 2, &styles_value); + + ACMatchClassifications styles_expected; + styles_expected.push_back(ACMatchClassification(0, kUrl | kMatch)); + styles_expected.push_back(ACMatchClassification(1, kUrl | kMatch | kDim)); + styles_expected.push_back(ACMatchClassification(3, kUrl | kMatch)); + styles_expected.push_back(ACMatchClassification(4, kUrl)); + styles_expected.push_back(ACMatchClassification(5, kNone)); + styles_expected.push_back(ACMatchClassification(9, kMatch | kDim)); + + ExtensionOmniboxSuggestion suggestions; + suggestions.description.resize(10); + EXPECT_TRUE(suggestions.ReadStylesFromValue(styles_value)); + CompareClassification(styles_expected, suggestions.description_styles); + + // Try moving the "dim/match" style pair at offset 9. Output should be the + // same. + styles_value.Clear(); + AppendStyle("url", 0, 5, &styles_value); + AppendStyle("match", 0, 4, &styles_value); + AppendStyle("dim", 9, 2, &styles_value); + AppendStyle("match", 9, 2, &styles_value); + AppendStyle("dim", 1, 2, &styles_value); + EXPECT_TRUE(suggestions.ReadStylesFromValue(styles_value)); + CompareClassification(styles_expected, suggestions.description_styles); +} + +// 0123456789 +// uuuuu +// + mmmmm +// + mmm +// + ddd +// + ddd +// = 77777nnnnn +TEST(ExtensionOmniboxTest, DescriptionStylesCombine2) { + ListValue styles_value; + AppendStyle("url", 0, 5, &styles_value); + AppendStyle("match", 0, 5, &styles_value); + AppendStyle("match", 0, 3, &styles_value); + AppendStyle("dim", 2, 3, &styles_value); + AppendStyle("dim", 0, 3, &styles_value); + + ACMatchClassifications styles_expected; + styles_expected.push_back(ACMatchClassification(0, kUrl | kMatch | kDim)); + styles_expected.push_back(ACMatchClassification(5, kNone)); + + ExtensionOmniboxSuggestion suggestions; + suggestions.description.resize(10); + EXPECT_TRUE(suggestions.ReadStylesFromValue(styles_value)); + CompareClassification(styles_expected, suggestions.description_styles); +} diff --git a/chrome/browser/extensions/extension_override_apitest.cc b/chrome/browser/extensions/extension_override_apitest.cc index 1efa5e7..3f0c801 100644 --- a/chrome/browser/extensions/extension_override_apitest.cc +++ b/chrome/browser/extensions/extension_override_apitest.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_dom_ui.h" @@ -10,6 +9,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc index 86426ee..84b20de 100644 --- a/chrome/browser/extensions/extension_page_actions_module.cc +++ b/chrome/browser/extensions/extension_page_actions_module.cc @@ -5,14 +5,14 @@ #include "chrome/browser/extensions/extension_page_actions_module.h" #include "base/string_number_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension_page_actions_module_constants.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/extensions/extension_error_utils.h" diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc index 72f3962..42ae83a 100644 --- a/chrome/browser/extensions/extension_popup_api.cc +++ b/chrome/browser/extensions/extension_popup_api.cc @@ -11,13 +11,13 @@ #include "chrome/browser/extensions/extension_dom_ui.h" #include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extension_host.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_details.h" diff --git a/chrome/browser/extensions/extension_pref_store_unittest.cc b/chrome/browser/extensions/extension_pref_store_unittest.cc index 90bed62..580dd3e 100644 --- a/chrome/browser/extensions/extension_pref_store_unittest.cc +++ b/chrome/browser/extensions/extension_pref_store_unittest.cc @@ -343,7 +343,7 @@ TEST(ExtensionPrefStoreTest, NotifyWhenNeeded) { // only an ExtensionPrefStore. Likewise, the PrefService takes ownership of // the PrefValueStore and PrefNotifier. PrefValueStore* value_store = new TestingPrefService::TestingPrefValueStore( - NULL, eps, NULL, NULL, NULL, dps); + NULL, NULL, eps, NULL, NULL, NULL, dps); scoped_ptr pref_service(new MockPrefService(value_store)); MockPrefNotifier* pref_notifier = new MockPrefNotifier(pref_service.get(), value_store); diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index bf80550..3c789b0 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -75,6 +75,9 @@ const char kPrefLaunchType[] = "launchType"; // A preference determining the order of which the apps appear on the NTP. const char kPrefAppLaunchIndex[] = "app_launcher_index"; +// "A preference for storing extra data sent in update checks for an extension. +const char kUpdateUrlData[] = "update_url_data"; + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -895,6 +898,28 @@ int ExtensionPrefs::GetNextAppLaunchIndex() { return max_value + 1; } +void ExtensionPrefs::SetUpdateUrlData(const std::string& extension_id, + const std::string& data) { + DictionaryValue* dictionary = GetExtensionPref(extension_id); + if (!dictionary) { + NOTREACHED(); + return; + } + + dictionary->SetString(kUpdateUrlData, data); + SavePrefsAndNotify(); +} + +std::string ExtensionPrefs::GetUpdateUrlData(const std::string& extension_id) { + DictionaryValue* dictionary = GetExtensionPref(extension_id); + if (!dictionary) + return std::string(); + + std::string data; + dictionary->GetString(kUpdateUrlData, &data); + return data; +} + // static void ExtensionPrefs::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(kExtensionsPref); diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index eb16329..298d03c 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -187,6 +187,13 @@ class ExtensionPrefs { // highest current application launch index found. int GetNextAppLaunchIndex(); + // The extension's update URL data. If not empty, the ExtensionUpdater + // will append a ap= parameter to the URL when checking if a new version + // of the extension is available. + void SetUpdateUrlData(const std::string& extension_id, + const std::string& data); + std::string GetUpdateUrlData(const std::string& extension_id); + static void RegisterUserPrefs(PrefService* prefs); // The underlying PrefService. diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index c4e0799..8fd5538 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -4,7 +4,6 @@ #include "chrome/browser/extensions/extension_process_manager.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/browsing_instance.h" #if defined(OS_MACOSX) @@ -16,6 +15,7 @@ #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/extensions/extension_processes_apitest.cc b/chrome/browser/extensions/extension_processes_apitest.cc index 82f3f70..88ca335 100644 --- a/chrome/browser/extensions/extension_processes_apitest.cc +++ b/chrome/browser/extensions/extension_processes_apitest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/command_line.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/task_manager/task_manager.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Processes) { diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc index 90d198c..edf937b 100644 --- a/chrome/browser/extensions/extension_protocols.cc +++ b/chrome/browser/extensions/extension_protocols.cc @@ -12,6 +12,7 @@ #include "base/message_loop.h" #include "base/path_service.h" #include "base/string_util.h" +#include "base/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" @@ -190,8 +191,14 @@ static URLRequestJob* CreateExtensionURLRequestJob(URLRequest* request, ExtensionResource resource(extension_id, directory_path, extension_file_util::ExtensionURLToRelativeFilePath(request->url())); - return new URLRequestFileJob(request, - resource.GetFilePathOnAnyThreadHack()); + FilePath resource_file_path; + { + // Getting the file path will touch the file system. Fixing + // crbug.com/59849 would also fix this. Suppress the error for now. + base::ThreadRestrictions::ScopedAllowIO allow_io; + resource_file_path = resource.GetFilePath(); + } + return new URLRequestFileJob(request, resource_file_path); } // Factory registered with URLRequest to create URLRequestJobs for diff --git a/chrome/browser/extensions/extension_proxy_apitest.cc b/chrome/browser/extensions/extension_proxy_apitest.cc index a22baf8..7f83407 100644 --- a/chrome/browser/extensions/extension_proxy_apitest.cc +++ b/chrome/browser/extensions/extension_proxy_apitest.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/extensions/extension_startup_browsertest.cc b/chrome/browser/extensions/extension_startup_browsertest.cc index d0eed8c..1b15ce0 100644 --- a/chrome/browser/extensions/extension_startup_browsertest.cc +++ b/chrome/browser/extensions/extension_startup_browsertest.cc @@ -8,11 +8,11 @@ #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_details.h" diff --git a/chrome/browser/extensions/extension_tabs_apitest.cc b/chrome/browser/extensions/extension_tabs_apitest.cc index b9aba66..6ec3e6c 100644 --- a/chrome/browser/extensions/extension_tabs_apitest.cc +++ b/chrome/browser/extensions/extension_tabs_apitest.cc @@ -4,9 +4,9 @@ #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/browser.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" // Possible race in ChromeURLDataManager. http://crbug.com/59198 diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc index 8157f52..8deafb2 100644 --- a/chrome/browser/extensions/extension_tabs_module.cc +++ b/chrome/browser/extensions/extension_tabs_module.cc @@ -9,9 +9,7 @@ #include "base/string_util.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_function_dispatcher.h" #include "chrome/browser/extensions/extension_host.h" @@ -26,6 +24,8 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_error_utils.h" diff --git a/chrome/browser/extensions/extension_test_api.cc b/chrome/browser/extensions/extension_test_api.cc index 9fe1749..eb50391 100644 --- a/chrome/browser/extensions/extension_test_api.cc +++ b/chrome/browser/extensions/extension_test_api.cc @@ -6,10 +6,10 @@ #include -#include "chrome/browser/browser.h" -#include "chrome/browser/profile.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extensions_quota_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" namespace { diff --git a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc index 45c936e..755ac01 100644 --- a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc +++ b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/extensions/extension_toolbar_model.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_toolbar_model.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc index f074c9b..8688806 100644 --- a/chrome/browser/extensions/extension_uitest.cc +++ b/chrome/browser/extensions/extension_uitest.cc @@ -8,9 +8,9 @@ #include "base/values.h" #include "chrome/browser/automation/extension_automation_constants.h" #include "chrome/browser/extensions/extension_tabs_module_constants.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" -#include "chrome/test/automation/automation_messages.h" #include "chrome/test/automation/automation_proxy_uitest.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/ui/ui_test.h" diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc index b2b3972..573da94 100644 --- a/chrome/browser/extensions/extension_updater.cc +++ b/chrome/browser/extensions/extension_updater.cc @@ -97,7 +97,8 @@ ManifestFetchData::~ManifestFetchData() {} // // (Note that '=' is %3D and '&' is %26 when urlencoded.) bool ManifestFetchData::AddExtension(std::string id, std::string version, - int days) { + int days, + const std::string& update_url_data) { if (extension_ids_.find(id) != extension_ids_.end()) { NOTREACHED() << "Duplicate extension id " << id; return false; @@ -109,6 +110,13 @@ bool ManifestFetchData::AddExtension(std::string id, std::string version, parts.push_back("v=" + version); parts.push_back("uc"); + if (!update_url_data.empty()) { + // Make sure the update_url_data string is escaped before using it so that + // there is no chance of overriding the id or v other parameter value + // we place into the x= value. + parts.push_back("ap=" + EscapeQueryParamValue(update_url_data, true)); + } + if (ShouldPing(days)) { parts.push_back("ping=" + EscapeQueryParamValue("r=" + base::IntToString(days), true)); @@ -177,12 +185,20 @@ void ManifestFetchesBuilder::AddExtension(const Extension& extension) { return; } + // If the extension updates itself from the gallery, ignore any update URL + // data. At the moment there is no extra data that an extension can + // communicate to the the gallery update servers. + std::string update_url_data; + if (!extension.UpdatesFromGallery()) + update_url_data = service_->extension_prefs()-> + GetUpdateUrlData(extension.id()); + AddExtensionData(extension.location(), extension.id(), *extension.version(), (extension.is_theme() ? PendingExtensionInfo::THEME : PendingExtensionInfo::EXTENSION), - extension.update_url()); + extension.update_url(), update_url_data); } void ManifestFetchesBuilder::AddPendingExtension( @@ -195,7 +211,7 @@ void ManifestFetchesBuilder::AddPendingExtension( Version::GetVersionFromString("0.0.0.0")); AddExtensionData(info.install_source, id, *version, - info.expected_crx_type, info.update_url); + info.expected_crx_type, info.update_url, ""); } void ManifestFetchesBuilder::ReportStats() const { @@ -230,7 +246,8 @@ void ManifestFetchesBuilder::AddExtensionData( const std::string& id, const Version& version, PendingExtensionInfo::ExpectedCrxType crx_type, - GURL update_url) { + GURL update_url, + const std::string& update_url_data) { if (!Extension::IsAutoUpdateableLocation(location)) { return; @@ -277,7 +294,7 @@ void ManifestFetchesBuilder::AddExtensionData( CalculatePingDays(service_->extension_prefs()->LastPingDay(id)); while (existing_iter != fetches_.end()) { if (existing_iter->second->AddExtension(id, version.GetString(), - ping_days)) { + ping_days, update_url_data)) { fetch = existing_iter->second; break; } @@ -286,7 +303,8 @@ void ManifestFetchesBuilder::AddExtensionData( if (!fetch) { fetch = new ManifestFetchData(update_url); fetches_.insert(std::pair(update_url, fetch)); - bool added = fetch->AddExtension(id, version.GetString(), ping_days); + bool added = fetch->AddExtension(id, version.GetString(), ping_days, + update_url_data); DCHECK(added); } } @@ -333,7 +351,7 @@ class ExtensionUpdaterFileHandler ExtensionUpdater::ExtensionUpdater(ExtensionUpdateService* service, PrefService* prefs, int frequency_seconds) - : service_(service), frequency_seconds_(frequency_seconds), + : alive_(false), service_(service), frequency_seconds_(frequency_seconds), prefs_(prefs), file_handler_(new ExtensionUpdaterFileHandler()), blacklist_checks_enabled_(true) { Init(); @@ -350,7 +368,7 @@ void ExtensionUpdater::Init() { } ExtensionUpdater::~ExtensionUpdater() { - STLDeleteElements(&manifests_pending_); + Stop(); } static void EnsureInt64PrefRegistered(PrefService* prefs, @@ -367,6 +385,7 @@ static void EnsureBlacklistVersionPrefRegistered(PrefService* prefs) { // The overall goal here is to balance keeping clients up to date while // avoiding a thundering herd against update servers. TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() { + DCHECK(alive_); // If someone's testing with a quick frequency, just allow it. if (frequency_seconds_ < kStartupWaitSeconds) return TimeDelta::FromSeconds(frequency_seconds_); @@ -409,6 +428,12 @@ TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() { } void ExtensionUpdater::Start() { + DCHECK(!alive_); + // If these are NULL, then that means we've been called after Stop() + // has been called. + DCHECK(service_); + DCHECK(prefs_); + alive_ = true; // Make sure our prefs are registered, then schedule the first check. EnsureInt64PrefRegistered(prefs_, kLastExtensionsUpdateCheck); EnsureInt64PrefRegistered(prefs_, kNextExtensionsUpdateCheck); @@ -417,9 +442,13 @@ void ExtensionUpdater::Start() { } void ExtensionUpdater::Stop() { + alive_ = false; + service_ = NULL; + prefs_ = NULL; timer_.Stop(); manifest_fetcher_.reset(); extension_fetcher_.reset(); + STLDeleteElements(&manifests_pending_); manifests_pending_.clear(); extensions_pending_.clear(); } @@ -428,6 +457,10 @@ void ExtensionUpdater::OnURLFetchComplete( const URLFetcher* source, const GURL& url, const URLRequestStatus& status, int response_code, const ResponseCookies& cookies, const std::string& data) { + // Stop() destroys all our URLFetchers, which means we shouldn't be + // called after Stop() is called. + DCHECK(alive_); + if (source == manifest_fetcher_.get()) { OnManifestFetchComplete(url, status, response_code, data); } else if (source == extension_fetcher_.get()) { @@ -540,6 +573,9 @@ void ExtensionUpdater::OnManifestFetchComplete(const GURL& url, void ExtensionUpdater::HandleManifestResults( const ManifestFetchData& fetch_data, const UpdateManifest::Results& results) { + // This can be called after we've been stopped. + if (!alive_) + return; // Examine the parsed manifest and kick off fetches of any new crx files. std::vector updates = DetermineUpdates(fetch_data, results); @@ -572,6 +608,7 @@ void ExtensionUpdater::HandleManifestResults( } void ExtensionUpdater::ProcessBlacklist(const std::string& data) { + DCHECK(alive_); // Verify sha256 hash value. char sha256_hash_value[base::SHA256_LENGTH]; base::SHA256HashString(data, sha256_hash_value, base::SHA256_LENGTH); @@ -635,6 +672,9 @@ void ExtensionUpdater::OnCRXFetchComplete(const GURL& url, void ExtensionUpdater::OnCRXFileWritten(const std::string& id, const FilePath& path, const GURL& download_url) { + // This can be called after we've been stopped. + if (!alive_) + return; // The ExtensionsService is now responsible for cleaning up the temp file // at |path|. service_->UpdateExtension(id, path, download_url); @@ -642,6 +682,7 @@ void ExtensionUpdater::OnCRXFileWritten(const std::string& id, void ExtensionUpdater::ScheduleNextCheck(const TimeDelta& target_delay) { + DCHECK(alive_); DCHECK(!timer_.IsRunning()); DCHECK(target_delay >= TimeDelta::FromSeconds(1)); @@ -661,6 +702,7 @@ void ExtensionUpdater::ScheduleNextCheck(const TimeDelta& target_delay) { } void ExtensionUpdater::TimerFired() { + DCHECK(alive_); CheckNow(); // If the user has overridden the update frequency, don't bother reporting @@ -685,6 +727,7 @@ void ExtensionUpdater::TimerFired() { } void ExtensionUpdater::CheckNow() { + DCHECK(alive_); ManifestFetchesBuilder fetches_builder(service_); const ExtensionList* extensions = service_->extensions(); @@ -711,7 +754,7 @@ void ExtensionUpdater::CheckNow() { std::string version = prefs_->GetString(kExtensionBlacklistUpdateVersion); int ping_days = CalculatePingDays(service_->extension_prefs()->BlacklistLastPingDay()); - blacklist_fetch->AddExtension(kBlacklistAppID, version, ping_days); + blacklist_fetch->AddExtension(kBlacklistAppID, version, ping_days, ""); StartUpdateCheck(blacklist_fetch); } @@ -730,6 +773,7 @@ void ExtensionUpdater::CheckNow() { bool ExtensionUpdater::GetExistingVersion(const std::string& id, std::string* version) { + DCHECK(alive_); if (id == kBlacklistAppID) { *version = prefs_->GetString(kExtensionBlacklistUpdateVersion); return true; @@ -745,6 +789,7 @@ bool ExtensionUpdater::GetExistingVersion(const std::string& id, std::vector ExtensionUpdater::DetermineUpdates( const ManifestFetchData& fetch_data, const UpdateManifest::Results& possible_updates) { + DCHECK(alive_); std::vector result; // This will only get set if one of possible_updates specifies @@ -806,6 +851,7 @@ std::vector ExtensionUpdater::DetermineUpdates( } void ExtensionUpdater::StartUpdateCheck(ManifestFetchData* fetch_data) { + scoped_ptr scoped_fetch_data(fetch_data); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableBackgroundNetworking)) return; @@ -814,20 +860,19 @@ void ExtensionUpdater::StartUpdateCheck(ManifestFetchData* fetch_data) { for (i = manifests_pending_.begin(); i != manifests_pending_.end(); i++) { if (fetch_data->full_url() == (*i)->full_url()) { // This url is already scheduled to be fetched. - delete fetch_data; return; } } if (manifest_fetcher_.get() != NULL) { if (manifest_fetcher_->url() != fetch_data->full_url()) { - manifests_pending_.push_back(fetch_data); + manifests_pending_.push_back(scoped_fetch_data.release()); } } else { UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength", fetch_data->full_url().possibly_invalid_spec().length()); - current_manifest_fetch_.reset(fetch_data); + current_manifest_fetch_.swap(scoped_fetch_data); manifest_fetcher_.reset( URLFetcher::Create(kManifestFetcherId, fetch_data->full_url(), URLFetcher::GET, this)); diff --git a/chrome/browser/extensions/extension_updater.h b/chrome/browser/extensions/extension_updater.h index 79fa166..1e99649 100644 --- a/chrome/browser/extensions/extension_updater.h +++ b/chrome/browser/extensions/extension_updater.h @@ -12,6 +12,7 @@ #include #include +#include "base/gtest_prod_util.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/scoped_temp_dir.h" @@ -42,7 +43,8 @@ class ManifestFetchData { // Returns true if this extension information was successfully added. If the // return value is false it means the full_url would have become too long, and // this ManifestFetchData object remains unchanged. - bool AddExtension(std::string id, std::string version, int ping_days); + bool AddExtension(std::string id, std::string version, int ping_days, + const std::string& update_url_data); const GURL& base_url() const { return base_url_; } const GURL& full_url() const { return full_url_; } @@ -111,7 +113,8 @@ class ManifestFetchesBuilder { const std::string& id, const Version& version, PendingExtensionInfo::ExpectedCrxType crx_type, - GURL update_url); + GURL update_url, + const std::string& update_url_data); ExtensionUpdateService* service_; // List of data on fetches we're going to do. We limit the number of @@ -144,7 +147,7 @@ class ExtensionUpdater PrefService* prefs, int frequency_seconds); - // Starts the updater running. + // Starts the updater running. Should be called at most once. void Start(); // Stops the updater running, cancelling any outstanding update manifest and @@ -251,6 +254,9 @@ class ExtensionUpdater std::vector DetermineUpdates(const ManifestFetchData& fetch_data, const UpdateManifest::Results& possible_updates); + // Whether Start() has been called but not Stop(). + bool alive_; + // Outstanding url fetch requests for manifests and updates. scoped_ptr manifest_fetcher_; scoped_ptr extension_fetcher_; @@ -277,6 +283,9 @@ class ExtensionUpdater scoped_refptr file_handler_; bool blacklist_checks_enabled_; + FRIEND_TEST(ExtensionUpdaterTest, TestStartUpdateCheckMemory); + FRIEND_TEST(ExtensionUpdaterTest, TestAfterStopBehavior); + DISALLOW_COPY_AND_ASSIGN(ExtensionUpdater); }; diff --git a/chrome/browser/extensions/extension_updater_unittest.cc b/chrome/browser/extensions/extension_updater_unittest.cc index f099b86..bc1a6ff 100644 --- a/chrome/browser/extensions/extension_updater_unittest.cc +++ b/chrome/browser/extensions/extension_updater_unittest.cc @@ -32,11 +32,17 @@ using base::Time; using base::TimeDelta; -static int expected_load_flags = +namespace { + +const char kEmptyUpdateUrlData[] = ""; + +int expected_load_flags = net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE; +} // namespace + // Base class for further specialized test classes. class MockService : public ExtensionUpdateService { public: @@ -402,6 +408,70 @@ class ExtensionUpdaterTest : public testing::Test { EXPECT_TRUE(ContainsKey(params, "ping")); } + static void TestUpdateUrlDataEmpty() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an empty update URL data string does not cause a ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, ""); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataSimple() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an update URL data string causes an appropriate ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, "bar"); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc%26ap%3Dbar", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataCompound() { + const std::string id = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const std::string version = "1.0"; + + // Make sure that an update URL data string causes an appropriate ap= + // option to appear in the x= parameter. + ManifestFetchData fetch_data(GURL("http://localhost/foo")); + fetch_data.AddExtension(id, version, + ManifestFetchData::kNeverPinged, "a=1&b=2&c"); + EXPECT_EQ("http://localhost/foo\?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "%26v%3D1.0%26uc%26ap%3Da%253D1%2526b%253D2%2526c", + fetch_data.full_url().spec()); + } + + static void TestUpdateUrlDataFromGallery(const char* gallery_url) { + MockService service; + ManifestFetchesBuilder builder(&service); + ExtensionList extensions; + std::string url(gallery_url); + + service.CreateTestExtensions(1, &extensions, &url, Extension::INTERNAL); + builder.AddExtension(*extensions[0]); + std::vector fetches = builder.GetFetches(); + EXPECT_EQ(1u, fetches.size()); + scoped_ptr fetch(fetches[0]); + fetches.clear(); + + // Make sure that extensions that update from the gallery ignore any + // update URL data. + const std::string& update_url = fetch->full_url().spec(); + std::string::size_type x = update_url.find("x="); + EXPECT_NE(std::string::npos, x); + std::string::size_type ap = update_url.find("ap%3D", x); + EXPECT_EQ(std::string::npos, ap); + } + static void TestDetermineUpdates() { // Create a set of test extensions ServiceForManifestTests service; @@ -413,6 +483,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); // Check passing an empty list of parse results to DetermineUpdates ManifestFetchData fetch_data(GURL("http://localhost/foo")); @@ -427,11 +498,13 @@ class ExtensionUpdaterTest : public testing::Test { scoped_ptr one(Version::GetVersionFromString("1.0")); EXPECT_TRUE(tmp[0]->version()->Equals(*one)); fetch_data.AddExtension(tmp[0]->id(), tmp[0]->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(tmp[0]->id(), "1.1", "http://localhost/e1_1.1.crx", &updates); fetch_data.AddExtension(tmp[1]->id(), tmp[1]->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(tmp[1]->id(), tmp[1]->VersionString(), "http://localhost/e2_2.0.crx", &updates); updateable = updater->DetermineUpdates(fetch_data, updates); @@ -450,13 +523,15 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); ManifestFetchData fetch_data(GURL("http://localhost/foo")); UpdateManifest::Results updates; for (PendingExtensionMap::const_iterator it = pending_extensions.begin(); it != pending_extensions.end(); ++it) { fetch_data.AddExtension(it->first, "1.0.0.0", - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); AddParseResult(it->first, "1.1", "http://localhost/e1_1.1.crx", &updates); } @@ -484,6 +559,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); GURL url1("http://localhost/manifest1"); GURL url2("http://localhost/manifest2"); @@ -492,8 +568,9 @@ class ExtensionUpdaterTest : public testing::Test { // second one should be queued up. ManifestFetchData* fetch1 = new ManifestFetchData(url1); ManifestFetchData* fetch2 = new ManifestFetchData(url2); - fetch1->AddExtension("1111", "1.0", 0); - fetch2->AddExtension("12345", "2.0", ManifestFetchData::kNeverPinged); + fetch1->AddExtension("1111", "1.0", 0, kEmptyUpdateUrlData); + fetch2->AddExtension("12345", "2.0", ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); updater->StartUpdateCheck(fetch1); updater->StartUpdateCheck(fetch2); @@ -548,6 +625,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); GURL test_url("http://localhost/extension.crx"); @@ -611,8 +689,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); - service.pref_service()-> - RegisterStringPref(prefs::kExtensionBlacklistUpdateVersion, "0"); + updater->Start(); GURL test_url("http://localhost/extension.crx"); std::string id = "com.google.crx.blacklist"; @@ -658,6 +735,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); GURL url1("http://localhost/extension1.crx"); GURL url2("http://localhost/extension2.crx"); @@ -745,6 +823,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); updater->set_blacklist_checks_enabled(false); // Make the updater do manifest fetching, and note the urls it tries to @@ -794,9 +873,11 @@ class ExtensionUpdaterTest : public testing::Test { // >= 1 day for the extension. static void TestHandleManifestResults() { ServiceForManifestTests service; + MessageLoop message_loop; scoped_refptr updater( new ExtensionUpdater(&service, service.pref_service(), kUpdateFrequencySecs)); + updater->Start(); GURL update_url("http://www.google.com/manifest"); ExtensionList tmp; @@ -807,7 +888,8 @@ class ExtensionUpdaterTest : public testing::Test { ManifestFetchData fetch_data(update_url); const Extension* extension = tmp[0]; fetch_data.AddExtension(extension->id(), extension->VersionString(), - ManifestFetchData::kNeverPinged); + ManifestFetchData::kNeverPinged, + kEmptyUpdateUrlData); UpdateManifest::Results results; results.daystart_elapsed_seconds = 750; @@ -837,6 +919,16 @@ TEST(ExtensionUpdaterTest, TestBlacklistUpdateCheckRequests) { ExtensionUpdaterTest::TestBlacklistUpdateCheckRequests(); } +TEST(ExtensionUpdaterTest, TestUpdateUrlData) { + ExtensionUpdaterTest::TestUpdateUrlDataEmpty(); + ExtensionUpdaterTest::TestUpdateUrlDataSimple(); + ExtensionUpdaterTest::TestUpdateUrlDataCompound(); + ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( + extension_urls::kGalleryUpdateHttpUrl); + ExtensionUpdaterTest::TestUpdateUrlDataFromGallery( + extension_urls::kGalleryUpdateHttpsUrl); +} + TEST(ExtensionUpdaterTest, TestDetermineUpdates) { ExtensionUpdaterTest::TestDetermineUpdates(); } @@ -923,6 +1015,41 @@ TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) { EXPECT_FALSE(fetch->full_url().is_empty()); } +TEST(ExtensionUpdaterTest, TestStartUpdateCheckMemory) { + MessageLoop message_loop; + ServiceForManifestTests service; + TestURLFetcherFactory factory; + URLFetcher::set_factory(&factory); + scoped_refptr updater( + new ExtensionUpdater(&service, service.pref_service(), + kUpdateFrequencySecs)); + updater->Start(); + updater->StartUpdateCheck(new ManifestFetchData(GURL())); + // This should delete the newly-created ManifestFetchData. + updater->StartUpdateCheck(new ManifestFetchData(GURL())); + // This should add into |manifests_pending_|. + updater->StartUpdateCheck(new ManifestFetchData( + GURL("http://www.google.com"))); + // This should clear out |manifests_pending_|. + updater->Stop(); +} + +TEST(ExtensionUpdaterTest, TestAfterStopBehavior) { + MessageLoop message_loop; + ServiceForManifestTests service; + scoped_refptr updater( + new ExtensionUpdater(&service, service.pref_service(), + kUpdateFrequencySecs)); + updater->Start(); + updater->Stop(); + // All the below functions should do nothing. + updater->OnCRXFileWritten("", FilePath(), GURL()); + GURL dummy_gurl; + ManifestFetchData dummy_manifest_fetch_data(dummy_gurl); + updater->HandleManifestResults(dummy_manifest_fetch_data, + UpdateManifest::Results()); +} + // TODO(asargent) - (http://crbug.com/12780) add tests for: // -prodversionmin (shouldn't update if browser version too old) // -manifests & updates arriving out of order / interleaved diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc index 092d395..e1c3dff 100644 --- a/chrome/browser/extensions/extension_webstore_private_api.cc +++ b/chrome/browser/extensions/extension_webstore_private_api.cc @@ -18,7 +18,9 @@ #include "chrome/browser/profile_manager.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension_error_utils.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" @@ -31,9 +33,15 @@ namespace { const char* install_base_url = extension_urls::kGalleryUpdateHttpsUrl; const char kLoginKey[] = "login"; const char kTokenKey[] = "token"; +const char kInvalidIdError[] = "Invalid id"; +const char kNoPreviousBeginInstallError[] = + "* does not match a previous call to beginInstall"; +const char kUserGestureRequiredError[] = + "This function must be called during a user gesture"; ProfileSyncService* test_sync_service = NULL; BrowserSignin* test_signin = NULL; +bool ignore_user_gesture_for_tests = false; // Returns either the test sync service, or the real one from |profile|. ProfileSyncService* GetSyncService(Profile* profile) { @@ -53,7 +61,10 @@ BrowserSignin* GetBrowserSignin(Profile* profile) { bool IsWebStoreURL(Profile* profile, const GURL& url) { ExtensionsService* service = profile->GetExtensionsService(); const Extension* store = service->GetWebStoreApp(); - DCHECK(store); + if (!store) { + NOTREACHED(); + return false; + } return (service->GetExtensionByWebExtent(url) == store); } @@ -64,8 +75,10 @@ DictionaryValue* CreateLoginResult(Profile* profile) { std::string username = GetBrowserSignin(profile)->GetSignedInUsername(); dictionary->SetString(kLoginKey, username); if (!username.empty()) { + CommandLine* cmdline = CommandLine::ForCurrentProcess(); TokenService* token_service = profile->GetTokenService(); - if (token_service->HasTokenForService(GaiaConstants::kGaiaService)) { + if (cmdline->HasSwitch(switches::kAppsGalleryReturnTokens) && + token_service->HasTokenForService(GaiaConstants::kGaiaService)) { dictionary->SetString(kTokenKey, token_service->GetTokenForService( GaiaConstants::kGaiaService)); @@ -97,18 +110,55 @@ void WebstorePrivateApi::SetTestingBrowserSignin(BrowserSignin* signin) { } // static -void InstallFunction::SetTestingInstallBaseUrl( +void BeginInstallFunction::SetIgnoreUserGestureForTests(bool ignore) { + ignore_user_gesture_for_tests = ignore; +} + +bool BeginInstallFunction::RunImpl() { + if (!IsWebStoreURL(profile_, source_url())) + return false; + + std::string id; + EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id)); + if (!Extension::IdIsValid(id)) { + error_ = kInvalidIdError; + return false; + } + + if (!user_gesture() && !ignore_user_gesture_for_tests) { + error_ = kUserGestureRequiredError; + return false; + } + + // This gets cleared in CrxInstaller::ConfirmInstall(). TODO(asargent) - in + // the future we may also want to add time-based expiration, where a whitelist + // entry is only valid for some number of minutes. + CrxInstaller::SetWhitelistedInstallId(id); + return true; +} + +// static +void CompleteInstallFunction::SetTestingInstallBaseUrl( const char* testing_install_base_url) { install_base_url = testing_install_base_url; } -bool InstallFunction::RunImpl() { +bool CompleteInstallFunction::RunImpl() { if (!IsWebStoreURL(profile_, source_url())) return false; std::string id; EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id)); - EXTENSION_FUNCTION_VALIDATE(Extension::IdIsValid(id)); + if (!Extension::IdIsValid(id)) { + error_ = kInvalidIdError; + return false; + } + + if (!CrxInstaller::IsIdWhitelisted(id)) { + error_ = ExtensionErrorUtils::FormatErrorMessage( + kNoPreviousBeginInstallError, id); + return false; + } std::vector params; params.push_back("id=" + id); @@ -120,9 +170,6 @@ bool InstallFunction::RunImpl() { EscapeQueryParamValue(JoinString(params, '&'), true)); DCHECK(url.is_valid()); - // Cleared in ~CrxInstaller(). - CrxInstaller::SetWhitelistedInstallId(id); - // The download url for the given |id| is now contained in |url|. We // navigate the current (calling) tab to this url which will result in a // download starting. Once completed it will go through the normal extension diff --git a/chrome/browser/extensions/extension_webstore_private_api.h b/chrome/browser/extensions/extension_webstore_private_api.h index 39d883c..5796ab0 100644 --- a/chrome/browser/extensions/extension_webstore_private_api.h +++ b/chrome/browser/extensions/extension_webstore_private_api.h @@ -25,14 +25,23 @@ class WebstorePrivateApi { static void SetTestingBrowserSignin(BrowserSignin* signin); }; -class InstallFunction : public SyncExtensionFunction { +class BeginInstallFunction : public SyncExtensionFunction { public: - static void SetTestingInstallBaseUrl(const char* testing_install_base_url); + // For use only in tests - sets a flag that can cause this function to ignore + // the normal requirement that it is called during a user gesture. + static void SetIgnoreUserGestureForTests(bool ignore); + protected: + virtual bool RunImpl(); + DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.beginInstall"); +}; +class CompleteInstallFunction : public SyncExtensionFunction { + public: + // This changes the base of the download url to the crx file to be installed. + static void SetTestingInstallBaseUrl(const char* testing_install_base_url); protected: - ~InstallFunction() {} virtual bool RunImpl(); - DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.install"); + DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.completeInstall"); }; class GetBrowserLoginFunction : public SyncExtensionFunction { diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 4227333..e8f39aa 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -15,13 +15,16 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/stringprintf.h" +#include "base/thread_restrictions.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "base/version.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/themes/browser_theme_provider.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/debugger/devtools_manager.h" +#include "chrome/browser/dom_ui/shown_sections_handler.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/default_apps.h" #include "chrome/browser/extensions/extension_accessibility_api.h" @@ -54,6 +57,7 @@ #include "chrome/common/extensions/extension_error_utils.h" #include "chrome/common/extensions/extension_file_util.h" #include "chrome/common/extensions/extension_l10n_util.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" #include "chrome/common/json_value_serializer.h" @@ -85,14 +89,27 @@ static const int kOmniboxIconPaddingLeft = 0; static const int kOmniboxIconPaddingRight = 0; #endif -bool ShouldReloadExtensionManifest(const ExtensionInfo& info) { - // Always reload LOAD extension manifests, because they can change on disk - // independent of the manifest in our prefs. +// The following enumeration is used in histograms matching +// Extensions.ManifestReload* . Values may be added, as long +// as existing values are not changed. +enum ManifestReloadReason { + NOT_NEEDED = 0, // Reload not needed. + UNPACKED_DIR, // Unpacked directory + NEEDS_RELOCALIZATION, // The local has changed since we read this extension. + NUM_MANIFEST_RELOAD_REASONS +}; + +ManifestReloadReason ShouldReloadExtensionManifest(const ExtensionInfo& info) { + // Always reload manifests of unpacked extensions, because they can change + // on disk independent of the manifest in our prefs. if (info.extension_location == Extension::LOAD) - return true; + return UNPACKED_DIR; - // Otherwise, reload the manifest it needs to be relocalized. - return extension_l10n_util::ShouldRelocalizeManifest(info); + // Reload the manifest if it needs to be relocalized. + if (extension_l10n_util::ShouldRelocalizeManifest(info)) + return NEEDS_RELOCALIZATION; + + return NOT_NEEDED; } void GetExplicitOriginsInExtent(const Extension* extension, @@ -215,13 +232,6 @@ class ExtensionsServiceBackend const GURL& update_url, Extension::Location location); - // Reloads the given extensions from their manifests on disk (instead of what - // we have cached in the prefs). - void ReloadExtensionManifests( - ExtensionPrefs::ExtensionsInfo* extensions_to_reload, - base::TimeTicks start_time, - scoped_refptr frontend); - private: friend class base::RefCountedThreadSafe; @@ -444,41 +454,6 @@ void ExtensionsServiceBackend::OnExternalExtensionUpdateUrlFound( external_extension_added_ |= true; } -void ExtensionsServiceBackend::ReloadExtensionManifests( - ExtensionPrefs::ExtensionsInfo* extensions_to_reload, - base::TimeTicks start_time, - scoped_refptr frontend) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - - frontend_ = frontend; - - for (size_t i = 0; i < extensions_to_reload->size(); ++i) { - ExtensionInfo* info = extensions_to_reload->at(i).get(); - if (!ShouldReloadExtensionManifest(*info)) - continue; - - // We need to reload original manifest in order to localize properly. - std::string error; - scoped_refptr extension(extension_file_util::LoadExtension( - info->extension_path, info->extension_location, false, &error)); - - if (extension.get()) - extensions_to_reload->at(i)->extension_manifest.reset( - static_cast( - extension->manifest_value()->DeepCopy())); - } - - // Finish installing on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - NewRunnableMethod( - frontend_, - &ExtensionsService::ContinueLoadAllExtensions, - extensions_to_reload, - start_time, - true)); -} - bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, const GURL& referrer_url) { // Special-case the themes mini-gallery. @@ -782,7 +757,7 @@ void ExtensionsService::AddPendingExtensionInternal( // type to be external. An external extension should not be // rejected if it fails the safty checks for a syncable extension. // TODO(skerner): Work out other potential overlapping conditions. - // (crbug/61000) + // (crbug.com/61000) PendingExtensionMap::iterator it = pending_extensions_.find(id); if (it != pending_extensions_.end()) { VLOG(1) << "Extension id " << id @@ -988,47 +963,66 @@ void ExtensionsService::LoadComponentExtensions() { } void ExtensionsService::LoadAllExtensions() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::TimeTicks start_time = base::TimeTicks::Now(); // Load any component extensions. LoadComponentExtensions(); // Load the previously installed extensions. - scoped_ptr info( + scoped_ptr extensions_info( extension_prefs_->GetInstalledExtensionsInfo()); - // If any extensions need localization, we bounce them all to the file thread - // for re-reading and localization. - for (size_t i = 0; i < info->size(); ++i) { - if (ShouldReloadExtensionManifest(*info->at(i))) { - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, NewRunnableMethod( - backend_.get(), - &ExtensionsServiceBackend::ReloadExtensionManifests, - info.release(), // Callee takes ownership of the memory. - start_time, - scoped_refptr(this))); - return; + std::vector reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS, 0); + bool should_write_prefs = false; + + for (size_t i = 0; i < extensions_info->size(); ++i) { + ExtensionInfo* info = extensions_info->at(i).get(); + + ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info); + ++reload_reason_counts[reload_reason]; + UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestReloadEnumValue", + reload_reason, 100); + + if (reload_reason != NOT_NEEDED) { + // Reloading and extension reads files from disk. We do this on the + // UI thread because reloads should be very rare, and the complexity + // added by delaying the time when the extensions service knows about + // all extensions is significant. See crbug.com/37548 for details. + // |allow_io| disables tests that file operations run on the file + // thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + + std::string error; + scoped_refptr extension( + extension_file_util::LoadExtension( + info->extension_path, info->extension_location, false, &error)); + + if (extension.get()) { + extensions_info->at(i)->extension_manifest.reset( + static_cast( + extension->manifest_value()->DeepCopy())); + should_write_prefs = true; + } } } - // Don't update prefs. - // Callee takes ownership of the memory. - ContinueLoadAllExtensions(info.release(), start_time, false); -} - -void ExtensionsService::ContinueLoadAllExtensions( - ExtensionPrefs::ExtensionsInfo* extensions_info, - base::TimeTicks start_time, - bool write_to_prefs) { - scoped_ptr info(extensions_info); - - for (size_t i = 0; i < info->size(); ++i) { - LoadInstalledExtension(*info->at(i), write_to_prefs); + for (size_t i = 0; i < extensions_info->size(); ++i) { + LoadInstalledExtension(*extensions_info->at(i), should_write_prefs); } OnLoadedInstalledExtensions(); + // The histograms Extensions.ManifestReload* allow us to validate + // the assumption that reloading manifest is a rare event. + UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNotNeeded", + reload_reason_counts[NOT_NEEDED]); + UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadUnpackedDir", + reload_reason_counts[UNPACKED_DIR]); + UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNeedsRelocalization", + reload_reason_counts[NEEDS_RELOCALIZATION]); + UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAll", extensions_.size()); UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled", disabled_extensions_.size()); @@ -1072,30 +1066,30 @@ void ExtensionsService::ContinueLoadAllExtensions( UMA_HISTOGRAM_ENUMERATION("Extensions.LoadType", type, 100); switch (type) { case Extension::TYPE_THEME: - theme_count++; + ++theme_count; break; case Extension::TYPE_USER_SCRIPT: - user_script_count++; + ++user_script_count; break; case Extension::TYPE_HOSTED_APP: - app_count++; - hosted_app_count++; + ++app_count; + ++hosted_app_count; break; case Extension::TYPE_PACKAGED_APP: - app_count++; - packaged_app_count++; + ++app_count; + ++packaged_app_count; break; case Extension::TYPE_EXTENSION: default: - extension_count++; + ++extension_count; break; } if (Extension::IsExternalLocation(location)) - external_count++; + ++external_count; if ((*ex)->page_action() != NULL) - page_action_count++; + ++page_action_count; if ((*ex)->browser_action() != NULL) - browser_action_count++; + ++browser_action_count; } UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp", app_count); UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count); @@ -1109,6 +1103,7 @@ void ExtensionsService::ContinueLoadAllExtensions( browser_action_count); } + void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, bool write_to_prefs) { std::string error; @@ -1243,8 +1238,8 @@ void ExtensionsService::GrantUnlimitedStorage(const Extension* extension) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( - profile_->GetFileSystemHostContext(), - &FileSystemHostContext::SetOriginQuotaUnlimited, + profile_->GetFileSystemContext(), + &BrowserFileSystemContext::SetOriginQuotaUnlimited, origin)); } } @@ -1278,8 +1273,8 @@ void ExtensionsService::RevokeUnlimitedStorage(const Extension* extension) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( - profile_->GetFileSystemHostContext(), - &FileSystemHostContext::ResetOriginQuotaUnlimited, + profile_->GetFileSystemContext(), + &BrowserFileSystemContext::ResetOriginQuotaUnlimited, origin)); } } @@ -1398,8 +1393,10 @@ void ExtensionsService::UnloadExtension(const std::string& extension_id) { scoped_refptr extension( GetExtensionByIdInternal(extension_id, true, true)); - // Callers should not send us nonexistent extensions. - CHECK(extension.get()); + // This method can be called via PostTask, so the extension may have been + // unloaded by the time this runs. + if (!extension) + return; // Keep information about the extension so that we can reload it later // even if it's not permanently installed. @@ -1466,6 +1463,13 @@ void ExtensionsService::GarbageCollectExtensions() { NewRunnableFunction( &extension_file_util::GarbageCollectExtensions, install_directory_, extension_paths)); + + // Also garbage-collect themes. We check |profile_| to be + // defensive; in the future, we may call GarbageCollectExtensions() + // from somewhere other than Init() (e.g., in a timer). + if (profile_) { + profile_->GetThemeProvider()->RemoveUnusedThemes(); + } } void ExtensionsService::OnLoadedInstalledExtensions() { @@ -1689,6 +1693,7 @@ void ExtensionsService::OnExtensionInstalled(const Extension* extension, UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", extension->GetHistogramType(), 100); + ShownSectionsHandler::OnExtensionInstalled(profile_->GetPrefs(), extension); extension_prefs_->OnExtensionInstalled( extension, initial_state, initial_enable_incognito); @@ -1881,19 +1886,6 @@ void ExtensionsService::Observe(NotificationType type, ExtensionHost* host = Details(details).ptr(); - // TODO(rafaelw): Remove this check and ExtensionHost::recently_deleted(). - // This is only here to help track down crbug.com/49114. - ExtensionHost::HostPointerList::iterator iter = - ExtensionHost::recently_deleted()->begin(); - for (; iter != ExtensionHost::recently_deleted()->end(); iter++) { - if (*iter == host) { - CHECK(host->GetURL().spec().size() + 2 != 0); - break; - } - } - if (iter == ExtensionHost::recently_deleted()->end()) - CHECK(host->GetURL().spec().size() + 1 != 0); - // Unload the entire extension. We want it to be in a consistent state: // either fully working or not loaded at all, but never half-crashed. // We do it in a PostTask so that other handlers of this notification will diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index fa8f341..d5057b7 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -23,7 +23,7 @@ #include "base/version.h" #include "chrome/browser/appcache/chrome_appcache_service.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/file_system/file_system_host_context.h" +#include "chrome/browser/file_system/browser_file_system_context.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_error_reporter.h" @@ -297,17 +297,17 @@ class ExtensionTestingProfile : public TestingProfile { return appcache_service_; } - virtual FileSystemHostContext* GetFileSystemHostContext() { - if (!file_system_host_context_) - file_system_host_context_ = new FileSystemHostContext( + virtual BrowserFileSystemContext* GetFileSystemContext() { + if (!browser_file_system_context_) + browser_file_system_context_ = new BrowserFileSystemContext( GetPath(), IsOffTheRecord()); - return file_system_host_context_; + return browser_file_system_context_; } private: ExtensionsService* service_; scoped_refptr appcache_service_; - scoped_refptr file_system_host_context_; + scoped_refptr browser_file_system_context_; }; // Our message loop may be used in tests which require it to be an IO loop. @@ -747,7 +747,6 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { InitializeInstalledExtensionsService(pref_path, source_install_dir); service_->Init(); - loop_.RunAllPending(); // On Chrome OS, we disallow extensions with plugins. "good1" has plugins, // so we need to edit it out here. diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index d3f6a6c..cf78bec 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -14,7 +14,6 @@ #include "base/utf_string_conversions.h" #include "base/thread.h" #include "base/version.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/debugger/devtools_manager.h" @@ -36,6 +35,7 @@ #include "chrome/browser/tab_contents/background_contents.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_icon_set.h" diff --git a/chrome/browser/extensions/notifications_apitest.cc b/chrome/browser/extensions/notifications_apitest.cc index eb51c67..6a80635 100644 --- a/chrome/browser/extensions/notifications_apitest.cc +++ b/chrome/browser/extensions/notifications_apitest.cc @@ -4,9 +4,9 @@ #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/browser.h" #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" // Fails and hoses bot, http://crbug.com/50060. // Flaky, http://crbug.com/42314. diff --git a/chrome/browser/extensions/page_action_apitest.cc b/chrome/browser/extensions/page_action_apitest.cc index 95e029e..dede04b 100644 --- a/chrome/browser/extensions/page_action_apitest.cc +++ b/chrome/browser/extensions/page_action_apitest.cc @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extensions_service.h" -#include "chrome/browser/profile.h" #include "chrome/browser/location_bar.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/extensions/extension.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/extensions/extension_action.h" +#include "chrome/common/extensions/extension.h" #include "chrome/test/ui_test_utils.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PageAction) { diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc index c1702b1..faf236b 100644 --- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc +++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc @@ -228,6 +228,10 @@ bool SandboxedExtensionUnpacker::ValidateSignature() { ReportFailure("Key length is zero"); return false; } + if (header.signature_size == 0) { + ReportFailure("Signature length is zero"); + return false; + } std::vector key; key.resize(header.key_size); diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.cc b/chrome/browser/extensions/theme_installed_infobar_delegate.cc index ebfbe98..49f690c 100644 --- a/chrome/browser/extensions/theme_installed_infobar_delegate.cc +++ b/chrome/browser/extensions/theme_installed_infobar_delegate.cc @@ -19,7 +19,8 @@ #include "grit/theme_resources.h" ThemeInstalledInfoBarDelegate::ThemeInstalledInfoBarDelegate( - TabContents* tab_contents, const Extension* new_theme, + TabContents* tab_contents, + const Extension* new_theme, const std::string& previous_theme_id) : ConfirmInfoBarDelegate(tab_contents), profile_(tab_contents->profile()), @@ -51,8 +52,7 @@ string16 ThemeInstalledInfoBarDelegate::GetMessageText() const { SkBitmap* ThemeInstalledInfoBarDelegate::GetIcon() const { // TODO(aa): Reply with the theme's icon, but this requires reading it // asynchronously from disk. - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_THEME); + return ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_INFOBAR_THEME); } ThemeInstalledInfoBarDelegate* @@ -66,15 +66,11 @@ int ThemeInstalledInfoBarDelegate::GetButtons() const { string16 ThemeInstalledInfoBarDelegate::GetButtonLabel( ConfirmInfoBarDelegate::InfoBarButton button) const { - switch (button) { - case BUTTON_CANCEL: { - return l10n_util::GetStringUTF16(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON); - } - default: - // The InfoBar will create a default OK button and make it invisible. - // TODO(mirandac): remove the default OK button from ConfirmInfoBar. - return string16(); - } + // The InfoBar will create a default OK button and make it invisible. + // TODO(mirandac): remove the default OK button from ConfirmInfoBar. + return (button == BUTTON_CANCEL) ? + l10n_util::GetStringUTF16(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON) : + string16(); } bool ThemeInstalledInfoBarDelegate::Cancel() { @@ -98,19 +94,12 @@ void ThemeInstalledInfoBarDelegate::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { - switch (type.value) { - case NotificationType::BROWSER_THEME_CHANGED: { - // If the new theme is different from what this info bar is associated - // with, close this info bar since it is no longer relevant. - const Extension* extension = Details(details).ptr(); - if (!extension || theme_id_ != extension->id()) - tab_contents_->RemoveInfoBar(this); - break; - } - - default: - NOTREACHED(); - } + DCHECK_EQ(NotificationType::BROWSER_THEME_CHANGED, type.value); + // If the new theme is different from what this info bar is associated + // with, close this info bar since it is no longer relevant. + const Extension* extension = Details(details).ptr(); + if (!extension || theme_id_ != extension->id()) + tab_contents_->RemoveInfoBar(this); } bool ThemeInstalledInfoBarDelegate::MatchesTheme(const Extension* theme) { diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc index 5de474b..7fe20b9 100644 --- a/chrome/browser/extensions/window_open_apitest.cc +++ b/chrome/browser/extensions/window_open_apitest.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include "base/command_line.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ui_test_utils.h" #include "net/base/mock_host_resolver.h" diff --git a/chrome/browser/external_protocol_handler.cc b/chrome/browser/external_protocol_handler.cc index e005780..49c0061 100644 --- a/chrome/browser/external_protocol_handler.cc +++ b/chrome/browser/external_protocol_handler.cc @@ -12,10 +12,10 @@ #include "base/message_loop.h" #include "base/string_util.h" #include "base/thread.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process_impl.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" diff --git a/chrome/browser/external_tab_container_win.cc b/chrome/browser/external_tab_container_win.cc index eb336b9..41b0a99 100644 --- a/chrome/browser/external_tab_container_win.cc +++ b/chrome/browser/external_tab_container_win.cc @@ -19,6 +19,7 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/debugger/devtools_toggle_action.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/load_notification_details.h" #include "chrome/browser/page_info_window.h" @@ -27,10 +28,11 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" #include "chrome/browser/tab_contents/provisional_load_details.h" -#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/page_info_bubble_view.h" +#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h" #include "chrome/browser/views/tab_contents/tab_contents_container.h" +#include "chrome/common/automation_messages.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/render_messages.h" @@ -38,7 +40,7 @@ #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/notification_service.h" #include "chrome/common/page_transition_types.h" -#include "chrome/test/automation/automation_messages.h" +#include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "views/grid_layout.h" @@ -66,7 +68,8 @@ class ExternalTabPageInfoBubbleView : public PageInfoBubbleView { } // LinkController methods: virtual void LinkActivated(views::Link* source, int event_flags) { - GURL url = GURL(l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER)); + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kPageInfoHelpCenterURL)); container_->OpenURLFromTab(container_->tab_contents(), url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); } diff --git a/chrome/browser/external_tab_container_win.h b/chrome/browser/external_tab_container_win.h index 226c01d..91ce11c 100644 --- a/chrome/browser/external_tab_container_win.h +++ b/chrome/browser/external_tab_container_win.h @@ -13,9 +13,9 @@ #include "base/lazy_instance.h" #include "base/scoped_ptr.h" #include "chrome/browser/automation/automation_resource_message_filter.h" -#include "chrome/browser/browser.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/views/frame/browser_bubble_host.h" #include "chrome/browser/views/infobars/infobar_container.h" #include "chrome/browser/views/unhandled_keyboard_event_handler.h" diff --git a/chrome/browser/file_system/browser_file_system_callback_dispatcher.cc b/chrome/browser/file_system/browser_file_system_callback_dispatcher.cc index b95930f..810bf3f 100644 --- a/chrome/browser/file_system/browser_file_system_callback_dispatcher.cc +++ b/chrome/browser/file_system/browser_file_system_callback_dispatcher.cc @@ -36,8 +36,11 @@ void BrowserFileSystemCallbackDispatcher::DidReadDirectory( } void BrowserFileSystemCallbackDispatcher::DidOpenFileSystem( - const std::string&, const FilePath&) { - NOTREACHED(); + const std::string& name, const FilePath& path) { + dispatcher_host_->Send( + new ViewMsg_OpenFileSystemRequest_Complete( + request_id_, !path.empty(), name, path)); + dispatcher_host_->RemoveCompletedOperation(request_id_); } void BrowserFileSystemCallbackDispatcher::DidFail( diff --git a/chrome/browser/file_system/browser_file_system_context.cc b/chrome/browser/file_system/browser_file_system_context.cc new file mode 100644 index 0000000..bbc4806 --- /dev/null +++ b/chrome/browser/file_system/browser_file_system_context.cc @@ -0,0 +1,34 @@ +// 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/file_system/browser_file_system_context.h" + +#include "base/file_path.h" +#include "base/command_line.h" +#include "chrome/common/chrome_switches.h" +#include "webkit/fileapi/file_system_quota_manager.h" + +BrowserFileSystemContext::BrowserFileSystemContext( + const FilePath& profile_path, bool is_incognito) + : fileapi::SandboxedFileSystemContext( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), + profile_path, + is_incognito, + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAllowFileAccessFromFiles), + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUnlimitedQuotaForFiles)) { +} + +void BrowserFileSystemContext::SetOriginQuotaUnlimited(const GURL& url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + quota_manager()->SetOriginQuotaUnlimited(url); +} + +void BrowserFileSystemContext::ResetOriginQuotaUnlimited(const GURL& url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + quota_manager()->ResetOriginQuotaUnlimited(url); +} + +BrowserFileSystemContext::~BrowserFileSystemContext() {} diff --git a/chrome/browser/file_system/browser_file_system_context.h b/chrome/browser/file_system/browser_file_system_context.h new file mode 100644 index 0000000..8082179 --- /dev/null +++ b/chrome/browser/file_system/browser_file_system_context.h @@ -0,0 +1,35 @@ +// 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_FILE_SYSTEM_BROWSER_FILE_SYSTEM_CONTEXT_H_ +#define CHROME_BROWSER_FILE_SYSTEM_BROWSER_FILE_SYSTEM_CONTEXT_H_ + +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/browser_thread.h" +#include "webkit/fileapi/sandboxed_file_system_context.h" + +class FilePath; +class GURL; + +// This is owned by profile and shared by all the FileSystemDispatcherHost +// that shared by the same profile. This class is just a thin wrapper around +// fileapi::SandboxedFileSystemContext. +class BrowserFileSystemContext + : public base::RefCountedThreadSafe, + public fileapi::SandboxedFileSystemContext { + public: + BrowserFileSystemContext(const FilePath& profile_path, bool is_incognito); + virtual ~BrowserFileSystemContext(); + + // Quota related methods. + void SetOriginQuotaUnlimited(const GURL& url); + void ResetOriginQuotaUnlimited(const GURL& url); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(BrowserFileSystemContext); +}; + +#endif // CHROME_BROWSER_FILE_SYSTEM_BROWSER_FILE_SYSTEM_CONTEXT_H_ diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc index cb13bd0..12b4d19 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.cc +++ b/chrome/browser/file_system/file_system_dispatcher_host.cc @@ -10,7 +10,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/file_system/browser_file_system_callback_dispatcher.h" -#include "chrome/browser/file_system/file_system_host_context.h" +#include "chrome/browser/file_system/browser_file_system_context.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" @@ -20,65 +20,20 @@ #include "chrome/common/render_messages_params.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_context.h" +#include "webkit/fileapi/file_system_operation.h" #include "webkit/fileapi/file_system_path_manager.h" -#include "webkit/fileapi/file_system_quota.h" +#include "webkit/fileapi/file_system_quota_manager.h" +#include "webkit/fileapi/sandboxed_file_system_operation.h" -using fileapi::FileSystemQuota; - -class FileSystemDispatcherHost::OpenFileSystemTask { - public: - static void Start( - int request_id, - const GURL& origin_url, - fileapi::FileSystemType type, - bool create, - FileSystemDispatcherHost* dispatcher_host) { - // The task is self-destructed. - new OpenFileSystemTask( - request_id, origin_url, type, create, dispatcher_host); - } - - private: - void DidGetRootPath(bool success, const FilePath& root_path, - const std::string& name) { - if (success) - dispatcher_host_->Send( - new ViewMsg_OpenFileSystemRequest_Complete( - request_id_, true, name, root_path)); - else - dispatcher_host_->Send( - new ViewMsg_OpenFileSystemRequest_Complete( - request_id_, false, std::string(), FilePath())); - delete this; - } - - OpenFileSystemTask( - int request_id, - const GURL& origin_url, - fileapi::FileSystemType type, - bool create, - FileSystemDispatcherHost* dispatcher_host) - : request_id_(request_id), - dispatcher_host_(dispatcher_host), - callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { - dispatcher_host->context_->path_manager()->GetFileSystemRootPath( - origin_url, type, create, - callback_factory_.NewCallback(&OpenFileSystemTask::DidGetRootPath)); - } - - int request_id_; - std::string name_; - FilePath root_path_; - scoped_refptr dispatcher_host_; - base::ScopedCallbackFactory callback_factory_; -}; +using fileapi::FileSystemQuotaManager; +using fileapi::SandboxedFileSystemOperation; FileSystemDispatcherHost::FileSystemDispatcherHost( IPC::Message::Sender* sender, Profile* profile) : message_sender_(sender), process_handle_(0), shutdown_(false), - context_(profile->GetFileSystemHostContext()), + context_(profile->GetFileSystemContext()), host_content_settings_map_(profile->GetHostContentSettingsMap()), request_context_getter_(profile->GetRequestContext()) { DCHECK(message_sender_); @@ -89,7 +44,7 @@ FileSystemDispatcherHost::FileSystemDispatcherHost( : message_sender_(sender), process_handle_(0), shutdown_(false), - context_(context->file_system_host_context()), + context_(context->browser_file_system_context()), host_content_settings_map_(context->host_content_settings_map()), request_context_(context) { DCHECK(message_sender_); @@ -156,48 +111,32 @@ void FileSystemDispatcherHost::OnOpenFileSystem( return; } - OpenFileSystemTask::Start(request_id, origin_url, type, create, this); + GetNewOperation(request_id)->OpenFileSystem(origin_url, type, create); } void FileSystemDispatcherHost::OnMove( int request_id, const FilePath& src_path, const FilePath& dest_path) { - if (!VerifyFileSystemPathForRead(src_path, request_id) || - !VerifyFileSystemPathForWrite(dest_path, request_id, true /* create */, - FileSystemQuota::kUnknownSize)) - return; - GetNewOperation(request_id)->Move(src_path, dest_path); } void FileSystemDispatcherHost::OnCopy( int request_id, const FilePath& src_path, const FilePath& dest_path) { - if (!VerifyFileSystemPathForRead(src_path, request_id) || - !VerifyFileSystemPathForWrite(dest_path, request_id, true /* create */, - FileSystemQuota::kUnknownSize)) - return; - GetNewOperation(request_id)->Copy(src_path, dest_path); } void FileSystemDispatcherHost::OnRemove( int request_id, const FilePath& path, bool recursive) { - if (!VerifyFileSystemPathForWrite(path, request_id, false /* create */, 0)) - return; GetNewOperation(request_id)->Remove(path, recursive); } void FileSystemDispatcherHost::OnReadMetadata( int request_id, const FilePath& path) { - if (!VerifyFileSystemPathForRead(path, request_id)) - return; GetNewOperation(request_id)->GetMetadata(path); } void FileSystemDispatcherHost::OnCreate( int request_id, const FilePath& path, bool exclusive, bool is_directory, bool recursive) { - if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, 0)) - return; if (is_directory) GetNewOperation(request_id)->CreateDirectory(path, exclusive, recursive); else @@ -206,8 +145,6 @@ void FileSystemDispatcherHost::OnCreate( void FileSystemDispatcherHost::OnExists( int request_id, const FilePath& path, bool is_directory) { - if (!VerifyFileSystemPathForRead(path, request_id)) - return; if (is_directory) GetNewOperation(request_id)->DirectoryExists(path); else @@ -216,8 +153,6 @@ void FileSystemDispatcherHost::OnExists( void FileSystemDispatcherHost::OnReadDirectory( int request_id, const FilePath& path) { - if (!VerifyFileSystemPathForRead(path, request_id)) - return; GetNewOperation(request_id)->ReadDirectory(path); } @@ -226,9 +161,6 @@ void FileSystemDispatcherHost::OnWrite( const FilePath& path, const GURL& blob_url, int64 offset) { - if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, - FileSystemQuota::kUnknownSize)) - return; GetNewOperation(request_id)->Write( request_context_, path, blob_url, offset); } @@ -237,8 +169,6 @@ void FileSystemDispatcherHost::OnTruncate( int request_id, const FilePath& path, int64 length) { - if (!VerifyFileSystemPathForWrite(path, request_id, false /* create */, 0)) - return; GetNewOperation(request_id)->Truncate(path, length); } @@ -247,8 +177,6 @@ void FileSystemDispatcherHost::OnTouchFile( const FilePath& path, const base::Time& last_access_time, const base::Time& last_modified_time) { - if (!VerifyFileSystemPathForWrite(path, request_id, true /* create */, 0)) - return; GetNewOperation(request_id)->TouchFile( path, last_access_time, last_modified_time); } @@ -256,8 +184,8 @@ void FileSystemDispatcherHost::OnTouchFile( void FileSystemDispatcherHost::OnCancel( int request_id, int request_id_to_cancel) { - fileapi::FileSystemOperation* write = - operations_.Lookup(request_id_to_cancel); + SandboxedFileSystemOperation* write = operations_.Lookup( + request_id_to_cancel); if (write) { // The cancel will eventually send both the write failure and the cancel // success. @@ -277,69 +205,14 @@ void FileSystemDispatcherHost::Send(IPC::Message* message) { delete message; } -bool FileSystemDispatcherHost::VerifyFileSystemPathForRead( - const FilePath& path, int request_id) { - // We may want do more checks, but for now it just checks if the given - // |path| is under the valid FileSystem root path for this host context. - if (!context_->path_manager()->CrackFileSystemPath( - path, NULL, NULL, NULL)) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_SECURITY)); - return false; - } - return true; -} - -bool FileSystemDispatcherHost::VerifyFileSystemPathForWrite( - const FilePath& path, int request_id, bool create, int64 growth) { - GURL origin_url; - FilePath virtual_path; - if (!context_->path_manager()->CrackFileSystemPath( - path, &origin_url, NULL, &virtual_path)) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_SECURITY)); - return false; - } - // Any write access is disallowed on the root path. - if (virtual_path.value().length() == 0 || - virtual_path.DirName().value() == virtual_path.value()) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_SECURITY)); - return false; - } - if (create && context_->path_manager()->IsRestrictedFileName( - path.BaseName())) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_SECURITY)); - return false; - } - // TODO(kinuko): For operations with kUnknownSize we'll eventually - // need to resolve what amount of size it's going to write. - if (!context_->CheckOriginQuota(origin_url, growth)) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_NO_SPACE)); - return false; - } - return true; -} - -bool FileSystemDispatcherHost::CheckIfFilePathIsSafe( - const FilePath& path, int request_id) { - if (context_->path_manager()->IsRestrictedFileName(path.BaseName())) { - Send(new ViewMsg_FileSystem_DidFail( - request_id, base::PLATFORM_FILE_ERROR_SECURITY)); - return false; - } - return true; -} - -fileapi::FileSystemOperation* FileSystemDispatcherHost::GetNewOperation( +SandboxedFileSystemOperation* FileSystemDispatcherHost::GetNewOperation( int request_id) { BrowserFileSystemCallbackDispatcher* dispatcher = new BrowserFileSystemCallbackDispatcher(this, request_id); - fileapi::FileSystemOperation* operation = new fileapi::FileSystemOperation( + SandboxedFileSystemOperation* operation = new SandboxedFileSystemOperation( dispatcher, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), + context_.get()); operations_.AddWithID(operation, request_id); return operation; } diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h index f51e7f2..2cfe4f6 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.h +++ b/chrome/browser/file_system/file_system_dispatcher_host.h @@ -5,16 +5,13 @@ #ifndef CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_DISPATCHER_HOST_H_ #define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_DISPATCHER_HOST_H_ +#include + #include "base/basictypes.h" -#include "base/file_util.h" #include "base/id_map.h" -#include "base/nullable_string16.h" #include "base/process.h" -#include "base/platform_file.h" -#include "base/scoped_callback_factory.h" #include "base/ref_counted.h" #include "ipc/ipc_message.h" -#include "webkit/fileapi/file_system_operation.h" #include "webkit/fileapi/file_system_types.h" namespace base { @@ -22,14 +19,20 @@ class Time; } class ChromeURLRequestContext; -class FileSystemHostContext; +class BrowserFileSystemContext; +class FilePath; class GURL; class HostContentSettingsMap; class Profile; class Receiver; class ResourceMessageFilter; +class URLRequestContext; class URLRequestContextGetter; +namespace fileapi { +class SandboxedFileSystemOperation; +} + class FileSystemDispatcherHost : public base::RefCountedThreadSafe { public: @@ -79,37 +82,8 @@ class FileSystemDispatcherHost void RemoveCompletedOperation(int request_id); private: - // Creates a new FileSystemOperation. - fileapi::FileSystemOperation* GetNewOperation(int request_id); - - // Checks the validity of a given |path| for reading. - // Returns true if the given |path| is a valid FileSystem path. - // Otherwise it sends back PLATFORM_FILE_ERROR_SECURITY to the - // dispatcher and returns false. - bool VerifyFileSystemPathForRead(const FilePath& path, int request_id); - - // Checks the validity of a given |path| for writing. - // Returns true if the given |path| is a valid FileSystem path, and - // its origin embedded in the path has the right to write as much as - // the given |growth|. - // Otherwise it sends back PLATFORM_FILE_ERROR_SECURITY if the path - // is not valid for writing, or sends back PLATFORM_FILE_ERROR_NO_SPACE - // if the origin is not allowed to increase the usage by |growth|. - // If |create| flag is true this also checks if the |path| contains - // any restricted names and chars. If it does, the call sends back - // PLATFORM_FILE_ERROR_SECURITY to the dispatcher. - bool VerifyFileSystemPathForWrite(const FilePath& path, - int request_id, - bool create, - int64 growth); - - class OpenFileSystemTask; - - // Checks if a given |path| does not contain any restricted names/chars - // for new files. Returns true if the given |path| is safe. - // Otherwise it sends back a security error code to the dispatcher and - // returns false. - bool CheckIfFilePathIsSafe(const FilePath& path, int request_id); + // Creates a new SandboxedFileSystemOperation. + fileapi::SandboxedFileSystemOperation* GetNewOperation(int request_id); // The sender to be used for sending out IPC messages. IPC::Message::Sender* message_sender_; @@ -119,13 +93,14 @@ class FileSystemDispatcherHost bool shutdown_; - scoped_refptr context_; + scoped_refptr context_; // Used to look up permissions. scoped_refptr host_content_settings_map_; // Keeps ongoing file system operations. - typedef IDMap OperationsMap; + typedef IDMap + OperationsMap; OperationsMap operations_; // This holds the URLRequestContextGetter until Init() can be called from the diff --git a/chrome/browser/file_system/file_system_host_context.cc b/chrome/browser/file_system/file_system_host_context.cc deleted file mode 100644 index 34698db..0000000 --- a/chrome/browser/file_system/file_system_host_context.cc +++ /dev/null @@ -1,50 +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/file_system/file_system_host_context.h" - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/common/chrome_switches.h" -#include "googleurl/src/gurl.h" -#include "webkit/glue/webkit_glue.h" - -FileSystemHostContext::FileSystemHostContext( - const FilePath& data_path, bool is_incognito) - : quota_manager_(new fileapi::FileSystemQuota()) { - CommandLine* command_line = CommandLine::ForCurrentProcess(); - allow_file_access_from_files_ = - command_line->HasSwitch(switches::kAllowFileAccessFromFiles); - unlimited_quota_ = - command_line->HasSwitch(switches::kUnlimitedQuotaForFiles); - path_manager_.reset(new fileapi::FileSystemPathManager( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), - data_path, is_incognito, allow_file_access_from_files_)); -} - -bool FileSystemHostContext::CheckOriginQuota(const GURL& url, int64 growth) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - // If allow-file-access-from-files flag is explicitly given and the scheme - // is file, or if unlimited quota for this process was explicitly requested, - // return true. - if (unlimited_quota_ || - (url.SchemeIsFile() && allow_file_access_from_files_)) - return true; - return quota_manager_->CheckOriginQuota(url, growth); -} - -void FileSystemHostContext::SetOriginQuotaUnlimited(const GURL& url) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - quota_manager_->SetOriginQuotaUnlimited(url); -} - -void FileSystemHostContext::ResetOriginQuotaUnlimited(const GURL& url) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - quota_manager_->ResetOriginQuotaUnlimited(url); -} - -FileSystemHostContext::~FileSystemHostContext() {} diff --git a/chrome/browser/file_system/file_system_host_context.h b/chrome/browser/file_system/file_system_host_context.h deleted file mode 100644 index ddb0bf2..0000000 --- a/chrome/browser/file_system/file_system_host_context.h +++ /dev/null @@ -1,44 +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_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_ -#define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_ - -#include "base/file_path.h" -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/browser_thread.h" -#include "webkit/fileapi/file_system_types.h" -#include "webkit/fileapi/file_system_path_manager.h" -#include "webkit/fileapi/file_system_quota.h" - -class GURL; - -// This is owned by profile and shared by all the FileSystemDispatcherHost -// that shared by the same profile. -class FileSystemHostContext - : public base::RefCountedThreadSafe { - public: - FileSystemHostContext(const FilePath& data_path, bool is_incognito); - virtual ~FileSystemHostContext(); - - // Quota related methods. - bool CheckOriginQuota(const GURL& url, int64 growth); - void SetOriginQuotaUnlimited(const GURL& url); - void ResetOriginQuotaUnlimited(const GURL& url); - - fileapi::FileSystemPathManager* path_manager() { return path_manager_.get(); } - - private: - scoped_ptr quota_manager_; - scoped_ptr path_manager_; - - bool allow_file_access_from_files_; - bool unlimited_quota_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemHostContext); -}; - -#endif // CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_ diff --git a/chrome/browser/find_bar_host_browsertest.cc b/chrome/browser/find_bar_host_browsertest.cc index f36dd32..eaf5b3b 100644 --- a/chrome/browser/find_bar_host_browsertest.cc +++ b/chrome/browser/find_bar_host_browsertest.cc @@ -6,9 +6,6 @@ #include "base/message_loop.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_navigator.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/find_bar.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/find_notification_details.h" @@ -17,6 +14,9 @@ #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/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/notification_service.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/gears_integration.cc b/chrome/browser/gears_integration.cc index d1f13cf..1ab162a 100644 --- a/chrome/browser/gears_integration.cc +++ b/chrome/browser/gears_integration.cc @@ -15,10 +15,10 @@ #include "chrome/browser/chrome_plugin_host.h" #include "chrome/common/chrome_plugin_util.h" #include "chrome/common/gears_api.h" +#include "chrome/common/web_apps.h" #include "gfx/codec/png_codec.h" #include "googleurl/src/gurl.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "webkit/glue/dom_operations.h" // The following 2 helpers are borrowed from the Gears codebase. @@ -139,7 +139,7 @@ class CreateShortcutCommand : public CPCommandInterface { CreateShortcutCommand( const std::string& name, const std::string& orig_name, const std::string& url, const std::string& description, - const std::vector &icons, + const std::vector &icons, const SkBitmap& fallback_icon, GearsCreateShortcutCallback* callback) : name_(name), url_(url), description_(description), @@ -157,7 +157,7 @@ class CreateShortcutCommand : public CPCommandInterface { bool has_icon = false; for (size_t i = 0; i < icons.size(); ++i) { - const webkit_glue::WebApplicationInfo::IconInfo& icon = icons[i]; + const WebApplicationInfo::IconInfo& icon = icons[i]; if (icon.width == 16 && icon.height == 16) { has_icon = true; InitIcon(SIZE_16x16, icon.url, 16, 16); @@ -232,7 +232,7 @@ class CreateShortcutCommand : public CPCommandInterface { DISABLE_RUNNABLE_METHOD_REFCOUNT(CreateShortcutCommand); void GearsCreateShortcut( - const webkit_glue::WebApplicationInfo& app_info, + const WebApplicationInfo& app_info, const string16& fallback_name, const GURL& fallback_url, const SkBitmap& fallback_icon, diff --git a/chrome/browser/gears_integration.h b/chrome/browser/gears_integration.h index 4723c9b..6461377 100644 --- a/chrome/browser/gears_integration.h +++ b/chrome/browser/gears_integration.h @@ -18,9 +18,7 @@ class CPCommandInterface; class GURL; class SkBitmap; -namespace webkit_glue { struct WebApplicationInfo; -} // We use this in place of GearsShortcutData so we can keep browser-specific // data on the structure. @@ -40,12 +38,11 @@ void GearsSettingsPressed(gfx::NativeWindow parent_wnd); typedef Callback2::Type GearsCreateShortcutCallback; -void GearsCreateShortcut( - const webkit_glue::WebApplicationInfo& app_info, - const string16& fallback_name, - const GURL& fallback_url, - const SkBitmap& fallback_icon, - GearsCreateShortcutCallback* callback); +void GearsCreateShortcut(const WebApplicationInfo& app_info, + const string16& fallback_name, + const GURL& fallback_url, + const SkBitmap& fallback_icon, + GearsCreateShortcutCallback* callback); // Call into Gears to query the list of shortcuts. Results will be returned // asynchronously via the callback. The callback's arguments will be NULL diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index 30510ac..bc9d719 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc @@ -6,7 +6,6 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/dom_operation_notification_details.h" @@ -18,6 +17,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/geoposition.h" #include "chrome/common/notification_details.h" diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc index 4d7c848..bf19218 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.cc +++ b/chrome/browser/geolocation/geolocation_permission_context.cc @@ -7,12 +7,12 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/geolocation/geolocation_dispatcher_host_old.h" #include "chrome/browser/geolocation/geolocation_provider.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" @@ -21,6 +21,7 @@ #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" @@ -29,6 +30,17 @@ #include "grit/theme_resources.h" #include "net/base/net_util.h" +namespace { + +const char kGeolocationLearnMoreUrl[] = +#if defined(OS_CHROMEOS) + "http://www.google.com/support/chromeos/bin/answer.py?answer=142065"; +#else + "http://www.google.com/support/chrome/bin/answer.py?answer=142065"; +#endif + +} // namespace + // This class controls the geolocation infobar queue per profile, and it's an // internal class to GeolocationPermissionContext. // An alternate approach would be to have this queue per tab, and use @@ -138,10 +150,11 @@ class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { return l10n_util::GetStringUTF16(IDS_LEARN_MORE); } virtual bool LinkClicked(WindowOpenDisposition disposition) { - // Ignore the click dispostion and always open in a new top level tab. + GURL learn_more_url = + google_util::AppendGoogleLocaleParam(GURL(kGeolocationLearnMoreUrl)); + // Ignore the click disposition and always open in a new top level tab. tab_contents_->OpenURL( - GURL(l10n_util::GetStringUTF8(IDS_LEARN_MORE_GEOLOCATION_URL)), GURL(), - NEW_FOREGROUND_TAB, PageTransition::LINK); + learn_more_url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); return false; // Do not dismiss the info bar. } diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm index 6e3f206..cc5ba64 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac.mm @@ -31,15 +31,24 @@ const KeyboardShortcutData* GetWindowKeyboardShortcutTable {false, false, true, false, kVK_PageUp, 0, IDC_SELECT_PREVIOUS_TAB}, {false, true, true, false, kVK_Tab, 0, IDC_SELECT_PREVIOUS_TAB}, // Cmd-0..8 select the Nth tab, with cmd-9 being "last tab". - {true, false, false, false, kVK_ANSI_1, 0, IDC_SELECT_TAB_0}, - {true, false, false, false, kVK_ANSI_2, 0, IDC_SELECT_TAB_1}, - {true, false, false, false, kVK_ANSI_3, 0, IDC_SELECT_TAB_2}, - {true, false, false, false, kVK_ANSI_4, 0, IDC_SELECT_TAB_3}, - {true, false, false, false, kVK_ANSI_5, 0, IDC_SELECT_TAB_4}, - {true, false, false, false, kVK_ANSI_6, 0, IDC_SELECT_TAB_5}, - {true, false, false, false, kVK_ANSI_7, 0, IDC_SELECT_TAB_6}, - {true, false, false, false, kVK_ANSI_8, 0, IDC_SELECT_TAB_7}, - {true, false, false, false, kVK_ANSI_9, 0, IDC_SELECT_LAST_TAB}, + {true, false, false, false, kVK_ANSI_1, 0, IDC_SELECT_TAB_0}, + {true, false, false, false, kVK_ANSI_Keypad1, 0, IDC_SELECT_TAB_0}, + {true, false, false, false, kVK_ANSI_2, 0, IDC_SELECT_TAB_1}, + {true, false, false, false, kVK_ANSI_Keypad2, 0, IDC_SELECT_TAB_1}, + {true, false, false, false, kVK_ANSI_3, 0, IDC_SELECT_TAB_2}, + {true, false, false, false, kVK_ANSI_Keypad3, 0, IDC_SELECT_TAB_2}, + {true, false, false, false, kVK_ANSI_4, 0, IDC_SELECT_TAB_3}, + {true, false, false, false, kVK_ANSI_Keypad4, 0, IDC_SELECT_TAB_3}, + {true, false, false, false, kVK_ANSI_5, 0, IDC_SELECT_TAB_4}, + {true, false, false, false, kVK_ANSI_Keypad5, 0, IDC_SELECT_TAB_4}, + {true, false, false, false, kVK_ANSI_6, 0, IDC_SELECT_TAB_5}, + {true, false, false, false, kVK_ANSI_Keypad6, 0, IDC_SELECT_TAB_5}, + {true, false, false, false, kVK_ANSI_7, 0, IDC_SELECT_TAB_6}, + {true, false, false, false, kVK_ANSI_Keypad7, 0, IDC_SELECT_TAB_6}, + {true, false, false, false, kVK_ANSI_8, 0, IDC_SELECT_TAB_7}, + {true, false, false, false, kVK_ANSI_Keypad8, 0, IDC_SELECT_TAB_7}, + {true, false, false, false, kVK_ANSI_9, 0, IDC_SELECT_LAST_TAB}, + {true, false, false, false, kVK_ANSI_Keypad9, 0, IDC_SELECT_LAST_TAB}, }; *num_entries = arraysize(keyboard_shortcuts); @@ -152,8 +161,20 @@ int CommandForBrowserKeyboardShortcut( } unichar KeyCharacterForEvent(NSEvent* event) { - const NSString* eventString = [event charactersIgnoringModifiers]; - const NSString* characters = [event characters]; + NSString* eventString = [event charactersIgnoringModifiers]; + NSString* characters = [event characters]; + + // Character pairs that undergo BiDi mirrored. + // There are actually many more such pairs, but these are the ones that + // are likely to show up in keyboard shortcuts. + const struct { + unichar a; + unichar b; + } kMirroredBiDiChars[] = { + {'{', '}'}, + {'[', ']'}, + {'(', ')'}, + }; if ([eventString length] != 1) return 0; @@ -161,13 +182,30 @@ unichar KeyCharacterForEvent(NSEvent* event) { if ([characters length] != 1) return [eventString characterAtIndex:0]; + unichar noModifiersChar = [eventString characterAtIndex:0]; + unichar rawChar = [characters characterAtIndex:0]; // When both |characters| and |charactersIgnoringModifiers| are ascii, // return the first character of |characters|, if... - if (isascii([eventString characterAtIndex:0]) && - isascii([characters characterAtIndex:0])) { + if (isascii(noModifiersChar) && isascii(rawChar)) { // |characters| is an alphabet (mainly for dvorak-qwerty layout), or - if (isalpha([characters characterAtIndex:0])) - return [characters characterAtIndex:0]; + if (isalpha(rawChar)) + return rawChar; + + // http://crbug.com/42517 + // In RTL keyboard layouts, Cocoa mirrors characters in the string + // returned by [event charactersIgnoringModifiers]. In this case, return + // the raw (unmirrored) char. + // FIXME: If there is a need to add any more characters to the + // kMirroredBiDiChars table, then it's probably better to use ICU's + // u_charMirror() function to perform this test. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kMirroredBiDiChars); ++i) { + const unichar& a = kMirroredBiDiChars[i].a; + const unichar& b = kMirroredBiDiChars[i].b; + if ((rawChar == a && noModifiersChar == b) || + (rawChar == b && noModifiersChar == a)) + return rawChar; + } + // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). if ([event modifierFlags] & NSAlternateKeyMask) return [characters characterAtIndex:0]; diff --git a/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm b/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm index 4e3ab07..cdf3956 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm @@ -12,7 +12,7 @@ TEST(GlobalKeyboardShortcuts, ShortcutsToWindowCommand) { // Test that an invalid shortcut translates into an invalid command id. - ASSERT_EQ( + EXPECT_EQ( -1, CommandForWindowKeyboardShortcut(false, false, false, false, 0, 0)); // Check that all known keyboard shortcuts return valid results. @@ -24,32 +24,86 @@ TEST(GlobalKeyboardShortcuts, ShortcutsToWindowCommand) { int cmd_num = CommandForWindowKeyboardShortcut( it->command_key, it->shift_key, it->cntrl_key, it->opt_key, it->vkey_code, it->key_char); - ASSERT_EQ(cmd_num, it->chrome_command); + EXPECT_EQ(cmd_num, it->chrome_command); } // Test that cmd-left and backspace are not window-level commands (else they // would be invoked even if e.g. the omnibox had focus, where they really // should have text editing functionality). - ASSERT_EQ(-1, CommandForWindowKeyboardShortcut( + EXPECT_EQ(-1, CommandForWindowKeyboardShortcut( true, false, false, false, kVK_LeftArrow, 0)); - ASSERT_EQ(-1, CommandForWindowKeyboardShortcut( + EXPECT_EQ(-1, CommandForWindowKeyboardShortcut( false, false, false, false, kVK_Delete, 0)); // Test that Cmd-'{' and Cmd-'}' are interpreted as IDC_SELECT_NEXT_TAB // and IDC_SELECT_PREVIOUS_TAB regardless of the virtual key code values. - ASSERT_EQ(IDC_SELECT_NEXT_TAB, CommandForWindowKeyboardShortcut( + EXPECT_EQ(IDC_SELECT_NEXT_TAB, CommandForWindowKeyboardShortcut( true, false, false, false, kVK_ANSI_Period, '}')); - ASSERT_EQ(IDC_SELECT_PREVIOUS_TAB, CommandForWindowKeyboardShortcut( + EXPECT_EQ(IDC_SELECT_PREVIOUS_TAB, CommandForWindowKeyboardShortcut( true, true, false, false, kVK_ANSI_Slash, '{')); - // One more test for Cmd-'{' / Alt-8 (on german keyboard layout). - ASSERT_EQ(IDC_SELECT_PREVIOUS_TAB, CommandForWindowKeyboardShortcut( + // One more test for Cmd-'{' / Alt-8 (on German keyboard layout). + EXPECT_EQ(IDC_SELECT_PREVIOUS_TAB, CommandForWindowKeyboardShortcut( true, false, false, true, kVK_ANSI_8, '{')); + + // Test that switching tabs triggers off keycodes and not characters (visible + // with the Italian keyboard layout). + EXPECT_EQ(IDC_SELECT_TAB_0, CommandForWindowKeyboardShortcut( + true, false, false, false, kVK_ANSI_1, '&')); +} + +TEST(GlobalKeyboardShortcuts, KeypadNumberKeysMatch) { + // Test that the shortcuts that are generated by keypad number keys match the + // equivalent keys. + static const struct { + int keycode; + int keypad_keycode; + } equivalents[] = { + {kVK_ANSI_0, kVK_ANSI_Keypad0}, + {kVK_ANSI_1, kVK_ANSI_Keypad1}, + {kVK_ANSI_2, kVK_ANSI_Keypad2}, + {kVK_ANSI_3, kVK_ANSI_Keypad3}, + {kVK_ANSI_4, kVK_ANSI_Keypad4}, + {kVK_ANSI_5, kVK_ANSI_Keypad5}, + {kVK_ANSI_6, kVK_ANSI_Keypad6}, + {kVK_ANSI_7, kVK_ANSI_Keypad7}, + {kVK_ANSI_8, kVK_ANSI_Keypad8}, + {kVK_ANSI_9, kVK_ANSI_Keypad9}, + }; + + for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(equivalents); ++i) { + for (int command = 0; command <= 1; ++command) { + for (int shift = 0; shift <= 1; ++shift) { + for (int control = 0; control <= 1; ++control) { + for (int option = 0; option <= 1; ++option) { + EXPECT_EQ( + CommandForWindowKeyboardShortcut( + command, shift, control, option, equivalents[i].keycode, 0), + CommandForWindowKeyboardShortcut( + command, shift, control, option, + equivalents[i].keypad_keycode, 0)); + EXPECT_EQ( + CommandForDelayedWindowKeyboardShortcut( + command, shift, control, option, equivalents[i].keycode, 0), + CommandForDelayedWindowKeyboardShortcut( + command, shift, control, option, + equivalents[i].keypad_keycode, 0)); + EXPECT_EQ( + CommandForBrowserKeyboardShortcut( + command, shift, control, option, equivalents[i].keycode, 0), + CommandForBrowserKeyboardShortcut( + command, shift, control, option, + equivalents[i].keypad_keycode, 0)); + } + } + } + } + } } TEST(GlobalKeyboardShortcuts, ShortcutsToDelayedWindowCommand) { // Test that an invalid shortcut translates into an invalid command id. - ASSERT_EQ(-1, + EXPECT_EQ(-1, CommandForDelayedWindowKeyboardShortcut(false, false, false, false, 0, 0)); @@ -62,13 +116,13 @@ TEST(GlobalKeyboardShortcuts, ShortcutsToDelayedWindowCommand) { int cmd_num = CommandForDelayedWindowKeyboardShortcut( it->command_key, it->shift_key, it->cntrl_key, it->opt_key, it->vkey_code, it->key_char); - ASSERT_EQ(cmd_num, it->chrome_command); + EXPECT_EQ(cmd_num, it->chrome_command); } } TEST(GlobalKeyboardShortcuts, ShortcutsToBrowserCommand) { // Test that an invalid shortcut translates into an invalid command id. - ASSERT_EQ( + EXPECT_EQ( -1, CommandForBrowserKeyboardShortcut(false, false, false, false, 0, 0)); @@ -81,7 +135,7 @@ TEST(GlobalKeyboardShortcuts, ShortcutsToBrowserCommand) { int cmd_num = CommandForBrowserKeyboardShortcut( it->command_key, it->shift_key, it->cntrl_key, it->opt_key, it->vkey_code, it->key_char); - ASSERT_EQ(cmd_num, it->chrome_command); + EXPECT_EQ(cmd_num, it->chrome_command); } } @@ -111,24 +165,27 @@ NSEvent* KeyEvent(bool command_key, bool shift_key, TEST(GlobalKeyboardShortcuts, KeyCharacterForEvent) { // 'a' - ASSERT_EQ('a', KeyCharacterForEvent( + EXPECT_EQ('a', KeyCharacterForEvent( KeyEvent(false, false, false, false, @"a", @"a"))); // cmd-'a' / cmd-shift-'a' - ASSERT_EQ('a', KeyCharacterForEvent( + EXPECT_EQ('a', KeyCharacterForEvent( KeyEvent(true, true, false, false, @"a", @"A"))); // '8' - ASSERT_EQ('8', KeyCharacterForEvent( + EXPECT_EQ('8', KeyCharacterForEvent( KeyEvent(false, false, false, false, @"8", @"8"))); // '{' / alt-'8' on german - ASSERT_EQ('{', KeyCharacterForEvent( + EXPECT_EQ('{', KeyCharacterForEvent( KeyEvent(false, false, false, true, @"{", @"8"))); // cmd-'{' / cmd-shift-'[' on ansi - ASSERT_EQ('{', KeyCharacterForEvent( + EXPECT_EQ('{', KeyCharacterForEvent( KeyEvent(true, true, false, false, @"[", @"{"))); // cmd-'z' / cmd-shift-';' on dvorak-qwerty - ASSERT_EQ('z', KeyCharacterForEvent( + EXPECT_EQ('z', KeyCharacterForEvent( KeyEvent(true, true, false, false, @"z", @":"))); + // cmd-shift-'[' in an RTL context. + EXPECT_EQ('{', KeyCharacterForEvent( + KeyEvent(true, true, false, false, @"{", @"}"))); // Test if getting dead-key events return 0 and do not hang. - ASSERT_EQ(0, KeyCharacterForEvent( + EXPECT_EQ(0, KeyCharacterForEvent( KeyEvent(false, false, false, false, @"", @""))); } diff --git a/chrome/browser/google/google_url_tracker.cc b/chrome/browser/google/google_url_tracker.cc index 30956b6..9b06e33 100644 --- a/chrome/browser/google/google_url_tracker.cc +++ b/chrome/browser/google/google_url_tracker.cc @@ -15,7 +15,6 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/chrome_switches.h" @@ -26,90 +25,87 @@ #include "net/base/load_flags.h" #include "net/url_request/url_request_status.h" -const char GoogleURLTracker::kDefaultGoogleHomepage[] = - "http://www.google.com/"; -const char GoogleURLTracker::kSearchDomainCheckURL[] = - "https://www.google.com/searchdomaincheck?format=domain&type=chrome"; - namespace { -class GoogleURLTrackerInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - GoogleURLTrackerInfoBarDelegate(TabContents* tab_contents, - GoogleURLTracker* google_url_tracker, - const GURL& new_google_url) - : ConfirmInfoBarDelegate(tab_contents), - google_url_tracker_(google_url_tracker), - new_google_url_(new_google_url) {} - - // ConfirmInfoBarDelegate - virtual string16 GetMessageText() const { - // TODO(ukai): change new_google_url to google_base_domain? - return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE, - UTF8ToUTF16(new_google_url_.spec())); - } +InfoBarDelegate* CreateInfobar(TabContents* tab_contents, + GoogleURLTracker* google_url_tracker, + const GURL& new_google_url) { + InfoBarDelegate* infobar = new GoogleURLTrackerInfoBarDelegate(tab_contents, + google_url_tracker, new_google_url); + tab_contents->AddInfoBar(infobar); + return infobar; +} - virtual int GetButtons() const { - return BUTTON_OK | BUTTON_CANCEL; - } +} // namespace - virtual string16 GetButtonLabel(InfoBarButton button) const { - return l10n_util::GetStringUTF16((button == BUTTON_OK) ? - IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL : - IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); - } +// GoogleURLTrackerInfoBarDelegate -------------------------------------------- - virtual bool Accept() { - google_url_tracker_->AcceptGoogleURL(new_google_url_); - google_url_tracker_->RedoSearch(); - return true; - } +GoogleURLTrackerInfoBarDelegate::GoogleURLTrackerInfoBarDelegate( + TabContents* tab_contents, + GoogleURLTracker* google_url_tracker, + const GURL& new_google_url) + : ConfirmInfoBarDelegate(tab_contents), + google_url_tracker_(google_url_tracker), + new_google_url_(new_google_url) { +} - virtual bool Cancel() { - google_url_tracker_->CancelGoogleURL(new_google_url_); - return true; - } +bool GoogleURLTrackerInfoBarDelegate::Accept() { + google_url_tracker_->AcceptGoogleURL(new_google_url_); + google_url_tracker_->RedoSearch(); + return true; +} - virtual void InfoBarClosed() { - google_url_tracker_->InfoBarClosed(); - delete this; - } +bool GoogleURLTrackerInfoBarDelegate::Cancel() { + google_url_tracker_->CancelGoogleURL(new_google_url_); + return true; +} - private: - virtual ~GoogleURLTrackerInfoBarDelegate() {} +void GoogleURLTrackerInfoBarDelegate::InfoBarClosed() { + google_url_tracker_->InfoBarClosed(); + delete this; +} - GoogleURLTracker* google_url_tracker_; - const GURL new_google_url_; +GoogleURLTrackerInfoBarDelegate::~GoogleURLTrackerInfoBarDelegate() { +} - DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerInfoBarDelegate); -}; +string16 GoogleURLTrackerInfoBarDelegate::GetMessageText() const { + // TODO(ukai): change new_google_url to google_base_domain? + return l10n_util::GetStringFUTF16(IDS_GOOGLE_URL_TRACKER_INFOBAR_MESSAGE, + UTF8ToUTF16(new_google_url_.spec())); +} -} // anonymous namespace +int GoogleURLTrackerInfoBarDelegate::GetButtons() const { + return BUTTON_OK | BUTTON_CANCEL; +} -InfoBarDelegate* GoogleURLTracker::InfoBarDelegateFactory::CreateInfoBar( - TabContents* tab_contents, - GoogleURLTracker* google_url_tracker, - const GURL& new_google_url) { - InfoBarDelegate* infobar = - new GoogleURLTrackerInfoBarDelegate(tab_contents, - google_url_tracker, - new_google_url); - tab_contents->AddInfoBar(infobar); - return infobar; +string16 GoogleURLTrackerInfoBarDelegate::GetButtonLabel( + InfoBarButton button) const { + return l10n_util::GetStringUTF16((button == BUTTON_OK) ? + IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL : + IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); } + +// GoogleURLTracker ----------------------------------------------------------- + +const char GoogleURLTracker::kDefaultGoogleHomepage[] = + "http://www.google.com/"; +const char GoogleURLTracker::kSearchDomainCheckURL[] = + "https://www.google.com/searchdomaincheck?format=domain&type=chrome"; + GoogleURLTracker::GoogleURLTracker() - : google_url_(g_browser_process->local_state()->GetString( + : infobar_creator_(&CreateInfobar), + google_url_(g_browser_process->local_state()->GetString( prefs::kLastKnownGoogleURL)), ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)), fetcher_id_(0), + queue_wakeup_task_(true), in_startup_sleep_(true), already_fetched_(false), need_to_fetch_(false), request_context_available_(!!Profile::GetDefaultRequestContext()), need_to_prompt_(false), controller_(NULL), - infobar_factory_(new InfoBarDelegateFactory), infobar_(NULL) { registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, NotificationService::AllSources()); @@ -123,17 +119,9 @@ GoogleURLTracker::GoogleURLTracker() static const int kMaxRetries = 5; protect->SetMaxRetries(kMaxRetries); - // Because this function can be called during startup, when kicking off a URL - // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully - // long enough to be after startup, but still get results back quickly. - // Ideally, instead of this timer, we'd do something like "check if the - // browser is starting up, and if so, come back later", but there is currently - // no function to do this. - static const int kStartFetchDelayMS = 5000; - MessageLoop::current()->PostDelayedTask(FROM_HERE, - runnable_method_factory_.NewRunnableMethod( - &GoogleURLTracker::FinishSleep), - kStartFetchDelayMS); + MessageLoop::current()->PostTask(FROM_HERE, + runnable_method_factory_.NewRunnableMethod( + &GoogleURLTracker::QueueWakeupTask)); } GoogleURLTracker::~GoogleURLTracker() { @@ -174,6 +162,25 @@ void GoogleURLTracker::SetNeedToFetch() { StartFetchIfDesirable(); } +void GoogleURLTracker::QueueWakeupTask() { + // When testing, we want to wake from sleep at controlled times, not on a + // timer. + if (!queue_wakeup_task_) + return; + + // Because this function can be called during startup, when kicking off a URL + // fetch can eat up 20 ms of time, we delay five seconds, which is hopefully + // long enough to be after startup, but still get results back quickly. + // Ideally, instead of this timer, we'd do something like "check if the + // browser is starting up, and if so, come back later", but there is currently + // no function to do this. + static const int kStartFetchDelayMS = 5000; + MessageLoop::current()->PostDelayedTask(FROM_HERE, + runnable_method_factory_.NewRunnableMethod( + &GoogleURLTracker::FinishSleep), + kStartFetchDelayMS); +} + void GoogleURLTracker::FinishSleep() { in_startup_sleep_ = false; StartFetchIfDesirable(); @@ -235,23 +242,23 @@ void GoogleURLTracker::OnURLFetchComplete(const URLFetcher* source, g_browser_process->local_state()->GetString( prefs::kLastPromptedGoogleURL)); need_to_prompt_ = false; - // On the very first run of Chrome, when we've never looked up the URL at all, - // we should just silently switch over to whatever we get immediately. + if (last_prompted_url.is_empty()) { + // On the very first run of Chrome, when we've never looked up the URL at + // all, we should just silently switch over to whatever we get immediately. AcceptGoogleURL(fetched_google_url_); - // Set fetched_google_url_ as an initial value of last prompted URL. - g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL, - fetched_google_url_.spec()); return; } + // If the URL hasn't changed, then whether |need_to_prompt_| is true or false, + // nothing has changed, so just bail. if (fetched_google_url_ == last_prompted_url) return; + if (fetched_google_url_ == google_url_) { // The user came back to their original location after having temporarily // moved. Reset the prompted URL so we'll prompt again if they move again. - g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL, - fetched_google_url_.spec()); + CancelGoogleURL(fetched_google_url_); return; } @@ -263,7 +270,7 @@ void GoogleURLTracker::AcceptGoogleURL(const GURL& new_google_url) { g_browser_process->local_state()->SetString(prefs::kLastKnownGoogleURL, google_url_.spec()); g_browser_process->local_state()->SetString(prefs::kLastPromptedGoogleURL, - new_google_url.spec()); + google_url_.spec()); NotificationService::current()->Notify(NotificationType::GOOGLE_URL_UPDATED, NotificationService::AllSources(), NotificationService::NoDetails()); @@ -283,14 +290,14 @@ void GoogleURLTracker::InfoBarClosed() { } void GoogleURLTracker::RedoSearch() { - // re-do the user's search on the new domain. + // Re-do the user's search on the new domain. DCHECK(controller_); url_canon::Replacements replacements; replacements.SetHost(google_url_.host().data(), url_parse::Component(0, google_url_.host().length())); - search_url_ = search_url_.ReplaceComponents(replacements); - if (search_url_.is_valid()) - controller_->tab_contents()->OpenURL(search_url_, GURL(), CURRENT_TAB, + GURL new_search_url(search_url_.ReplaceComponents(replacements)); + if (new_search_url.is_valid()) + controller_->tab_contents()->OpenURL(new_search_url, GURL(), CURRENT_TAB, PageTransition::GENERATED); } @@ -306,32 +313,18 @@ void GoogleURLTracker::Observe(NotificationType type, StartFetchIfDesirable(); break; - case NotificationType::NAV_ENTRY_PENDING: - controller_ = Source(source).ptr(); - search_url_ = controller_->pending_entry()->url(); - // We don't need to listen NAV_ENTRY_PENDING any more, until another - // search is committed. - registrar_.Remove(this, NotificationType::NAV_ENTRY_PENDING, - NotificationService::AllSources()); - // Start listening for the commit notification. We also need to listen - // for the tab close command since that means the load will never - // commit! - registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, - Source(controller_)); - registrar_.Add(this, NotificationType::TAB_CLOSED, - Source(controller_)); + case NotificationType::NAV_ENTRY_PENDING: { + NavigationController* controller = + Source(source).ptr(); + OnNavigationPending(source, controller->pending_entry()->url()); break; + } case NotificationType::NAV_ENTRY_COMMITTED: - registrar_.RemoveAll(); - DCHECK(controller_); - ShowGoogleURLInfoBarIfNecessary(controller_->tab_contents()); - break; - case NotificationType::TAB_CLOSED: - registrar_.RemoveAll(); - controller_ = NULL; - infobar_ = NULL; + OnNavigationCommittedOrTabClosed( + Source(source).ptr()->tab_contents(), + type.value); break; default: @@ -345,10 +338,39 @@ void GoogleURLTracker::OnIPAddressChanged() { } void GoogleURLTracker::SearchCommitted() { - if (!registrar_.IsEmpty() || (!need_to_prompt_ && !fetcher_.get())) - return; - registrar_.Add(this, NotificationType::NAV_ENTRY_PENDING, - NotificationService::AllSources()); + if (registrar_.IsEmpty() && (need_to_prompt_ || fetcher_.get())) { + // This notification will fire a bit later in the same call chain we're + // currently in. + registrar_.Add(this, NotificationType::NAV_ENTRY_PENDING, + NotificationService::AllSources()); + } +} + +void GoogleURLTracker::OnNavigationPending(const NotificationSource& source, + const GURL& pending_url) { + controller_ = Source(source).ptr(); + search_url_ = pending_url; + registrar_.Remove(this, NotificationType::NAV_ENTRY_PENDING, + NotificationService::AllSources()); + // Start listening for the commit notification. We also need to listen for the + // tab close command since that means the load will never commit. + registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, + Source(controller_)); + registrar_.Add(this, NotificationType::TAB_CLOSED, + Source(controller_)); +} + +void GoogleURLTracker::OnNavigationCommittedOrTabClosed( + TabContents* tab_contents, + NotificationType::Type type) { + registrar_.RemoveAll(); + + if (type == NotificationType::NAV_ENTRY_COMMITTED) { + ShowGoogleURLInfoBarIfNecessary(tab_contents); + } else { + controller_ = NULL; + infobar_ = NULL; + } } void GoogleURLTracker::ShowGoogleURLInfoBarIfNecessary( @@ -356,9 +378,6 @@ void GoogleURLTracker::ShowGoogleURLInfoBarIfNecessary( if (!need_to_prompt_) return; DCHECK(!fetched_google_url_.is_empty()); - DCHECK(infobar_factory_.get()); - infobar_ = infobar_factory_->CreateInfoBar(tab_contents, - this, - fetched_google_url_); + infobar_ = (*infobar_creator_)(tab_contents, this, fetched_google_url_); } diff --git a/chrome/browser/google/google_url_tracker.h b/chrome/browser/google/google_url_tracker.h index b00bd25..590c6df 100644 --- a/chrome/browser/google/google_url_tracker.h +++ b/chrome/browser/google/google_url_tracker.h @@ -10,13 +10,13 @@ #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/common/net/url_fetcher.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "googleurl/src/gurl.h" #include "net/base/network_change_notifier.h" -class InfoBarDelegate; class NavigationController; class PrefService; class TabContents; @@ -39,14 +39,6 @@ class GoogleURLTracker : public URLFetcher::Delegate, public NotificationObserver, public net::NetworkChangeNotifier::Observer { public: - class InfoBarDelegateFactory { - public: - virtual ~InfoBarDelegateFactory() {} - virtual InfoBarDelegate* CreateInfoBar(TabContents* tab_contents, - GoogleURLTracker* google_url_tracker, - const GURL& new_google_url); - }; - // Only the main browser process loop should call this, when setting up // g_browser_process->google_url_tracker_. No code other than the // GoogleURLTracker itself should actually use @@ -89,16 +81,22 @@ class GoogleURLTracker : public URLFetcher::Delegate, void InfoBarClosed(); void RedoSearch(); - NavigationController* controller() const { return controller_; } - private: friend class GoogleURLTrackerTest; + typedef InfoBarDelegate* (*InfobarCreator)(TabContents*, + GoogleURLTracker*, + const GURL&); + // Registers consumer interest in getting an updated URL from the server. // It will be notified as NotificationType::GOOGLE_URL_UPDATED, so the // consumer should observe this notification before calling this. void SetNeedToFetch(); + // Begins the five-second startup sleep period, unless a test has cleared + // |queue_wakeup_task_|. + void QueueWakeupTask(); + // Called when the five second startup sleep has finished. Runs any pending // fetch. void FinishSleep(); @@ -124,10 +122,14 @@ class GoogleURLTracker : public URLFetcher::Delegate, virtual void OnIPAddressChanged(); void SearchCommitted(); - + void OnNavigationPending(const NotificationSource& source, + const GURL& pending_url); + void OnNavigationCommittedOrTabClosed(TabContents* tab_contents, + NotificationType::Type type); void ShowGoogleURLInfoBarIfNecessary(TabContents* tab_contents); NotificationRegistrar registrar_; + InfobarCreator infobar_creator_; // TODO(ukai): GoogleURLTracker should track google domain (e.g. google.co.uk) // rather than URL (e.g. http://www.google.co.uk/), so that user could // configure to use https in search engine templates. @@ -136,6 +138,7 @@ class GoogleURLTracker : public URLFetcher::Delegate, ScopedRunnableMethodFactory runnable_method_factory_; scoped_ptr fetcher_; int fetcher_id_; + bool queue_wakeup_task_; bool in_startup_sleep_; // True if we're in the five-second "no fetching" // period that begins at browser start. bool already_fetched_; // True if we've already fetched a URL once this run; @@ -153,11 +156,39 @@ class GoogleURLTracker : public URLFetcher::Delegate, // matched with current user's default Google URL // nor the last prompted Google URL. NavigationController* controller_; - scoped_ptr infobar_factory_; InfoBarDelegate* infobar_; GURL search_url_; DISALLOW_COPY_AND_ASSIGN(GoogleURLTracker); }; + +// This infobar delegate is declared here (rather than in the .cc file) so test +// code can subclass it. +class GoogleURLTrackerInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + GoogleURLTrackerInfoBarDelegate(TabContents* tab_contents, + GoogleURLTracker* google_url_tracker, + const GURL& new_google_url); + + // ConfirmInfoBarDelegate + virtual bool Accept(); + virtual bool Cancel(); + virtual void InfoBarClosed(); + + protected: + virtual ~GoogleURLTrackerInfoBarDelegate(); + + GoogleURLTracker* google_url_tracker_; + const GURL new_google_url_; + + private: + // ConfirmInfoBarDelegate + virtual string16 GetMessageText() const; + virtual int GetButtons() const; + virtual string16 GetButtonLabel(InfoBarButton button) const; + + DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerInfoBarDelegate); +}; + #endif // CHROME_BROWSER_GOOGLE_GOOGLE_URL_TRACKER_H_ diff --git a/chrome/browser/google/google_url_tracker_unittest.cc b/chrome/browser/google/google_url_tracker_unittest.cc index 937c909..d9fe0c7 100644 --- a/chrome/browser/google/google_url_tracker_unittest.cc +++ b/chrome/browser/google/google_url_tracker_unittest.cc @@ -19,488 +19,468 @@ #include "net/url_request/url_request_unittest.h" #include "testing/gtest/include/gtest/gtest.h" +// TestNotificationObserver --------------------------------------------------- + namespace { class TestNotificationObserver : public NotificationObserver { public: - TestNotificationObserver() : notified_(false) {} - virtual ~TestNotificationObserver() {} + TestNotificationObserver(); + virtual ~TestNotificationObserver(); virtual void Observe(NotificationType type, const NotificationSource& source, - const NotificationDetails& details) { - notified_ = true; - } + const NotificationDetails& details); bool notified() const { return notified_; } - void ClearNotified() { notified_ = false; } + void clear_notified() { notified_ = false; } + private: bool notified_; }; -class TestInfoBar : public InfoBarDelegate { +TestNotificationObserver::TestNotificationObserver() : notified_(false) { +} + +TestNotificationObserver::~TestNotificationObserver() { +} + +void TestNotificationObserver::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + notified_ = true; +} + + +// TestInfoBarDelegate -------------------------------------------------------- + +class TestInfoBarDelegate : public InfoBarDelegate { public: - TestInfoBar(GoogleURLTracker* google_url_tracker, - const GURL& new_google_url) - : InfoBarDelegate(NULL), - google_url_tracker_(google_url_tracker), - new_google_url_(new_google_url) {} - virtual ~TestInfoBar() {} - GoogleURLTracker* google_url_tracker() const { return google_url_tracker_; } - const GURL& new_google_url() const { return new_google_url_; } + TestInfoBarDelegate(GoogleURLTracker* google_url_tracker, + const GURL& new_google_url); + virtual ~TestInfoBarDelegate(); - virtual InfoBar* CreateInfoBar() { return NULL; } + // InfoBarDelegate + virtual InfoBar* CreateInfoBar(); + + GoogleURLTracker* google_url_tracker() const { return google_url_tracker_; } + GURL new_google_url() const { return new_google_url_; } private: GoogleURLTracker* google_url_tracker_; GURL new_google_url_; }; -class TestInfoBarDelegateFactory - : public GoogleURLTracker::InfoBarDelegateFactory { - public: - virtual InfoBarDelegate* CreateInfoBar(TabContents* tab_contents, - GoogleURLTracker* google_url_tracker, - const GURL& new_google_url) { - return new TestInfoBar(google_url_tracker, new_google_url); - } -}; +TestInfoBarDelegate::TestInfoBarDelegate(GoogleURLTracker* google_url_tracker, + const GURL& new_google_url) + : InfoBarDelegate(NULL), + google_url_tracker_(google_url_tracker), + new_google_url_(new_google_url) { +} + +TestInfoBarDelegate::~TestInfoBarDelegate() { +} + +InfoBar* TestInfoBarDelegate::CreateInfoBar() { + return NULL; +} -} // anonymous namespace +InfoBarDelegate* CreateTestInfobar( + TabContents* tab_contents, + GoogleURLTracker* google_url_tracker, + const GURL& new_google_url) { + return new TestInfoBarDelegate(google_url_tracker, new_google_url); +} + +} // namespace + + +// GoogleURLTrackerTest ------------------------------------------------------- class GoogleURLTrackerTest : public testing::Test { protected: - GoogleURLTrackerTest() - : message_loop_(NULL), - io_thread_(NULL), - original_default_request_context_(NULL) { - } + GoogleURLTrackerTest(); + virtual ~GoogleURLTrackerTest(); + + // testing::Test + virtual void SetUp(); + virtual void TearDown(); + + void CreateRequestContext(); + TestURLFetcher* GetFetcherByID(int expected_id); + void MockSearchDomainCheckResponse(int expected_id, + const std::string& domain); + void RequestServerCheck(); + void FinishSleep(); + void NotifyIPAddressChanged(); + GURL GetFetchedGoogleURL(); + void SetGoogleURL(const GURL& url); + void SetLastPromptedGoogleURL(const GURL& url); + GURL GetLastPromptedGoogleURL(); + void SearchCommitted(const GURL& search_url); + void NavEntryCommitted(); + bool InfoBarIsShown(); + GURL GetInfoBarShowingURL(); + void AcceptGoogleURL(); + void CancelGoogleURL(); + void InfoBarClosed(); + void ExpectDefaultURLs(); + + scoped_ptr observer_; - void SetUp() { - original_default_request_context_ = Profile::GetDefaultRequestContext(); - Profile::set_default_request_context(NULL); - message_loop_ = new MessageLoop(MessageLoop::TYPE_IO); - io_thread_ = new BrowserThread(BrowserThread::IO, message_loop_); - network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); - testing_profile_.reset(new TestingProfile); - TestingBrowserProcess* testing_browser_process = - static_cast(g_browser_process); - PrefService* pref_service = testing_profile_->GetPrefs(); - testing_browser_process->SetPrefService(pref_service); - testing_browser_process->SetGoogleURLTracker(new GoogleURLTracker); - - URLFetcher::set_factory(&fetcher_factory_); - observer_.reset(new TestNotificationObserver); - g_browser_process->google_url_tracker()->infobar_factory_.reset( - new TestInfoBarDelegateFactory); - } + private: + MessageLoop* message_loop_; + BrowserThread* io_thread_; + scoped_ptr network_change_notifier_; + scoped_ptr testing_profile_; - void TearDown() { - URLFetcher::set_factory(NULL); - TestingBrowserProcess* testing_browser_process = - static_cast(g_browser_process); - testing_browser_process->SetGoogleURLTracker(NULL); - testing_browser_process->SetPrefService(NULL); - testing_profile_.reset(); - network_change_notifier_.reset(); - delete io_thread_; - delete message_loop_; - Profile::set_default_request_context(original_default_request_context_); - original_default_request_context_ = NULL; - } + TestURLFetcherFactory fetcher_factory_; + NotificationRegistrar registrar_; - void CreateRequestContext() { - testing_profile_->CreateRequestContext(); - Profile::set_default_request_context(testing_profile_->GetRequestContext()); - NotificationService::current()->Notify( - NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, - NotificationService::AllSources(), NotificationService::NoDetails()); - } + URLRequestContextGetter* original_default_request_context_; +}; - TestURLFetcher* GetFetcherByID(int expected_id) { - return fetcher_factory_.GetFetcherByID(expected_id); - } +GoogleURLTrackerTest::GoogleURLTrackerTest() + : observer_(new TestNotificationObserver), + message_loop_(NULL), + io_thread_(NULL), + original_default_request_context_(NULL) { +} - void MockSearchDomainCheckResponse( - int expected_id, const std::string& domain) { - TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(expected_id); - ASSERT_TRUE(fetcher); - fetcher->delegate()->OnURLFetchComplete( - fetcher, - GURL(GoogleURLTracker::kSearchDomainCheckURL), - URLRequestStatus(), - 200, - ResponseCookies(), - domain); - MessageLoop::current()->RunAllPending(); - } +GoogleURLTrackerTest::~GoogleURLTrackerTest() { +} + +void GoogleURLTrackerTest::SetUp() { + original_default_request_context_ = Profile::GetDefaultRequestContext(); + Profile::set_default_request_context(NULL); + message_loop_ = new MessageLoop(MessageLoop::TYPE_IO); + io_thread_ = new BrowserThread(BrowserThread::IO, message_loop_); + network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); + testing_profile_.reset(new TestingProfile); + TestingBrowserProcess* testing_browser_process = + static_cast(g_browser_process); + PrefService* pref_service = testing_profile_->GetPrefs(); + testing_browser_process->SetPrefService(pref_service); + GoogleURLTracker* tracker = new GoogleURLTracker; + tracker->queue_wakeup_task_ = false; + MessageLoop::current()->RunAllPending(); + testing_browser_process->SetGoogleURLTracker(tracker); + + URLFetcher::set_factory(&fetcher_factory_); + g_browser_process->google_url_tracker()->infobar_creator_ = + &CreateTestInfobar; +} - void RequestServerCheck() { +void GoogleURLTrackerTest::TearDown() { + URLFetcher::set_factory(NULL); + TestingBrowserProcess* testing_browser_process = + static_cast(g_browser_process); + testing_browser_process->SetGoogleURLTracker(NULL); + testing_browser_process->SetPrefService(NULL); + testing_profile_.reset(); + network_change_notifier_.reset(); + delete io_thread_; + delete message_loop_; + Profile::set_default_request_context(original_default_request_context_); + original_default_request_context_ = NULL; +} + +void GoogleURLTrackerTest::CreateRequestContext() { + testing_profile_->CreateRequestContext(); + Profile::set_default_request_context(testing_profile_->GetRequestContext()); + NotificationService::current()->Notify( + NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, + NotificationService::AllSources(), NotificationService::NoDetails()); +} + +TestURLFetcher* GoogleURLTrackerTest::GetFetcherByID(int expected_id) { + return fetcher_factory_.GetFetcherByID(expected_id); +} + +void GoogleURLTrackerTest::MockSearchDomainCheckResponse( + int expected_id, + const std::string& domain) { + TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(expected_id); + if (!fetcher) + return; + fetcher->delegate()->OnURLFetchComplete(fetcher, + GURL(GoogleURLTracker::kSearchDomainCheckURL), URLRequestStatus(), 200, + ResponseCookies(), domain); + // At this point, |fetcher| is deleted. + MessageLoop::current()->RunAllPending(); +} + +void GoogleURLTrackerTest::RequestServerCheck() { + if (!registrar_.IsRegistered(observer_.get(), + NotificationType::GOOGLE_URL_UPDATED, + NotificationService::AllSources())) { registrar_.Add(observer_.get(), NotificationType::GOOGLE_URL_UPDATED, NotificationService::AllSources()); - GoogleURLTracker::RequestServerCheck(); - MessageLoop::current()->RunAllPending(); - } - - void FinishSleep() { - g_browser_process->google_url_tracker()->FinishSleep(); - MessageLoop::current()->RunAllPending(); } + GoogleURLTracker::RequestServerCheck(); + MessageLoop::current()->RunAllPending(); +} - void NotifyIPAddressChanged() { - net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - MessageLoop::current()->RunAllPending(); - } +void GoogleURLTrackerTest::FinishSleep() { + g_browser_process->google_url_tracker()->FinishSleep(); + MessageLoop::current()->RunAllPending(); +} - GURL GetFetchedGoogleURL() { - return g_browser_process->google_url_tracker()->fetched_google_url_; - } +void GoogleURLTrackerTest::NotifyIPAddressChanged() { + net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + MessageLoop::current()->RunAllPending(); +} - void SetGoogleURL(const GURL& url) { - g_browser_process->google_url_tracker()->google_url_ = url; - } +GURL GoogleURLTrackerTest::GetFetchedGoogleURL() { + return g_browser_process->google_url_tracker()->fetched_google_url_; +} - void SetLastPromptedGoogleURL(const GURL& url) { - g_browser_process->local_state()->SetString( - prefs::kLastPromptedGoogleURL, url.spec()); - } +void GoogleURLTrackerTest::SetGoogleURL(const GURL& url) { + g_browser_process->google_url_tracker()->google_url_ = url; +} - GURL GetLastPromptedGoogleURL() { - return GURL(g_browser_process->local_state()->GetString( - prefs::kLastPromptedGoogleURL)); - } +void GoogleURLTrackerTest::SetLastPromptedGoogleURL(const GURL& url) { + g_browser_process->local_state()->SetString( + prefs::kLastPromptedGoogleURL, url.spec()); +} - void SearchCommitted(const GURL& search_url) { - GoogleURLTracker* google_url_tracker = - g_browser_process->google_url_tracker(); +GURL GoogleURLTrackerTest::GetLastPromptedGoogleURL() { + return GURL(g_browser_process->local_state()->GetString( + prefs::kLastPromptedGoogleURL)); +} - google_url_tracker->SearchCommitted(); - // GoogleURLTracker wait for NAV_ENTRY_PENDING. - // In NAV_ENTRY_PENDING, it will set search_url_. +void GoogleURLTrackerTest::SearchCommitted(const GURL& search_url) { + GoogleURLTracker* google_url_tracker = + g_browser_process->google_url_tracker(); + google_url_tracker->SearchCommitted(); + if (google_url_tracker->registrar_.IsRegistered(google_url_tracker, + NotificationType::NAV_ENTRY_PENDING, + NotificationService::AllSources())) google_url_tracker->search_url_ = search_url; - } - - void NavEntryCommitted() { - GoogleURLTracker* google_url_tracker = - g_browser_process->google_url_tracker(); - google_url_tracker->ShowGoogleURLInfoBarIfNecessary(NULL); - } +} - bool InfoBarIsShown() { - return (g_browser_process->google_url_tracker()->infobar_ != NULL); - } +void GoogleURLTrackerTest::NavEntryCommitted() { + GoogleURLTracker* google_url_tracker = + g_browser_process->google_url_tracker(); + google_url_tracker->ShowGoogleURLInfoBarIfNecessary(NULL); +} - GURL GetInfoBarShowingURL() { - TestInfoBar* infobar = static_cast( - g_browser_process->google_url_tracker()->infobar_); - return infobar->new_google_url(); - } +bool GoogleURLTrackerTest::InfoBarIsShown() { + return (g_browser_process->google_url_tracker()->infobar_ != NULL); +} - void AcceptGoogleURL() { - TestInfoBar* infobar = static_cast( - g_browser_process->google_url_tracker()->infobar_); - ASSERT_TRUE(infobar); - ASSERT_TRUE(infobar->google_url_tracker()); - infobar->google_url_tracker()->AcceptGoogleURL(infobar->new_google_url()); - } +GURL GoogleURLTrackerTest::GetInfoBarShowingURL() { + TestInfoBarDelegate* infobar = static_cast( + g_browser_process->google_url_tracker()->infobar_); + return infobar->new_google_url(); +} - void CancelGoogleURL() { - TestInfoBar* infobar = static_cast( - g_browser_process->google_url_tracker()->infobar_); - ASSERT_TRUE(infobar); - ASSERT_TRUE(infobar->google_url_tracker()); - infobar->google_url_tracker()->CancelGoogleURL(infobar->new_google_url()); - } +void GoogleURLTrackerTest::AcceptGoogleURL() { + TestInfoBarDelegate* infobar = static_cast( + g_browser_process->google_url_tracker()->infobar_); + ASSERT_TRUE(infobar); + ASSERT_TRUE(infobar->google_url_tracker()); + infobar->google_url_tracker()->AcceptGoogleURL(infobar->new_google_url()); +} - void InfoBarClosed() { - TestInfoBar* infobar = static_cast( - g_browser_process->google_url_tracker()->infobar_); - ASSERT_TRUE(infobar); - ASSERT_TRUE(infobar->google_url_tracker()); - infobar->google_url_tracker()->InfoBarClosed(); - delete infobar; - } +void GoogleURLTrackerTest::CancelGoogleURL() { + TestInfoBarDelegate* infobar = static_cast( + g_browser_process->google_url_tracker()->infobar_); + ASSERT_TRUE(infobar); + ASSERT_TRUE(infobar->google_url_tracker()); + infobar->google_url_tracker()->CancelGoogleURL(infobar->new_google_url()); +} - void ExpectDefaultURLs() { - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL(), GetFetchedGoogleURL()); - } +void GoogleURLTrackerTest::InfoBarClosed() { + TestInfoBarDelegate* infobar = static_cast( + g_browser_process->google_url_tracker()->infobar_); + ASSERT_TRUE(infobar); + ASSERT_TRUE(infobar->google_url_tracker()); + infobar->google_url_tracker()->InfoBarClosed(); + delete infobar; +} - private: - MessageLoop* message_loop_; - BrowserThread* io_thread_; - scoped_ptr network_change_notifier_; - scoped_ptr testing_profile_; +void GoogleURLTrackerTest::ExpectDefaultURLs() { + EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), + GoogleURLTracker::GoogleURL()); + EXPECT_EQ(GURL(), GetFetchedGoogleURL()); +} - TestURLFetcherFactory fetcher_factory_; - NotificationRegistrar registrar_; - scoped_ptr observer_; - URLRequestContextGetter* original_default_request_context_; -}; +// Tests ---------------------------------------------------------------------- -TEST_F(GoogleURLTrackerTest, StartupSleepFinish) { +TEST_F(GoogleURLTrackerTest, DontFetchWhenNoOneRequestsCheck) { CreateRequestContext(); + ExpectDefaultURLs(); + FinishSleep(); + // No one called RequestServerCheck() so nothing should have happened. + EXPECT_FALSE(GetFetcherByID(0)); + ExpectDefaultURLs(); + EXPECT_FALSE(observer_->notified()); +} +TEST_F(GoogleURLTrackerTest, UpdateOnFirstRun) { + CreateRequestContext(); RequestServerCheck(); EXPECT_FALSE(GetFetcherByID(0)); ExpectDefaultURLs(); + EXPECT_FALSE(observer_->notified()); FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.uk"); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - // GoogleURL is updated, becase it was not the last prompted URL. + // GoogleURL should be updated, becase there was no last prompted URL. EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_TRUE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, StartupSleepFinishWithLastPrompted) { +TEST_F(GoogleURLTrackerTest, DontUpdateWhenUnchanged) { CreateRequestContext(); SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/")); RequestServerCheck(); EXPECT_FALSE(GetFetcherByID(0)); ExpectDefaultURLs(); + EXPECT_FALSE(observer_->notified()); FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.uk"); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - // GoogleURL should not be updated. + // GoogleURL should not be updated, because the fetched and prompted URLs + // match. EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), GoogleURLTracker::GoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, StartupSleepFinishNoObserver) { +TEST_F(GoogleURLTrackerTest, UpdatePromptedURLOnReturnToPreviousLocation) { CreateRequestContext(); - - ExpectDefaultURLs(); - + SetLastPromptedGoogleURL(GURL("http://www.google.co.jp/")); + SetGoogleURL(GURL("http://www.google.co.uk/")); + RequestServerCheck(); FinishSleep(); - EXPECT_FALSE(GetFetcherByID(0)); - - ExpectDefaultURLs(); + MockSearchDomainCheckResponse(0, ".google.co.uk"); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, MonitorNetworkChange) { +TEST_F(GoogleURLTrackerTest, RefetchOnIPAddressChange) { CreateRequestContext(); - RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.uk"); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - // GoogleURL is updated, becase it was not the last prompted URL. EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_TRUE(observer_->notified()); + observer_->clear_notified(); NotifyIPAddressChanged(); MockSearchDomainCheckResponse(1, ".google.co.in"); - EXPECT_EQ(GURL("http://www.google.co.in/"), GetFetchedGoogleURL()); - // Don't update GoogleURL. + // Just fetching a new URL shouldn't reset things without a prompt. EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, MonitorNetworkChangeNoObserver) { +TEST_F(GoogleURLTrackerTest, DontRefetchWhenNoOneRequestsCheck) { CreateRequestContext(); - - ExpectDefaultURLs(); - FinishSleep(); NotifyIPAddressChanged(); + // No one called RequestServerCheck() so nothing should have happened. EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, MonitorNetworkChangeAndObserverRegister) { +TEST_F(GoogleURLTrackerTest, FetchOnLateRequest) { CreateRequestContext(); - - ExpectDefaultURLs(); - FinishSleep(); NotifyIPAddressChanged(); - EXPECT_FALSE(GetFetcherByID(0)); - - ExpectDefaultURLs(); RequestServerCheck(); + // The first request for a check should trigger a fetch if it hasn't happened + // already. MockSearchDomainCheckResponse(0, ".google.co.uk"); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_TRUE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, NoSearchCommitedAndPromptedNotChanged) { +TEST_F(GoogleURLTrackerTest, SearchingDoesNothingIfNoNeedToPrompt) { CreateRequestContext(); - SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/")); RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - FinishSleep(); - MockSearchDomainCheckResponse(0, ".google.co.jp"); + MockSearchDomainCheckResponse(0, ".google.co.uk"); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); + EXPECT_TRUE(observer_->notified()); + observer_->clear_notified(); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetFetchedGoogleURL()); + SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); + NavEntryCommitted(); + EXPECT_FALSE(InfoBarIsShown()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); + EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, SearchCommitedAndUserCloseInfoBar) { +TEST_F(GoogleURLTrackerTest, InfobarClosed) { CreateRequestContext(); SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/")); - - ExpectDefaultURLs(); - RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.jp"); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); - SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); NavEntryCommitted(); - EXPECT_TRUE(InfoBarIsShown()); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetInfoBarShowingURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); InfoBarClosed(); EXPECT_FALSE(InfoBarIsShown()); EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), GoogleURLTracker::GoogleURL()); EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, SearchCommitedAndUserSayNo) { +TEST_F(GoogleURLTrackerTest, InfobarRefused) { CreateRequestContext(); SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/")); - - ExpectDefaultURLs(); - RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.jp"); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); - SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); NavEntryCommitted(); - EXPECT_TRUE(InfoBarIsShown()); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetInfoBarShowingURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); CancelGoogleURL(); - EXPECT_TRUE(InfoBarIsShown()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL()); - InfoBarClosed(); EXPECT_FALSE(InfoBarIsShown()); EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), GoogleURLTracker::GoogleURL()); EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL()); + EXPECT_FALSE(observer_->notified()); } -TEST_F(GoogleURLTrackerTest, SearchCommitedAndUserSayYes) { +TEST_F(GoogleURLTrackerTest, InfobarAccepted) { CreateRequestContext(); SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/")); - - ExpectDefaultURLs(); - RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - FinishSleep(); MockSearchDomainCheckResponse(0, ".google.co.jp"); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); - SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); NavEntryCommitted(); - EXPECT_TRUE(InfoBarIsShown()); - EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), - GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetInfoBarShowingURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); AcceptGoogleURL(); - EXPECT_TRUE(InfoBarIsShown()); - EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL()); - InfoBarClosed(); EXPECT_FALSE(InfoBarIsShown()); EXPECT_EQ(GURL("http://www.google.co.jp/"), GoogleURLTracker::GoogleURL()); EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL()); -} - -TEST_F(GoogleURLTrackerTest, InitialUpdate) { - CreateRequestContext(); - ExpectDefaultURLs(); - EXPECT_EQ(GURL(), GetLastPromptedGoogleURL()); - - RequestServerCheck(); - EXPECT_FALSE(GetFetcherByID(0)); - ExpectDefaultURLs(); - EXPECT_EQ(GURL(), GetLastPromptedGoogleURL()); - - FinishSleep(); - MockSearchDomainCheckResponse(0, ".google.co.uk"); - - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); - - SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); - NavEntryCommitted(); - - EXPECT_FALSE(InfoBarIsShown()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); -} - -TEST_F(GoogleURLTrackerTest, UpdatePromptedURLWhenBack) { - CreateRequestContext(); - SetLastPromptedGoogleURL(GURL("http://www.google.co.jp/")); - SetGoogleURL(GURL("http://www.google.co.uk/")); - - RequestServerCheck(); - FinishSleep(); - MockSearchDomainCheckResponse(0, ".google.co.uk"); - - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); - - SearchCommitted(GURL("http://www.google.co.uk/search?q=test")); - NavEntryCommitted(); - - EXPECT_FALSE(InfoBarIsShown()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL()); - EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL()); + EXPECT_TRUE(observer_->notified()); } diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc index 171c404..0e4166a 100644 --- a/chrome/browser/gpu_process_host.cc +++ b/chrome/browser/gpu_process_host.cc @@ -13,7 +13,6 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/renderer_host/resource_message_filter.h" -#include "chrome/common/child_process_logging.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/gpu_info.h" #include "chrome/common/gpu_messages.h" @@ -49,6 +48,11 @@ class RouteOnUIThreadTask : public Task { // initialized, the IO thread. static GpuProcessHost* sole_instance_ = NULL; +void RouteOnUIThread(const IPC::Message& message) { + BrowserThread::PostTask(BrowserThread::UI, + FROM_HERE, + new RouteOnUIThreadTask(message)); +} } // anonymous namespace GpuProcessHost::GpuProcessHost() @@ -123,12 +127,16 @@ bool GpuProcessHost::Init() { // static GpuProcessHost* GpuProcessHost::Get() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (sole_instance_ == NULL) sole_instance_ = new GpuProcessHost(); return sole_instance_; } bool GpuProcessHost::Send(IPC::Message* msg) { + DCHECK(CalledOnValidThread()); + if (!EnsureInitialized()) return false; @@ -136,34 +144,34 @@ bool GpuProcessHost::Send(IPC::Message* msg) { } void GpuProcessHost::OnMessageReceived(const IPC::Message& message) { - if (message.routing_id() == MSG_ROUTING_CONTROL) { + DCHECK(CalledOnValidThread()); + + if (message.routing_id() == MSG_ROUTING_CONTROL) OnControlMessageReceived(message); - } else { - // Need to transfer this message to the UI thread and the - // GpuProcessHostUIShim for dispatching via its message router. - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, - new RouteOnUIThreadTask(message)); - } + else + RouteOnUIThread(message); } void GpuProcessHost::EstablishGpuChannel(int renderer_id, ResourceMessageFilter* filter) { + DCHECK(CalledOnValidThread()); + if (Send(new GpuMsg_EstablishChannel(renderer_id))) { sent_requests_.push(ChannelRequest(filter)); } else { - ReplyToRenderer(IPC::ChannelHandle(), GPUInfo(), filter); + SendEstablishChannelReply(IPC::ChannelHandle(), GPUInfo(), filter); } } void GpuProcessHost::Synchronize(IPC::Message* reply, ResourceMessageFilter* filter) { - queued_synchronization_replies_.push(SynchronizationRequest(reply, filter)); - Send(new GpuMsg_Synchronize()); -} + DCHECK(CalledOnValidThread()); -GPUInfo GpuProcessHost::gpu_info() const { - return gpu_info_; + if (Send(new GpuMsg_Synchronize())) { + queued_synchronization_replies_.push(SynchronizationRequest(reply, filter)); + } else { + SendSynchronizationReply(reply, filter); + } } GpuProcessHost::ChannelRequest::ChannelRequest(ResourceMessageFilter* filter) @@ -182,11 +190,11 @@ GpuProcessHost::SynchronizationRequest::SynchronizationRequest( GpuProcessHost::SynchronizationRequest::~SynchronizationRequest() {} void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) { + DCHECK(CalledOnValidThread()); + IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished) IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, OnSynchronizeReply) - IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected, - OnGraphicsInfoCollected) #if defined(OS_LINUX) IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_GetViewXID, OnGetViewXID) #elif defined(OS_MACOSX) @@ -195,7 +203,10 @@ void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) #endif - IPC_MESSAGE_UNHANDLED_ERROR() + // If the IO thread does not handle the message then automatically route it + // to the UI thread. The UI thread will report an error if it does not + // handle it. + IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message)) IPC_END_MESSAGE_MAP() } @@ -203,23 +214,17 @@ void GpuProcessHost::OnChannelEstablished( const IPC::ChannelHandle& channel_handle, const GPUInfo& gpu_info) { const ChannelRequest& request = sent_requests_.front(); - ReplyToRenderer(channel_handle, gpu_info, request.filter); + SendEstablishChannelReply(channel_handle, gpu_info, request.filter); sent_requests_.pop(); - gpu_info_ = gpu_info; - child_process_logging::SetGpuInfo(gpu_info); } void GpuProcessHost::OnSynchronizeReply() { const SynchronizationRequest& request = queued_synchronization_replies_.front(); - request.filter->Send(request.reply); + SendSynchronizationReply(request.reply, request.filter); queued_synchronization_replies_.pop(); } -void GpuProcessHost::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { - gpu_info_ = gpu_info; -} - #if defined(OS_LINUX) namespace { @@ -344,7 +349,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( } #endif -void GpuProcessHost::ReplyToRenderer( +void GpuProcessHost::SendEstablishChannelReply( const IPC::ChannelHandle& channel, const GPUInfo& gpu_info, ResourceMessageFilter* filter) { @@ -357,6 +362,13 @@ void GpuProcessHost::ReplyToRenderer( filter->Send(message); } +// Sends the response for synchronization request to the renderer. +void GpuProcessHost::SendSynchronizationReply( + IPC::Message* reply, + ResourceMessageFilter* filter) { + filter->Send(reply); +} + URLRequestContext* GpuProcessHost::GetRequestContext( uint32 request_id, const ViewHostMsg_Resource_Request& request_data) { @@ -366,3 +378,9 @@ URLRequestContext* GpuProcessHost::GetRequestContext( bool GpuProcessHost::CanShutdown() { return true; } + +void GpuProcessHost::OnProcessCrashed() { + // TODO(alokp): Update gpu process crash rate. + BrowserChildProcessHost::OnProcessCrashed(); +} + diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h index f9aa06f..5def042 100644 --- a/chrome/browser/gpu_process_host.h +++ b/chrome/browser/gpu_process_host.h @@ -9,9 +9,9 @@ #include #include "base/basictypes.h" +#include "base/non_thread_safe.h" #include "base/ref_counted.h" #include "chrome/browser/browser_child_process_host.h" -#include "chrome/common/gpu_info.h" #include "gfx/native_widget_types.h" struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params; @@ -23,15 +23,11 @@ struct ChannelHandle; class Message; } -class GpuProcessHost : public BrowserChildProcessHost { +class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe { public: // Getter for the singleton. This will return NULL on failure. static GpuProcessHost* Get(); - // Shutdown routine, which should only be called upon process - // termination. - static void Shutdown(); - virtual bool Send(IPC::Message* msg); // IPC::Channel::Listener implementation. @@ -48,9 +44,6 @@ class GpuProcessHost : public BrowserChildProcessHost { void Synchronize(IPC::Message* reply, ResourceMessageFilter* filter); - // Return the stored gpu_info as this class the - // browser's point of contact with the gpu - GPUInfo gpu_info() const; private: // Used to queue pending channel requests. struct ChannelRequest { @@ -87,7 +80,6 @@ class GpuProcessHost : public BrowserChildProcessHost { void OnChannelEstablished(const IPC::ChannelHandle& channel_handle, const GPUInfo& gpu_info); void OnSynchronizeReply(); - void OnGraphicsInfoCollected(const GPUInfo& gpu_info); #if defined(OS_LINUX) void OnGetViewXID(gfx::NativeViewId id, IPC::Message* reply_msg); #elif defined(OS_MACOSX) @@ -99,9 +91,13 @@ class GpuProcessHost : public BrowserChildProcessHost { uint64 surface_id); #endif - void ReplyToRenderer(const IPC::ChannelHandle& channel, - const GPUInfo& gpu_info, - ResourceMessageFilter* filter); + // Sends the response for establish channel request to the renderer. + void SendEstablishChannelReply(const IPC::ChannelHandle& channel, + const GPUInfo& gpu_info, + ResourceMessageFilter* filter); + // Sends the response for synchronization request to the renderer. + void SendSynchronizationReply(IPC::Message* reply, + ResourceMessageFilter* filter); // ResourceDispatcherHost::Receiver implementation: virtual URLRequestContext* GetRequestContext( @@ -109,13 +105,11 @@ class GpuProcessHost : public BrowserChildProcessHost { const ViewHostMsg_Resource_Request& request_data); virtual bool CanShutdown(); + virtual void OnProcessCrashed(); bool initialized_; bool initialized_successfully_; - // GPUInfo class used for collecting gpu stats - GPUInfo gpu_info_; - // These are the channel requests that we have already sent to // the GPU process, but haven't heard back about yet. std::queue sent_requests_; diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index 3d1223d..2e3a531 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -6,6 +6,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/gpu_process_host.h" +#include "chrome/common/child_process_logging.h" #include "chrome/common/gpu_messages.h" // Tasks used by this file @@ -33,10 +34,12 @@ GpuProcessHostUIShim::~GpuProcessHostUIShim() { // static GpuProcessHostUIShim* GpuProcessHostUIShim::Get() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return Singleton::get(); } bool GpuProcessHostUIShim::Send(IPC::Message* msg) { + DCHECK(CalledOnValidThread()); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, new SendOnIOThreadTask(msg)); @@ -44,24 +47,32 @@ bool GpuProcessHostUIShim::Send(IPC::Message* msg) { } int32 GpuProcessHostUIShim::GetNextRoutingId() { + DCHECK(CalledOnValidThread()); return ++last_routing_id_; } void GpuProcessHostUIShim::AddRoute(int32 routing_id, IPC::Channel::Listener* listener) { + DCHECK(CalledOnValidThread()); router_.AddRoute(routing_id, listener); } void GpuProcessHostUIShim::RemoveRoute(int32 routing_id) { + DCHECK(CalledOnValidThread()); router_.RemoveRoute(routing_id); } void GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { - router_.RouteMessage(message); + DCHECK(CalledOnValidThread()); + + if (message.routing_id() == MSG_ROUTING_CONTROL) + OnControlMessageReceived(message); + else + router_.RouteMessage(message); } void GpuProcessHostUIShim::CollectGraphicsInfoAsynchronously() { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(CalledOnValidThread()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -69,7 +80,7 @@ void GpuProcessHostUIShim::CollectGraphicsInfoAsynchronously() { } void GpuProcessHostUIShim::SendAboutGpuCrash() { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(CalledOnValidThread()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -77,9 +88,30 @@ void GpuProcessHostUIShim::SendAboutGpuCrash() { } void GpuProcessHostUIShim::SendAboutGpuHang() { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(CalledOnValidThread()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, new SendOnIOThreadTask(new GpuMsg_Hang())); } + +const GPUInfo& GpuProcessHostUIShim::gpu_info() const { + DCHECK(CalledOnValidThread()); + return gpu_info_; +} + +void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { + gpu_info_ = gpu_info; + child_process_logging::SetGpuInfo(gpu_info); +} + +void GpuProcessHostUIShim::OnControlMessageReceived( + const IPC::Message& message) { + DCHECK(CalledOnValidThread()); + + IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message) + IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected, + OnGraphicsInfoCollected) + IPC_MESSAGE_UNHANDLED_ERROR() + IPC_END_MESSAGE_MAP() +} diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index f43b41d..d77c783 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -11,13 +11,16 @@ // portion of this class, the GpuProcessHost, is responsible for // shuttling messages between the browser and GPU processes. +#include "base/non_thread_safe.h" #include "base/singleton.h" +#include "chrome/common/gpu_info.h" #include "chrome/common/message_router.h" #include "ipc/ipc_channel.h" #include "gfx/native_widget_types.h" class GpuProcessHostUIShim : public IPC::Channel::Sender, - public IPC::Channel::Listener { + public IPC::Channel::Listener, + public NonThreadSafe { public: // Getter for the singleton. This will return NULL on failure. static GpuProcessHostUIShim* Get(); @@ -48,14 +51,24 @@ class GpuProcessHostUIShim : public IPC::Channel::Sender, // Useful for testing. void SendAboutGpuHang(); + // Return all known information about the GPU. + const GPUInfo& gpu_info() const; + private: friend struct DefaultSingletonTraits; GpuProcessHostUIShim(); virtual ~GpuProcessHostUIShim(); + // Message handlers. + void OnGraphicsInfoCollected(const GPUInfo& gpu_info); + + void OnControlMessageReceived(const IPC::Message& message); + int last_routing_id_; + GPUInfo gpu_info_; + MessageRouter router_; }; diff --git a/chrome/browser/gtk/back_forward_button_gtk.cc b/chrome/browser/gtk/back_forward_button_gtk.cc index 29d6ddd..669b9d7 100644 --- a/chrome/browser/gtk/back_forward_button_gtk.cc +++ b/chrome/browser/gtk/back_forward_button_gtk.cc @@ -10,11 +10,11 @@ #include "base/message_loop.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/back_forward_menu_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc index 0580b54..4784b2a 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk.cc @@ -7,13 +7,13 @@ #include #include "app/gtk_dnd_util.h" +#include "app/slide_animation.h" #include "app/resource_bundle.h" #include "base/utf_string_conversions.h" #include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/bookmark_menu_controller_gtk.h" #include "chrome/browser/gtk/bookmark_tree_model.h" #include "chrome/browser/gtk/bookmark_utils_gtk.h" @@ -38,6 +38,7 @@ #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "gfx/canvas_skia_paint.h" diff --git a/chrome/browser/gtk/bookmark_bar_gtk.h b/chrome/browser/gtk/bookmark_bar_gtk.h index 2e7f985..0939c70 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.h +++ b/chrome/browser/gtk/bookmark_bar_gtk.h @@ -10,8 +10,8 @@ #include +#include "app/animation_delegate.h" #include "app/gtk_signal.h" -#include "app/slide_animation.h" #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" #include "chrome/browser/bookmarks/bookmark_context_menu_controller.h" @@ -34,6 +34,7 @@ class GtkThemeProvider; class MenuGtk; class PageNavigator; class Profile; +class SlideAnimation; class TabstripOriginProvider; class BookmarkBarGtk : public AnimationDelegate, diff --git a/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc b/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc index 0fc9101..cb027a8 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk_interactive_uitest.cc @@ -4,10 +4,10 @@ #include -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/gtk/view_id_util.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "net/test/test_server.h" @@ -22,12 +22,12 @@ void OnClicked(GtkWidget* widget, bool* clicked_bit) { } // namespace -class BookmarkBarGtkBrowserTest : public InProcessBrowserTest { +class BookmarkBarGtkInteractiveUITest : public InProcessBrowserTest { }; // Makes sure that when you switch back to an NTP with an active findbar, // the findbar is above the floating bookmark bar. -IN_PROC_BROWSER_TEST_F(BookmarkBarGtkBrowserTest, FindBarTest) { +IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, FindBarTest) { ASSERT_TRUE(test_server()->Start()); // Create new tab; open findbar. @@ -52,7 +52,7 @@ IN_PROC_BROWSER_TEST_F(BookmarkBarGtkBrowserTest, FindBarTest) { } // Makes sure that you can click on the floating bookmark bar. -IN_PROC_BROWSER_TEST_F(BookmarkBarGtkBrowserTest, ClickOnFloatingTest) { +IN_PROC_BROWSER_TEST_F(BookmarkBarGtkInteractiveUITest, ClickOnFloatingTest) { ASSERT_TRUE(test_server()->Start()); GtkWidget* other_bookmarks = diff --git a/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc b/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc index fa04251..074e8fc 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk_unittest.cc @@ -4,14 +4,14 @@ #include "chrome/browser/gtk/bookmark_bar_gtk.h" +#include "base/task.h" #include "base/utf_string_conversions.h" #include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/gtk/tabstrip_origin_provider.h" -#include "base/task.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" // Dummy implementation that's good enough for the tests; we don't test // rendering here so all we need is a non-NULL object. diff --git a/chrome/browser/gtk/bookmark_editor_gtk.cc b/chrome/browser/gtk/bookmark_editor_gtk.cc index 5aafc6c..1ad5857 100644 --- a/chrome/browser/gtk/bookmark_editor_gtk.cc +++ b/chrome/browser/gtk/bookmark_editor_gtk.cc @@ -7,6 +7,7 @@ #include #include "app/l10n_util.h" +#include "app/menus/simple_menu_model.h" #include "base/basictypes.h" #include "base/logging.h" #include "base/string_util.h" @@ -21,11 +22,18 @@ #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/profile.h" #include "gfx/gtk_util.h" +#include "gfx/point.h" #include "googleurl/src/gurl.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" +#if defined(TOOLKIT_VIEWS) +#include "views/controls/menu/menu_2.h" +#else +#include "chrome/browser/gtk/menu_gtk.h" +#endif + namespace { // Background color of text field when URL is invalid. @@ -37,6 +45,143 @@ static const int kTreeHeight = 150; } // namespace +class BookmarkEditorGtk::ContextMenuController + : public menus::SimpleMenuModel::Delegate { + public: + explicit ContextMenuController(BookmarkEditorGtk* editor) + : editor_(editor), + running_menu_for_root_(false) { + menu_model_.reset(new menus::SimpleMenuModel(this)); + menu_model_->AddItemWithStringId(COMMAND_EDIT, IDS_EDIT); + menu_model_->AddItemWithStringId( + COMMAND_NEW_FOLDER, + IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM); +#if defined(TOOLKIT_VIEWS) + menu_.reset(new views::Menu2(menu_model_.get())); +#else + menu_.reset(new MenuGtk(NULL, menu_model_.get())); +#endif + } + virtual ~ContextMenuController() {} + + void RunMenu(const gfx::Point& point) { + const BookmarkNode* selected_node = GetSelectedNode(); + if (selected_node) + running_menu_for_root_ = selected_node->GetParent()->IsRoot(); +#if defined(TOOLKIT_VIEWS) + menu_->RunContextMenuAt(point); +#else + menu_->PopupAsContextAt(gtk_get_current_event_time(), point); +#endif + } + + void Cancel() { + editor_ = NULL; +#if defined(TOOLKIT_VIEWS) + menu_->CancelMenu(); +#else + menu_->Cancel(); +#endif + } + + private: + enum ContextMenuCommand { + COMMAND_EDIT, + COMMAND_NEW_FOLDER + }; + + // Overridden from menus::SimpleMenuModel::Delegate: + virtual bool IsCommandIdEnabled(int command_id) const { + return !(command_id == COMMAND_EDIT && running_menu_for_root_) && + (editor_ != NULL); + } + + virtual bool IsCommandIdChecked(int command_id) const { + return false; + } + + virtual bool GetAcceleratorForCommandId(int command_id, + menus::Accelerator* accelerator) { + return false; + } + + virtual void ExecuteCommand(int command_id) { + if (!editor_) + return; + + switch (command_id) { + case COMMAND_EDIT: { + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(editor_->tree_selection_, + NULL, + &iter)) { + return; + } + + GtkTreePath* path = gtk_tree_model_get_path( + GTK_TREE_MODEL(editor_->tree_store_), &iter); + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(editor_->tree_view_), path); + + // Make the folder name editable. + gtk_tree_view_set_cursor(GTK_TREE_VIEW(editor_->tree_view_), path, + gtk_tree_view_get_column(GTK_TREE_VIEW(editor_->tree_view_), 0), + TRUE); + + gtk_tree_path_free(path); + break; + } + case COMMAND_NEW_FOLDER: + editor_->NewFolder(); + break; + default: + NOTREACHED(); + break; + } + } + + int64 GetRowIdAt(GtkTreeModel* model, GtkTreeIter* iter) { + GValue value = { 0, }; + gtk_tree_model_get_value(model, iter, bookmark_utils::ITEM_ID, &value); + int64 id = g_value_get_int64(&value); + g_value_unset(&value); + return id; + } + + const BookmarkNode* GetNodeAt(GtkTreeModel* model, GtkTreeIter* iter) { + int64 id = GetRowIdAt(model, iter); + return (id > 0) ? editor_->bb_model_->GetNodeByID(id) : NULL; + } + + const BookmarkNode* GetSelectedNode() { + GtkTreeModel* model; + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(editor_->tree_selection_, + &model, + &iter)) { + return NULL; + } + + return GetNodeAt(model, &iter); + } + + // The model and view for the right click context menu. + scoped_ptr menu_model_; +#if defined(TOOLKIT_VIEWS) + scoped_ptr menu_; +#else + scoped_ptr menu_; +#endif + + // The context menu was brought up for. Set to NULL when the menu is canceled. + BookmarkEditorGtk* editor_; + + // If true, we're running the menu for the bookmark bar or other bookmarks + // nodes. + bool running_menu_for_root_; + + DISALLOW_COPY_AND_ASSIGN(ContextMenuController); +}; + // static void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, Profile* profile, @@ -181,6 +326,8 @@ void BookmarkEditorGtk::Init(GtkWindow* parent_window) { tree_view_ = bookmark_utils::MakeTreeViewForStore(tree_store_); gtk_widget_set_size_request(tree_view_, kTreeWidth, kTreeHeight); tree_selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_)); + g_signal_connect(tree_view_, "button-press-event", + G_CALLBACK(OnTreeViewButtonPressEventThunk), this); GtkTreePath* path = NULL; if (selected_id) { @@ -396,6 +543,27 @@ void BookmarkEditorGtk::OnEntryChanged(GtkWidget* entry) { } void BookmarkEditorGtk::OnNewFolderClicked(GtkWidget* button) { + NewFolder(); +} + +gboolean BookmarkEditorGtk::OnTreeViewButtonPressEvent(GtkWidget* widget, + GdkEventButton* event) { + if (event->button == 3) { + gfx::Point pt(event->x_root, event->y_root); + ShowContextMenu(pt); + } + + return FALSE; +} + +void BookmarkEditorGtk::ShowContextMenu(const gfx::Point& point) { + if (!menu_controller_.get()) + menu_controller_.reset(new ContextMenuController(this)); + + menu_controller_->RunMenu(point); +} + +void BookmarkEditorGtk::NewFolder() { GtkTreeIter iter; if (!gtk_tree_selection_get_selected(tree_selection_, NULL, diff --git a/chrome/browser/gtk/bookmark_editor_gtk.h b/chrome/browser/gtk/bookmark_editor_gtk.h index fda8769..7295689 100644 --- a/chrome/browser/gtk/bookmark_editor_gtk.h +++ b/chrome/browser/gtk/bookmark_editor_gtk.h @@ -9,6 +9,7 @@ #include "app/gtk_integers.h" #include "app/gtk_signal.h" #include "base/gtest_prod_util.h" +#include "base/scoped_ptr.h" #include "base/string16.h" #include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/bookmarks/bookmark_model_observer.h" @@ -16,24 +17,19 @@ class GURL; typedef union _GdkEvent GdkEvent; +typedef struct _GdkEventButton GdkEventButton; typedef struct _GtkTreeIter GtkTreeIter; typedef struct _GtkTreeSelection GtkTreeSelection; typedef struct _GtkTreeStore GtkTreeStore; typedef struct _GtkWidget GtkWidget; +namespace gfx { +class Point; +} // namespace gfx + // GTK version of the bookmark editor dialog. class BookmarkEditorGtk : public BookmarkEditor, public BookmarkModelObserver { - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParent); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParentAndURL); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLToExistingURL); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditTitleKeepsPosition); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditURLKeepsPosition); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ModelsMatch); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, MoveToNewParent); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, NewURL); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLNoTree); - FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeTitleNoTree); public: BookmarkEditorGtk(GtkWindow* window, Profile* profile, @@ -47,6 +43,20 @@ class BookmarkEditorGtk : public BookmarkEditor, void Close(); private: + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParent); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeParentAndURL); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLToExistingURL); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditTitleKeepsPosition); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, EditURLKeepsPosition); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ModelsMatch); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, MoveToNewParent); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, NewURL); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeURLNoTree); + FRIEND_TEST_ALL_PREFIXES(BookmarkEditorGtkTest, ChangeTitleNoTree); + + class ContextMenuController; + friend class ContextMenuController; + void Init(GtkWindow* parent_window); // BookmarkModel observer methods. Any structural change results in @@ -104,6 +114,13 @@ class BookmarkEditorGtk : public BookmarkEditor, CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnNewFolderClicked); + CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnTreeViewButtonPressEvent, + GdkEventButton*); + + void ShowContextMenu(const gfx::Point& point); + + void NewFolder(); + // Profile the entry is from. Profile* profile_; @@ -141,6 +158,9 @@ class BookmarkEditorGtk : public BookmarkEditor, // Is the tree shown? bool show_tree_; + // The context menu controller. + scoped_ptr menu_controller_; + DISALLOW_COPY_AND_ASSIGN(BookmarkEditorGtk); }; diff --git a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc b/chrome/browser/gtk/bookmark_menu_controller_gtk.cc index 38fc8ef..5930fb1 100644 --- a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc +++ b/chrome/browser/gtk/bookmark_menu_controller_gtk.cc @@ -80,15 +80,17 @@ BookmarkMenuController::BookmarkMenuController(Browser* browser, ignore_button_release_(false), triggering_widget_(NULL) { menu_ = gtk_menu_new(); + g_object_ref_sink(menu_); BuildMenu(node, start_child_index, menu_); - g_signal_connect(menu_, "hide", + signals_.Connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this); gtk_widget_show_all(menu_); } BookmarkMenuController::~BookmarkMenuController() { profile_->GetBookmarkModel()->RemoveObserver(this); - gtk_menu_popdown(GTK_MENU(menu_)); + gtk_widget_destroy(menu_); + g_object_unref(menu_); } void BookmarkMenuController::Popup(GtkWidget* widget, gint button_type, @@ -96,6 +98,8 @@ void BookmarkMenuController::Popup(GtkWidget* widget, gint button_type, profile_->GetBookmarkModel()->AddObserver(this); triggering_widget_ = widget; + signals_.Connect(triggering_widget_, "destroy", + G_CALLBACK(gtk_widget_destroyed), &triggering_widget_); gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget), GTK_STATE_ACTIVE); gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, @@ -139,9 +143,9 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, DCHECK(!parent->GetChildCount() || start_child_index < parent->GetChildCount()); - g_signal_connect(menu, "button-press-event", + signals_.Connect(menu, "button-press-event", G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this); - g_signal_connect(menu, "button-release-event", + signals_.Connect(menu, "button-release-event", G_CALLBACK(OnMenuButtonPressedOrReleasedThunk), this); for (int i = start_child_index; i < parent->GetChildCount(); ++i) { @@ -158,10 +162,10 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, SetImageMenuItem(menu_item, node, profile_->GetBookmarkModel()); gtk_util::SetAlwaysShowImage(menu_item); - g_signal_connect(menu_item, "button-release-event", + signals_.Connect(menu_item, "button-release-event", G_CALLBACK(OnButtonReleasedThunk), this); if (node->is_url()) { - g_signal_connect(menu_item, "activate", + signals_.Connect(menu_item, "activate", G_CALLBACK(OnMenuItemActivatedThunk), this); } else if (node->is_folder()) { GtkWidget* submenu = gtk_menu_new(); @@ -177,18 +181,18 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, if (node->is_url()) target_mask |= gtk_dnd_util::TEXT_URI_LIST | gtk_dnd_util::NETSCAPE_URL; gtk_dnd_util::SetSourceTargetListFromCodeMask(menu_item, target_mask); - g_signal_connect(menu_item, "drag-begin", + signals_.Connect(menu_item, "drag-begin", G_CALLBACK(OnMenuItemDragBeginThunk), this); - g_signal_connect(menu_item, "drag-end", + signals_.Connect(menu_item, "drag-end", G_CALLBACK(OnMenuItemDragEndThunk), this); - g_signal_connect(menu_item, "drag-data-get", + signals_.Connect(menu_item, "drag-data-get", G_CALLBACK(OnMenuItemDragGetThunk), this); // It is important to connect to this signal after setting up the drag // source because we only want to stifle the menu's default handler and // not the handler that the drag source uses. if (node->is_folder()) { - g_signal_connect(menu_item, "button-press-event", + signals_.Connect(menu_item, "button-press-event", G_CALLBACK(OnFolderButtonPressedThunk), this); } @@ -267,7 +271,7 @@ gboolean BookmarkMenuController::OnMenuButtonPressedOrReleased( // context menu is hidden, re-assert our grab. GtkWidget* grabbing_menu = gtk_grab_get_current(); g_object_ref(grabbing_menu); - g_signal_connect(context_menu_->widget(), "hide", + signals_.Connect(context_menu_->widget(), "hide", G_CALLBACK(OnContextMenuHide), grabbing_menu); context_menu_->PopupAsContext(event->time); diff --git a/chrome/browser/gtk/bookmark_menu_controller_gtk.h b/chrome/browser/gtk/bookmark_menu_controller_gtk.h index cf8443c..0060267 100644 --- a/chrome/browser/gtk/bookmark_menu_controller_gtk.h +++ b/chrome/browser/gtk/bookmark_menu_controller_gtk.h @@ -10,6 +10,7 @@ #include "app/gtk_integers.h" #include "app/gtk_signal.h" +#include "app/gtk_signal_registrar.h" #include "base/scoped_ptr.h" #include "chrome/browser/bookmarks/base_bookmark_model_observer.h" #include "chrome/browser/bookmarks/bookmark_context_menu_controller.h" @@ -136,6 +137,8 @@ class BookmarkMenuController : public BaseBookmarkModelObserver, scoped_ptr context_menu_controller_; scoped_ptr context_menu_; + GtkSignalRegistrar signals_; + DISALLOW_COPY_AND_ASSIGN(BookmarkMenuController); }; diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index 4ee92b1..4d45545 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -8,7 +8,6 @@ #include "base/i18n/rtl.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_context_menu_model.h" #include "chrome/browser/extensions/extensions_service.h" @@ -24,6 +23,7 @@ #include "chrome/browser/gtk/view_id_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/extensions/extension_resource.h" diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/gtk/browser_actions_toolbar_gtk.h index 72cf960..ac80386 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.h @@ -9,6 +9,7 @@ #include #include +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "app/gtk_signal_registrar.h" #include "app/menus/simple_menu_model.h" diff --git a/chrome/browser/gtk/browser_titlebar.cc b/chrome/browser/gtk/browser_titlebar.cc index dea24e6..995f047 100644 --- a/chrome/browser/gtk/browser_titlebar.cc +++ b/chrome/browser/gtk/browser_titlebar.cc @@ -18,12 +18,13 @@ #include "base/string_tokenizer.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/encoding_menu_controller.h" #include "chrome/browser/gtk/accelerators_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/custom_button.h" +#if defined(USE_GCONF) #include "chrome/browser/gtk/gconf_titlebar_listener.h" +#endif #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/menu_gtk.h" @@ -32,6 +33,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/wrench_menu_model.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" @@ -193,6 +195,9 @@ void PopupPageMenuModel::Build() { //////////////////////////////////////////////////////////////////////////////// // BrowserTitlebar +// static +const char BrowserTitlebar::kDefaultButtonString[] = ":minimize,maximize,close"; + BrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window, GtkWindow* window) : browser_window_(browser_window), @@ -299,9 +304,13 @@ void BrowserTitlebar::Init() { gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_buttons_vbox_, FALSE, FALSE, 0); +#if defined(USE_GCONF) // Either read the gconf database and register for updates (on GNOME), or use // the default value (anywhere else). Singleton()->SetTitlebarButtons(this); +#else + BuildButtons(kDefaultButtonString); +#endif // We use an alignment to control the titlebar height. titlebar_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); @@ -363,7 +372,9 @@ void BrowserTitlebar::Init() { BrowserTitlebar::~BrowserTitlebar() { ActiveWindowWatcherX::RemoveObserver(this); +#if defined(USE_GCONF) Singleton()->RemoveObserver(this); +#endif } void BrowserTitlebar::BuildButtons(const std::string& button_string) { diff --git a/chrome/browser/gtk/browser_titlebar.h b/chrome/browser/gtk/browser_titlebar.h index c6da855..5cd30e6 100644 --- a/chrome/browser/gtk/browser_titlebar.h +++ b/chrome/browser/gtk/browser_titlebar.h @@ -31,6 +31,10 @@ class BrowserTitlebar : public NotificationObserver, public ActiveWindowWatcherX::Observer, public menus::SimpleMenuModel::Delegate { public: + // A default button order string for when we aren't asking gconf for the + // metacity configuration. + static const char kDefaultButtonString[]; + BrowserTitlebar(BrowserWindowGtk* browser_window, GtkWindow* window); virtual ~BrowserTitlebar(); diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index 09fb457..5ceb32d 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -18,7 +18,6 @@ #include "base/path_service.h" #include "base/singleton.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/encoding_menu_controller.h" #include "chrome/browser/gtk/accelerators_gtk.h" #include "chrome/browser/gtk/back_forward_button_gtk.h" @@ -39,6 +38,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/upgrade_detector.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_details.h" diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index 1e27f8f..f2e8fec 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -10,6 +10,7 @@ #include #include "app/active_window_watcher_x.h" +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "app/gtk_signal_registrar.h" #include "app/menus/accelerator.h" diff --git a/chrome/browser/gtk/browser_window_factory_gtk.cc b/chrome/browser/gtk/browser_window_factory_gtk.cc index 8291fb9..054a0df 100644 --- a/chrome/browser/gtk/browser_window_factory_gtk.cc +++ b/chrome/browser/gtk/browser_window_factory_gtk.cc @@ -4,9 +4,9 @@ #include "chrome/browser/browser_window.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/find_bar_gtk.h" +#include "chrome/browser/ui/browser.h" BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) { return new BrowserWindowGtk(browser); diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 6d537c9..20dd209 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -24,7 +24,6 @@ #include "chrome/browser/app_modal_dialog_queue.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/bookmarks/bookmark_utils.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/debugger/devtools_window.h" @@ -69,12 +68,11 @@ #include "chrome/browser/page_info_window.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_widget_host_view_gtk.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/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/native_web_keyboard_event.h" @@ -304,26 +302,6 @@ bool ShouldExecuteReservedCommandImmediately( return true; } -// Performs Cut/Copy/Paste operation on the |window|. -// If the current render view is focused, then just call the specified |method| -// against the current render view host, otherwise emit the specified |signal| -// against the focused widget. -// TODO(suzhe): This approach does not work for plugins. -void DoCutCopyPaste(BrowserWindowGtk* window, void (RenderViewHost::*method)(), - const char* signal) { - TabContents* current_tab_contents = - window->browser()->tabstrip_model()->GetSelectedTabContents(); - if (current_tab_contents && current_tab_contents->GetContentNativeView() && - gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) { - (current_tab_contents->render_view_host()->*method)(); - } else { - GtkWidget* widget = gtk_window_get_focus(window->window()); - guint id; - if (widget && (id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0) - g_signal_emit(widget, id, 0); - } -} - } // namespace std::map BrowserWindowGtk::xid_map_; @@ -590,9 +568,10 @@ void BrowserWindowGtk::DrawCustomFrame(cairo_t* cr, CairoCachedSurface* surface = theme_provider->GetSurfaceNamed( image_name, widget); if (event->area.y < surface->Height()) { - surface->SetSource(cr, - 0, - UseCustomFrame() ? 0 : -kCustomFrameBackgroundVerticalOffset); + int offset = (IsMaximized() || (!UseCustomFrame())) ? + -kCustomFrameBackgroundVerticalOffset : 0; + surface->SetSource(cr, 0, offset); + // The frame background isn't tiled vertically. cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT); cairo_rectangle(cr, event->area.x, event->area.y, @@ -899,10 +878,6 @@ bool BrowserWindowGtk::IsToolbarVisible() const { return IsToolbarSupported(); } -gfx::Rect BrowserWindowGtk::GetRootWindowResizerRect() const { - return gfx::Rect(); -} - void BrowserWindowGtk::ConfirmAddSearchProvider(const TemplateURL* template_url, Profile* profile) { new EditSearchEngineDialog(window_, template_url, NULL, profile); @@ -1116,15 +1091,19 @@ void BrowserWindowGtk::ShowCreateShortcutsDialog(TabContents* tab_contents) { } void BrowserWindowGtk::Cut() { - DoCutCopyPaste(this, &RenderViewHost::Cut, "cut-clipboard"); + gtk_util::DoCut(this); } void BrowserWindowGtk::Copy() { - DoCutCopyPaste(this, &RenderViewHost::Copy, "copy-clipboard"); + gtk_util::DoCopy(this); } void BrowserWindowGtk::Paste() { - DoCutCopyPaste(this, &RenderViewHost::Paste, "paste-clipboard"); + gtk_util::DoPaste(this); +} + +void BrowserWindowGtk::PrepareForInstant() { + // TODO: implement fade as done on windows. } void BrowserWindowGtk::ShowInstant(TabContents* preview_contents) { diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index ce8e582..b1b8502 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -85,7 +85,6 @@ class BrowserWindowGtk : public BrowserWindow, virtual bool IsBookmarkBarVisible() const; virtual bool IsBookmarkBarAnimating() const; virtual bool IsToolbarVisible() const; - virtual gfx::Rect GetRootWindowResizerRect() const; virtual void ConfirmAddSearchProvider(const TemplateURL* template_url, Profile* profile); virtual void ToggleBookmarkBar(); @@ -125,6 +124,7 @@ class BrowserWindowGtk : public BrowserWindow, virtual void Copy(); virtual void Paste(); virtual void ToggleTabStripMode() {} + virtual void PrepareForInstant(); virtual void ShowInstant(TabContents* preview_contents); virtual void HideInstant(); virtual gfx::Rect GetInstantBounds(); diff --git a/chrome/browser/gtk/chrome_gtk_frame.cc b/chrome/browser/gtk/chrome_gtk_frame.cc new file mode 100644 index 0000000..77f28d1 --- /dev/null +++ b/chrome/browser/gtk/chrome_gtk_frame.cc @@ -0,0 +1,155 @@ +// 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/gtk/chrome_gtk_frame.h" + +G_BEGIN_DECLS + +// MetaFrames declaration +G_DEFINE_TYPE(MetaFrames, meta_frames, GTK_TYPE_WINDOW) + +static void meta_frames_class_init(MetaFramesClass* frames_class) { + // Noop since we don't declare anything. +} + +static void meta_frames_init(MetaFrames* button) { +} + + +// ChromeGtkFrame declaration +G_DEFINE_TYPE(ChromeGtkFrame, chrome_gtk_frame, meta_frames_get_type()) + +static void chrome_gtk_frame_class_init(ChromeGtkFrameClass* frame_class) { + GtkWidgetClass* widget_class = reinterpret_cast(frame_class); + + // Frame tints: + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "frame-color", + "Frame Color", + "The color that the chrome frame will be. (If unspecified, " + " Chrome will take ChromeGtkFrame::bg[SELECTED] and slightly darken" + " it.)", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "inactive-frame-color", + "Inactive Frame Color", + "The color that the inactive chrome frame will be. (If" + " unspecified, Chrome will take ChromeGtkFrame::bg[INSENSITIVE]" + " and slightly darken it.)", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "incognito-frame-color", + "Incognito Frame Color", + "The color that the incognito frame will be. (If unspecified," + " Chrome will take the frame color and tint it by Chrome's default" + " incognito tint.)", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "incognito-inactive-frame-color", + "Incognito Inactive Frame Color", + "The color that the inactive incognito frame will be. (If" + " unspecified, Chrome will take the frame color and tint it by" + " Chrome's default incognito tint.)", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + + // Frame gradient control: + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_int( + "frame-gradient-size", + "Chrome Frame Gradient Size", + "The size of the gradient on top of the frame image. Specify 0 to" + " make the frame a solid color.", + 0, // 0 disables the gradient + 128, // The frame image is only up to 128 pixels tall. + 16, // By default, gradients are 16 pixels high. + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "frame-gradient-color", + "Frame Gradient Color", + "The top color of the chrome frame gradient. (If unspecified," + " chrome will create a lighter tint of frame-color", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "inactive-frame-gradient-color", + "Inactive Frame Gradient Color", + "The top color of the inactive chrome frame gradient. (If" + " unspecified, chrome will create a lighter tint of frame-color", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "incognito-frame-gradient-color", + "Incognito Frame Gradient Color", + "The top color of the incognito chrome frame gradient. (If" + " unspecified, chrome will create a lighter tint of frame-color", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "incognito-inactive-frame-gradient-color", + "Incognito Inactive Frame Gradient Color", + "The top color of the incognito inactive chrome frame gradient. (If" + " unspecified, chrome will create a lighter tint of frame-color", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + + // Scrollbar color properties: + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "scrollbar-slider-prelight-color", + "Scrollbar Slider Prelight Color", + "The color applied to the mouse is above the tab", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "scrollbar-slider-normal-color", + "Scrollbar Slider Normal Color", + "The color applied to the slider normally", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property( + widget_class, + g_param_spec_boxed( + "scrollbar-trough-color", + "Scrollbar Trough Color", + "The background color of the slider track", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); +} + +static void chrome_gtk_frame_init(ChromeGtkFrame* frame) { +} + +GtkWidget* chrome_gtk_frame_new(void) { + GtkWindow* window = + GTK_WINDOW(g_object_new(chrome_gtk_frame_get_type(), NULL)); + window->type = GTK_WINDOW_TOPLEVEL; + return GTK_WIDGET(window); +} + + +G_END_DECLS diff --git a/chrome/browser/gtk/chrome_gtk_frame.h b/chrome/browser/gtk/chrome_gtk_frame.h new file mode 100644 index 0000000..0fd7d28 --- /dev/null +++ b/chrome/browser/gtk/chrome_gtk_frame.h @@ -0,0 +1,56 @@ +// 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_GTK_CHROME_GTK_FRAME_H_ +#define CHROME_BROWSER_GTK_CHROME_GTK_FRAME_H_ +#pragma once + +#include +#include + +G_BEGIN_DECLS + +// This file declares two subclasses of GtkWindow for easier gtk+ theme +// integration. +// +// The first is "MetaFrames," which is (was?) the name of a gobject class in +// the metacity window manager. To actually get at those values, we need to +// have an object whose gobject class name string matches the definitions in +// the gtkrc file. MetaFrames derives from GtkWindow. +// +// Metaframes can not be instantiated. It has no constructor; instantiate +// ChromeGtkFrame instead. +typedef struct _MetaFrames MetaFrames; +typedef struct _MetaFramesClass MetaFramesClass; + +struct _MetaFrames { + GtkWindow window; +}; + +struct _MetaFramesClass { + GtkWindowClass parent_class; +}; + + +// The second is ChromeGtkFrame, which defines a number of optional style +// properties so theme authors can control how chromium appears in gtk-theme +// mode. It derives from MetaFrames in chrome so older themes that declare a +// MetaFrames theme will still work. New themes should target this class. +typedef struct _ChromeGtkFrame ChromeGtkFrame; +typedef struct _ChromeGtkFrameClass ChromeGtkFrameClass; + +struct _ChromeGtkFrame { + MetaFrames frames; +}; + +struct _ChromeGtkFrameClass { + MetaFramesClass frames_class; +}; + +// Creates a GtkWindow object the the class name "ChromeGtkFrame". +GtkWidget* chrome_gtk_frame_new(); + +G_END_DECLS + +#endif // CHROME_BROWSER_GTK_CHROME_GTK_FRAME_H_ diff --git a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc b/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc index 2607359..b5b2450 100644 --- a/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc +++ b/chrome/browser/gtk/clear_browsing_data_dialog_gtk.cc @@ -7,7 +7,6 @@ #include #include "app/l10n_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browsing_data_remover.h" #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" @@ -15,6 +14,7 @@ #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" diff --git a/chrome/browser/gtk/constrained_window_gtk.cc b/chrome/browser/gtk/constrained_window_gtk.cc index 14564de..f10dc03 100644 --- a/chrome/browser/gtk/constrained_window_gtk.cc +++ b/chrome/browser/gtk/constrained_window_gtk.cc @@ -45,7 +45,11 @@ ConstrainedWindowGtk::ConstrainedWindowGtk( gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background); } - gtk_container_add(GTK_CONTAINER(alignment), dialog); + if (gtk_widget_get_parent(dialog)) + gtk_widget_reparent(dialog, alignment); + else + gtk_container_add(GTK_CONTAINER(alignment), dialog); + gtk_container_add(GTK_CONTAINER(frame), alignment); gtk_container_add(GTK_CONTAINER(ebox), frame); border_.Own(ebox); diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h index 4d19510..785df6b 100644 --- a/chrome/browser/gtk/custom_button.h +++ b/chrome/browser/gtk/custom_button.h @@ -8,6 +8,7 @@ #include +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "app/slide_animation.h" #include "base/scoped_ptr.h" diff --git a/chrome/browser/gtk/dialogs_gtk.cc b/chrome/browser/gtk/dialogs_gtk.cc index 4872f89..8a95192 100644 --- a/chrome/browser/gtk/dialogs_gtk.cc +++ b/chrome/browser/gtk/dialogs_gtk.cc @@ -172,6 +172,7 @@ SelectFileDialog* SelectFileDialog::Create(Listener* listener) { SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) : listener_(listener), file_type_index_(0), + type_(SELECT_NONE), preview_(NULL) { if (!last_saved_path_) { last_saved_path_ = new FilePath(); diff --git a/chrome/browser/gtk/download_in_progress_dialog_gtk.cc b/chrome/browser/gtk/download_in_progress_dialog_gtk.cc index 8a41589..3b039ca 100644 --- a/chrome/browser/gtk/download_in_progress_dialog_gtk.cc +++ b/chrome/browser/gtk/download_in_progress_dialog_gtk.cc @@ -9,11 +9,11 @@ #include "app/l10n_util.h" #include "base/string_number_conversions.h" #include "base/string16.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc index 844c751..329208b 100644 --- a/chrome/browser/gtk/download_item_gtk.cc +++ b/chrome/browser/gtk/download_item_gtk.cc @@ -14,7 +14,6 @@ #include "base/string_util.h" #include "base/time.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_item_model.h" @@ -27,6 +26,7 @@ #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/gtk/nine_box.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "gfx/canvas_skia_paint.h" #include "gfx/color_utils.h" diff --git a/chrome/browser/gtk/download_item_gtk.h b/chrome/browser/gtk/download_item_gtk.h index f73592a..a9ad27d 100644 --- a/chrome/browser/gtk/download_item_gtk.h +++ b/chrome/browser/gtk/download_item_gtk.h @@ -10,7 +10,7 @@ #include -#include "app/animation.h" +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "base/scoped_ptr.h" #include "base/time.h" diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc index a6c2a69..3c47c38 100644 --- a/chrome/browser/gtk/download_shelf_gtk.cc +++ b/chrome/browser/gtk/download_shelf_gtk.cc @@ -6,7 +6,6 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" -#include "chrome/browser/browser.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_util.h" @@ -18,6 +17,7 @@ #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "gfx/gtk_util.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/gtk/extension_infobar_gtk.cc b/chrome/browser/gtk/extension_infobar_gtk.cc index 35d86c0..bd40795 100644 --- a/chrome/browser/gtk/extension_infobar_gtk.cc +++ b/chrome/browser/gtk/extension_infobar_gtk.cc @@ -62,7 +62,13 @@ void ExtensionInfoBarGtk::BuildWidgets() { ExtensionHost* extension_host = delegate_->extension_host(); view_ = extension_host->view(); - gtk_box_pack_start(GTK_BOX(hbox_), view_->native_view(), TRUE, TRUE, 0); + if (gtk_widget_get_parent(view_->native_view())) { + gtk_widget_reparent(view_->native_view(), hbox_); + gtk_box_set_child_packing(GTK_BOX(hbox_), view_->native_view(), + TRUE, TRUE, 0, GTK_PACK_START); + } else { + gtk_box_pack_start(GTK_BOX(hbox_), view_->native_view(), TRUE, TRUE, 0); + } g_signal_connect(view_->native_view(), "size_allocate", G_CALLBACK(&OnSizeAllocateThunk), this); diff --git a/chrome/browser/gtk/extension_infobar_gtk.h b/chrome/browser/gtk/extension_infobar_gtk.h index b727c04..b204bfc 100644 --- a/chrome/browser/gtk/extension_infobar_gtk.h +++ b/chrome/browser/gtk/extension_infobar_gtk.h @@ -6,8 +6,6 @@ #define CHROME_BROWSER_GTK_EXTENSION_INFOBAR_GTK_H_ #pragma once -#include - #include "chrome/browser/gtk/extension_view_gtk.h" #include "chrome/browser/gtk/infobar_gtk.h" #include "chrome/browser/extensions/extension_infobar_delegate.h" diff --git a/chrome/browser/gtk/extension_install_prompt2_gtk.cc b/chrome/browser/gtk/extension_install_prompt2_gtk.cc index cf78028..10ee4e4 100644 --- a/chrome/browser/gtk/extension_install_prompt2_gtk.cc +++ b/chrome/browser/gtk/extension_install_prompt2_gtk.cc @@ -107,11 +107,8 @@ void ShowInstallPromptDialog2(GtkWindow* parent, SkBitmap* skia_icon, !show_permissions, !show_permissions, 0); if (show_permissions) { - int label = extension->is_app() ? - IDS_EXTENSION_PROMPT2_APP_WILL_HAVE_ACCESS_TO : - IDS_EXTENSION_PROMPT2_WILL_HAVE_ACCESS_TO; GtkWidget* warning_label = gtk_label_new(l10n_util::GetStringUTF8( - label).c_str()); + IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO).c_str()); gtk_misc_set_alignment(GTK_MISC(warning_label), 0.0, 0.5); gtk_util::SetLabelWidth(warning_label, kRightColumnMinWidth); diff --git a/chrome/browser/gtk/extension_installed_bubble_gtk.cc b/chrome/browser/gtk/extension_installed_bubble_gtk.cc index af9c915..adb2b7b 100644 --- a/chrome/browser/gtk/extension_installed_bubble_gtk.cc +++ b/chrome/browser/gtk/extension_installed_bubble_gtk.cc @@ -9,13 +9,13 @@ #include "base/i18n/rtl.h" #include "base/message_loop.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/browser_actions_toolbar_gtk.h" #include "chrome/browser/gtk/browser_toolbar_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/location_bar_view_gtk.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/notification_service.h" @@ -57,7 +57,9 @@ ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk( animation_wait_retries_(kAnimationWaitRetries) { AddRef(); // Balanced in Close(). - if (extension_->browser_action()) { + if (!extension_->omnibox_keyword().empty()) { + type_ = OMNIBOX_KEYWORD; + } else if (extension_->browser_action()) { type_ = BROWSER_ACTION; } else if (extension->page_action() && !extension->page_action()->default_icon_path().empty()) { @@ -141,7 +143,13 @@ void ExtensionInstalledBubbleGtk::ShowInternal() { gtk_container_check_resize(GTK_CONTAINER( browser_window->GetToolbar()->widget())); DCHECK(reference_widget); + } else if (type_ == OMNIBOX_KEYWORD) { + LocationBarViewGtk* location_bar_view = + browser_window->GetToolbar()->GetLocationBarView(); + reference_widget = location_bar_view->location_entry_widget(); + DCHECK(reference_widget); } + // Default case. if (reference_widget == NULL) reference_widget = browser_window->GetToolbar()->GetAppMenuButton(); @@ -153,34 +161,36 @@ void ExtensionInstalledBubbleGtk::ShowInternal() { GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing); gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder); - // Scale icon down to 43x43, but allow smaller icons (don't scale up). - GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon_); - gfx::Size size(icon_.width(), icon_.height()); - if (size.width() > kIconSize || size.height() > kIconSize) { - if (size.width() > size.height()) { - size.set_height(size.height() * kIconSize / size.width()); - size.set_width(kIconSize); - } else { - size.set_width(size.width() * kIconSize / size.height()); - size.set_height(kIconSize); + if (!icon_.isNull()) { + // Scale icon down to 43x43, but allow smaller icons (don't scale up). + GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon_); + gfx::Size size(icon_.width(), icon_.height()); + if (size.width() > kIconSize || size.height() > kIconSize) { + if (size.width() > size.height()) { + size.set_height(size.height() * kIconSize / size.width()); + size.set_width(kIconSize); + } else { + size.set_width(size.width() * kIconSize / size.height()); + size.set_height(kIconSize); + } + + GdkPixbuf* old = pixbuf; + pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(), + GDK_INTERP_BILINEAR); + g_object_unref(old); } - GdkPixbuf* old = pixbuf; - pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(), - GDK_INTERP_BILINEAR); - g_object_unref(old); + // Put Icon in top of the left column. + GtkWidget* icon_column = gtk_vbox_new(FALSE, 0); + // Use 3 pixel padding to get visual balance with InfoBubble border on the + // left. + gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE, + kIconPadding); + GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf); + g_object_unref(pixbuf); + gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0); } - // Put Icon in top of the left column. - GtkWidget* icon_column = gtk_vbox_new(FALSE, 0); - // Use 3 pixel padding to get visual balance with InfoBubble border on the - // left. - gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE, - kIconPadding); - GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf); - g_object_unref(pixbuf); - gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0); - // Center text column. GtkWidget* text_column = gtk_vbox_new(FALSE, kTextColumnVerticalSpacing); gtk_box_pack_start(GTK_BOX(bubble_content), text_column, FALSE, FALSE, 0); @@ -199,9 +209,19 @@ void ExtensionInstalledBubbleGtk::ShowInternal() { gtk_box_pack_start(GTK_BOX(text_column), heading_label, FALSE, FALSE, 0); // Page action label - if (type_ == ExtensionInstalledBubbleGtk::PAGE_ACTION) { + if (type_ == PAGE_ACTION) { GtkWidget* info_label = gtk_label_new(l10n_util::GetStringUTF8( - IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str()); + IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str()); + gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE); + gtk_widget_set_size_request(info_label, kTextColumnWidth, -1); + gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0); + } + + // Omnibox keyword label + if (type_ == OMNIBOX_KEYWORD) { + GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8( + IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO, + UTF8ToUTF16(extension_->omnibox_keyword())).c_str()); gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE); gtk_widget_set_size_request(info_label, kTextColumnWidth, -1); gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0); @@ -232,8 +252,23 @@ void ExtensionInstalledBubbleGtk::ShowInternal() { !base::i18n::IsRTL() ? InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT : InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT; + + gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget); + if (type_ == OMNIBOX_KEYWORD) { + // Reverse the arrow for omnibox keywords, since the bubble will be on the + // other side of the window. We also clear the width to avoid centering + // the popup on the URL bar. + arrow_location = + !base::i18n::IsRTL() ? + InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT : + InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT; + if (base::i18n::IsRTL()) + bounds.Offset(bounds.width(), 0); + bounds.set_width(0); + } + info_bubble_ = InfoBubbleGtk::Show(reference_widget, - NULL, + &bounds, bubble_content, arrow_location, true, // match_system_theme diff --git a/chrome/browser/gtk/extension_installed_bubble_gtk.h b/chrome/browser/gtk/extension_installed_bubble_gtk.h index 08d6fec..0613283 100644 --- a/chrome/browser/gtk/extension_installed_bubble_gtk.h +++ b/chrome/browser/gtk/extension_installed_bubble_gtk.h @@ -22,6 +22,7 @@ class SkBitmap; // Provides feedback to the user upon successful installation of an // extension. Depending on the type of extension, the InfoBubble will // point to: +// OMNIBOX_KEYWORD-> The omnibox. // BROWSER_ACTION -> The browserAction icon in the toolbar. // PAGE_ACTION -> A preview of the page action icon in the location // bar which is shown while the InfoBubble is shown. @@ -36,6 +37,7 @@ class ExtensionInstalledBubbleGtk public: // The behavior and content of this InfoBubble comes in three varieties. enum BubbleType { + OMNIBOX_KEYWORD, BROWSER_ACTION, PAGE_ACTION, GENERIC diff --git a/chrome/browser/gtk/extension_popup_gtk.cc b/chrome/browser/gtk/extension_popup_gtk.cc index 32b32bc..e9ed014 100644 --- a/chrome/browser/gtk/extension_popup_gtk.cc +++ b/chrome/browser/gtk/extension_popup_gtk.cc @@ -8,7 +8,6 @@ #include "base/i18n/rtl.h" #include "base/message_loop.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/profile.h" @@ -17,6 +16,7 @@ #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc index 8afba9a..aa3429f 100644 --- a/chrome/browser/gtk/find_bar_gtk.cc +++ b/chrome/browser/gtk/find_bar_gtk.cc @@ -16,7 +16,6 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/find_bar_state.h" #include "chrome/browser/gtk/browser_window_gtk.h" @@ -33,6 +32,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/notification_service.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/gtk/first_run_bubble.cc b/chrome/browser/gtk/first_run_bubble.cc index 81daf73..343f57b 100644 --- a/chrome/browser/gtk/first_run_bubble.cc +++ b/chrome/browser/gtk/first_run_bubble.cc @@ -10,11 +10,11 @@ #include "base/command_line.h" #include "base/i18n/rtl.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/search_engines/util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/gtk/gconf_titlebar_listener.cc b/chrome/browser/gtk/gconf_titlebar_listener.cc index 81b5ef0..237332f 100644 --- a/chrome/browser/gtk/gconf_titlebar_listener.cc +++ b/chrome/browser/gtk/gconf_titlebar_listener.cc @@ -13,10 +13,6 @@ namespace { -// A default button order string for when we aren't asking gconf for the -// metacity configuration. -const char* kDefaultButtonPlacement = ":minimize,maximize,close"; - // The GConf key we read for the button placement string. Even through the key // has "metacity" in it, it's shared between metacity and compiz. const char* kButtonLayoutKey = "/apps/metacity/general/button_layout"; @@ -34,7 +30,7 @@ void GConfTitlebarListener::SetTitlebarButtons(BrowserTitlebar* titlebar) { titlebar->BuildButtons(current_value_); titlebars_.insert(titlebar); } else { - titlebar->BuildButtons(kDefaultButtonPlacement); + titlebar->BuildButtons(BrowserTitlebar::kDefaultButtonString); } } @@ -113,8 +109,8 @@ bool GConfTitlebarListener::HandleGError(GError* error, const char* key) { void GConfTitlebarListener::ParseAndStoreValue(GConfValue* gconf_value) { if (gconf_value) { const char* value = gconf_value_get_string(gconf_value); - current_value_ = value ? value : kDefaultButtonPlacement; + current_value_ = value ? value : BrowserTitlebar::kDefaultButtonString; } else { - current_value_ = kDefaultButtonPlacement; + current_value_ = BrowserTitlebar::kDefaultButtonString; } } diff --git a/chrome/browser/gtk/gtk_theme_provider.cc b/chrome/browser/gtk/gtk_theme_provider.cc index 6d04b57..a57ab6b 100644 --- a/chrome/browser/gtk/gtk_theme_provider.cc +++ b/chrome/browser/gtk/gtk_theme_provider.cc @@ -14,10 +14,10 @@ #include "base/stl_util-inl.h" #include "base/nix/xdg_util.h" #include "chrome/browser/gtk/cairo_cached_surface.h" +#include "chrome/browser/gtk/chrome_gtk_frame.h" #include "chrome/browser/gtk/gtk_chrome_button.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/hover_controller_gtk.h" -#include "chrome/browser/gtk/meta_frames.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" @@ -26,15 +26,18 @@ #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" +#include "gfx/canvas_skia.h" #include "gfx/color_utils.h" #include "gfx/gtk_util.h" #include "gfx/skbitmap_operations.h" +#include "gfx/skia_util.h" #include "gfx/skia_utils_gtk.h" #include "grit/app_resources.h" #include "grit/theme_resources.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkShader.h" namespace { @@ -42,8 +45,11 @@ namespace { const int kToolbarImageWidth = 64; const int kToolbarImageHeight = 128; -const color_utils::HSL kExactColor = { -1, -1, -1 }; +// How much to tint the GTK+ color lighter at the top of the window. +const color_utils::HSL kGtkFrameShift = { -1, -1, 0.58 }; +// How much to tint the GTK+ color when an explicit frame color hasn't been +// specified. const color_utils::HSL kDefaultFrameShift = { -1, -1, 0.4 }; // Values used as the new luminance and saturation values in the inactive tab @@ -53,10 +59,6 @@ const double kLightInactiveLuminance = 0.15; const double kHeavyInactiveSaturation = 0.7; const double kLightInactiveSaturation = 0.3; -// Minimum difference between the toolbar and the button color before we try a -// different color. -const double kMinimumLuminanceDifference = 0.1; - // Number of times that the background color should be counted when trying to // calculate the border color in GTK theme mode. const int kBgWeight = 3; @@ -227,6 +229,14 @@ void BuildIconFromIDRWithColor(int id, gtk_icon_source_free(icon); } +// Applies an HSL shift to a GdkColor (instead of an SkColor) +void GdkColorHSLShift(const color_utils::HSL& shift, GdkColor* frame_color) { + SkColor shifted = color_utils::HSLShift(GdkToSkColor(frame_color), shift); + frame_color->pixel = 0; + frame_color->red = SkColorGetR(shifted) * kSkiaToGDKMultiplier; + frame_color->green = SkColorGetG(shifted) * kSkiaToGDKMultiplier; + frame_color->blue = SkColorGetB(shifted) * kSkiaToGDKMultiplier; +} } // namespace @@ -242,7 +252,7 @@ GtkThemeProvider* GtkThemeProvider::GetFrom(Profile* profile) { GtkThemeProvider::GtkThemeProvider() : BrowserThemeProvider(), fake_window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)), - fake_frame_(meta_frames_new()), + fake_frame_(chrome_gtk_frame_new()), signals_(new GtkSignalRegistrar), fullscreen_icon_set_(NULL) { fake_label_.Own(gtk_label_new("")); @@ -414,6 +424,24 @@ GtkIconSet* GtkThemeProvider::GetIconSetForId(int id) const { void GtkThemeProvider::GetScrollbarColors(GdkColor* thumb_active_color, GdkColor* thumb_inactive_color, GdkColor* track_color) { + const GdkColor* theme_thumb_active = NULL; + const GdkColor* theme_thumb_inactive = NULL; + const GdkColor* theme_trough_color = NULL; + gtk_widget_style_get(GTK_WIDGET(fake_frame_), + "scrollbar-slider-prelight-color", &theme_thumb_active, + "scrollbar-slider-normal-color", &theme_thumb_inactive, + "scrollbar-trough-color", &theme_trough_color, + NULL); + + // Ask the theme if the theme specifies all the scrollbar colors and short + // circuit the expensive painting/compositing if we have all of them. + if (theme_thumb_active && theme_thumb_inactive && theme_trough_color) { + *thumb_active_color = *theme_thumb_active; + *thumb_inactive_color = *theme_thumb_inactive; + *track_color = *theme_trough_color; + return; + } + // Create window containing scrollbar elements GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP); GtkWidget* fixed = gtk_fixed_new(); @@ -479,6 +507,17 @@ void GtkThemeProvider::GetScrollbarColors(GdkColor* thumb_active_color, g_object_unref(pm); gtk_widget_destroy(window); + + // Override any of the default colors with ones that were specified by the + // theme. + if (theme_thumb_active) + *thumb_active_color = *theme_thumb_active; + + if (theme_thumb_inactive) + *thumb_inactive_color = *theme_thumb_inactive; + + if (theme_trough_color) + *track_color = *theme_trough_color; } CairoCachedSurface* GtkThemeProvider::GetSurfaceNamed( @@ -630,87 +669,29 @@ void GtkThemeProvider::LoadGtkValues() { pref_images->Clear(); GtkStyle* frame_style = gtk_rc_get_style(fake_frame_); - GdkColor frame_color = frame_style->bg[GTK_STATE_SELECTED]; - GdkColor inactive_frame_color = frame_style->bg[GTK_STATE_INSENSITIVE]; GtkStyle* window_style = gtk_rc_get_style(fake_window_); + SetThemeColorFromGtk(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND, + &window_style->bg[GTK_STATE_NORMAL]); + SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND, + &window_style->bg[GTK_STATE_NORMAL]); + GdkColor toolbar_color = window_style->bg[GTK_STATE_NORMAL]; + SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TOOLBAR, &toolbar_color); + GdkColor button_color = window_style->bg[GTK_STATE_SELECTED]; + SetThemeTintFromGtk(BrowserThemeProvider::TINT_BUTTONS, &button_color); GtkStyle* label_style = gtk_rc_get_style(fake_label_.get()); GdkColor label_color = label_style->fg[GTK_STATE_NORMAL]; - - GtkSettings* settings = gtk_settings_get_default(); - bool theme_has_frame_color = false; - if (settings) { - GHashTable* color_scheme = NULL; - g_object_get(settings, "color-hash", &color_scheme, NULL); - - if (color_scheme) { - // If we have a "gtk-color-scheme" set in this theme, mine it for hints - // about what we should actually set the frame color to. - GdkColor* color = NULL; - if ((color = static_cast( - g_hash_table_lookup(color_scheme, "frame_color")))) { - frame_color = *color; - theme_has_frame_color = true; - } - - if ((color = static_cast( - g_hash_table_lookup(color_scheme, "inactive_frame_color")))) { - inactive_frame_color = *color; - } - } - } - - if (!theme_has_frame_color) { - // If the theme's gtkrc doesn't explicitly tell us to use a specific frame - // color, change the luminosity of the frame color downwards to 80% of what - // it currently is. This is in a futile attempt to match the default - // metacity and xfwm themes. - SkColor shifted = color_utils::HSLShift(GdkToSkColor(&frame_color), - kDefaultFrameShift); - frame_color.pixel = 0; - frame_color.red = SkColorGetR(shifted) * kSkiaToGDKMultiplier; - frame_color.green = SkColorGetG(shifted) * kSkiaToGDKMultiplier; - frame_color.blue = SkColorGetB(shifted) * kSkiaToGDKMultiplier; - } + SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TAB_TEXT, &label_color); + SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, &label_color); // Build the various icon tints. GetNormalButtonTintHSL(&button_tint_); GetNormalEntryForegroundHSL(&entry_tint_); GetSelectedEntryForegroundHSL(&selected_entry_tint_); - - SetThemeTintFromGtk(BrowserThemeProvider::TINT_BUTTONS, &button_color); - SetThemeTintFromGtk(BrowserThemeProvider::TINT_FRAME, &frame_color); - SetThemeTintFromGtk(BrowserThemeProvider::TINT_FRAME_INCOGNITO, &frame_color); - SetThemeTintFromGtk(BrowserThemeProvider::TINT_BACKGROUND_TAB, &frame_color); - - // The inactive color/tint is special: We *must* use the exact insensitive - // color for all inactive windows, otherwise we end up neon pink half the - // time. - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_FRAME_INACTIVE, - &inactive_frame_color); - SetTintToExactColor(BrowserThemeProvider::TINT_FRAME_INACTIVE, - &inactive_frame_color); - SetTintToExactColor(BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE, - &inactive_frame_color); - - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_FRAME, &frame_color); - BuildTintedFrameColor(BrowserThemeProvider::COLOR_FRAME_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INACTIVE); - BuildTintedFrameColor(BrowserThemeProvider::COLOR_FRAME_INCOGNITO, - BrowserThemeProvider::TINT_FRAME_INCOGNITO); - BuildTintedFrameColor(BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE); - - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TOOLBAR, &toolbar_color); - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_TAB_TEXT, &label_color); - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, &label_color); - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND, - &window_style->bg[GTK_STATE_NORMAL]); - SetThemeColorFromGtk(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND, - &window_style->bg[GTK_STATE_NORMAL]); + GdkColor frame_color = BuildFrameColors(frame_style); // The inactive frame color never occurs naturally in the theme, as it is a // tinted version of |frame_color|. We generate another color based on the @@ -794,6 +775,51 @@ void GtkThemeProvider::LoadGtkValues() { GdkToSkColor(&entry_style->text[GTK_STATE_ACTIVE]); } +GdkColor GtkThemeProvider::BuildFrameColors(GtkStyle* frame_style) { + const GdkColor* theme_frame = NULL; + const GdkColor* theme_inactive_frame = NULL; + const GdkColor* theme_incognito_frame = NULL; + const GdkColor* theme_incognito_inactive_frame = NULL; + gtk_widget_style_get(GTK_WIDGET(fake_frame_), + "frame-color", &theme_frame, + "inactive-frame-color", &theme_inactive_frame, + "incognito-frame-color", &theme_incognito_frame, + "incognito-inactive-frame-color", + &theme_incognito_inactive_frame, + NULL); + + GdkColor frame_color = BuildAndSetFrameColor( + &frame_style->bg[GTK_STATE_SELECTED], + theme_frame, + kDefaultFrameShift, + BrowserThemeProvider::COLOR_FRAME, + BrowserThemeProvider::TINT_FRAME); + SetThemeTintFromGtk(BrowserThemeProvider::TINT_BACKGROUND_TAB, &frame_color); + + BuildAndSetFrameColor( + &frame_style->bg[GTK_STATE_INSENSITIVE], + theme_inactive_frame, + kDefaultFrameShift, + BrowserThemeProvider::COLOR_FRAME_INACTIVE, + BrowserThemeProvider::TINT_FRAME_INACTIVE); + + BuildAndSetFrameColor( + &frame_color, + theme_incognito_frame, + GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO), + BrowserThemeProvider::COLOR_FRAME_INCOGNITO, + BrowserThemeProvider::TINT_FRAME_INCOGNITO); + + BuildAndSetFrameColor( + &frame_color, + theme_incognito_inactive_frame, + GetDefaultTint(BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE), + BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE, + BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE); + + return frame_color; +} + void GtkThemeProvider::LoadDefaultValues() { focus_ring_color_ = SkColorSetARGB(255, 229, 151, 0); thumb_active_color_ = SkColorSetRGB(244, 244, 244); @@ -840,16 +866,24 @@ void GtkThemeProvider::SetThemeTintFromGtk(int id, const GdkColor* color) { tints_[id] = hsl; } -void GtkThemeProvider::BuildTintedFrameColor(int color_id, int tint_id) { - colors_[color_id] = HSLShift( - GetDefaultColor(BrowserThemeProvider::COLOR_FRAME), - tints_[tint_id]); -} +GdkColor GtkThemeProvider::BuildAndSetFrameColor(const GdkColor* base, + const GdkColor* gtk_base, + const color_utils::HSL& tint, + int color_id, + int tint_id) { + GdkColor out_color = *base; + if (gtk_base) { + // The theme author specified a color to use, use it without modification. + out_color = *gtk_base; + } else { + // Tint the basic color since this is a heuristic color instead of one + // specified by the theme author. + GdkColorHSLShift(tint, &out_color); + } + SetThemeColorFromGtk(color_id, &out_color); + SetThemeTintFromGtk(tint_id, &out_color); -void GtkThemeProvider::SetTintToExactColor(int id, const GdkColor* color) { - color_utils::HSL hsl; - color_utils::SkColorToHSL(GdkToSkColor(color), &hsl); - tints_[id] = hsl; + return out_color; } void GtkThemeProvider::FreePerDisplaySurfaces( @@ -888,14 +922,18 @@ SkBitmap* GtkThemeProvider::GenerateGtkThemeBitmap(int id) const { case IDR_THEME_TAB_BACKGROUND_INCOGNITO: return GenerateTabImage(IDR_THEME_FRAME_INCOGNITO); case IDR_THEME_FRAME: - return GenerateFrameImage(BrowserThemeProvider::TINT_FRAME); + return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME, + "frame-gradient-color"); case IDR_THEME_FRAME_INACTIVE: - return GenerateFrameImage(BrowserThemeProvider::TINT_FRAME_INACTIVE); + return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INACTIVE, + "inactive-frame-gradient-color"); case IDR_THEME_FRAME_INCOGNITO: - return GenerateFrameImage(BrowserThemeProvider::TINT_FRAME_INCOGNITO); + return GenerateFrameImage(BrowserThemeProvider::COLOR_FRAME_INCOGNITO, + "incognito-frame-gradient-color"); case IDR_THEME_FRAME_INCOGNITO_INACTIVE: { return GenerateFrameImage( - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE); + BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE, + "incognito-inactive-frame-gradient-color"); } // Icons that sit inside the omnibox shouldn't receive TINT_BUTTONS and // instead should tint based on the foreground text entry color in GTK+ @@ -927,13 +965,42 @@ SkBitmap* GtkThemeProvider::GenerateGtkThemeBitmap(int id) const { } } -SkBitmap* GtkThemeProvider::GenerateFrameImage(int tint_id) const { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - scoped_ptr frame(new SkBitmap(*rb.GetBitmapNamed(IDR_THEME_FRAME))); - TintMap::const_iterator it = tints_.find(tint_id); - DCHECK(it != tints_.end()); - return new SkBitmap(SkBitmapOperations::CreateHSLShiftedBitmap(*frame, - it->second)); +SkBitmap* GtkThemeProvider::GenerateFrameImage( + int color_id, + const char* gradient_name) const { + // We use two colors: the main color (passed in) and a lightened version of + // that color (which is supposed to match the light gradient at the top of + // several GTK+ themes, such as Ambiance, Clearlooks or Bluebird). + ColorMap::const_iterator it = colors_.find(color_id); + DCHECK(it != colors_.end()); + SkColor base = it->second; + + gfx::CanvasSkia canvas(kToolbarImageWidth, kToolbarImageHeight, true); + + int gradient_size; + const GdkColor* gradient_top_color = NULL; + gtk_widget_style_get(GTK_WIDGET(fake_frame_), + "frame-gradient-size", &gradient_size, + gradient_name, &gradient_top_color, + NULL); + if (gradient_size) { + SkColor lighter = gradient_top_color ? GdkToSkColor(gradient_top_color) + : color_utils::HSLShift(base, kGtkFrameShift); + SkShader* shader = gfx::CreateGradientShader( + 0, gradient_size, lighter, base); + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setAntiAlias(true); + paint.setShader(shader); + shader->unref(); + + canvas.DrawRectInt(0, 0, kToolbarImageWidth, gradient_size, paint); + } + + canvas.FillRectInt(base, 0, gradient_size, + kToolbarImageWidth, + kToolbarImageHeight - gradient_size); + return new SkBitmap(canvas.ExtractBitmap()); } SkBitmap* GtkThemeProvider::GenerateTabImage(int base_id) const { diff --git a/chrome/browser/gtk/gtk_theme_provider.h b/chrome/browser/gtk/gtk_theme_provider.h index f31d974..630fdbc 100644 --- a/chrome/browser/gtk/gtk_theme_provider.h +++ b/chrome/browser/gtk/gtk_theme_provider.h @@ -84,11 +84,12 @@ class GtkThemeProvider : public BrowserThemeProvider, // label colors for the IDR resource |id|. GtkIconSet* GetIconSetForId(int id) const; - // This method returns averages of the thumb part and of the track colors. - // Used when rendering scrollbars. - static void GetScrollbarColors(GdkColor* thumb_active_color, - GdkColor* thumb_inactive_color, - GdkColor* track_color); + // This method returns the colors webkit will use for the scrollbars. When no + // colors are specified by the GTK+ theme, this function averages of the + // thumb part and of the track colors. + void GetScrollbarColors(GdkColor* thumb_active_color, + GdkColor* thumb_inactive_color, + GdkColor* track_color); // Expose the inner label. Only used for testing. GtkWidget* fake_label() { return fake_label_.get(); } @@ -162,6 +163,10 @@ class GtkThemeProvider : public BrowserThemeProvider, // BrowserThemeProvider interface and the colors we send to webkit. void LoadGtkValues(); + // Reads in explicit theme frame colors from the ChromeGtkFrame style class + // or generates them per our fallback algorithm. + GdkColor BuildFrameColors(GtkStyle* frame_style); + // Sets the values that we send to webkit to safe defaults. void LoadDefaultValues(); @@ -173,8 +178,15 @@ class GtkThemeProvider : public BrowserThemeProvider, // Sets the underlying theme colors/tints from a GTK color. void SetThemeColorFromGtk(int id, const GdkColor* color); void SetThemeTintFromGtk(int id, const GdkColor* color); - void BuildTintedFrameColor(int color_id, int tint_id); - void SetTintToExactColor(int id, const GdkColor* color); + + // Creates and returns a frame color, either using |gtk_base| verbatim if + // non-NULL, or tinting |base| with |tint|. Also sets |color_id| and + // |tint_id| to the returned color. + GdkColor BuildAndSetFrameColor(const GdkColor* base, + const GdkColor* gtk_base, + const color_utils::HSL& tint, + int color_id, + int tint_id); // Split out from FreePlatformCaches so it can be called in our destructor; // FreePlatformCaches() is called from the BrowserThemeProvider's destructor, @@ -188,9 +200,12 @@ class GtkThemeProvider : public BrowserThemeProvider, // Lazily generates each bitmap used in the gtk theme. SkBitmap* GenerateGtkThemeBitmap(int id) const; - // Tints IDR_THEME_FRAME based based on |tint_id|. Used during lazy - // generation of the gtk theme bitmaps. - SkBitmap* GenerateFrameImage(int tint_id) const; + // Creates a GTK+ version of IDR_THEME_FRAME. Instead of tinting, this + // creates a theme configurable gradient ending with |color_id| at the + // bottom, and |gradient_name| at the top if that color is specified in the + // theme. + SkBitmap* GenerateFrameImage(int color_id, + const char* gradient_name) const; // Takes the base frame image |base_id| and tints it with |tint_id|. SkBitmap* GenerateTabImage(int base_id) const; diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc index 74b7423..e07d990 100644 --- a/chrome/browser/gtk/gtk_util.cc +++ b/chrome/browser/gtk/gtk_util.cc @@ -22,11 +22,15 @@ #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/gtk/cairo_cached_surface.h" #include "chrome/browser/gtk/gtk_theme_provider.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/renderer_preferences.h" #include "gfx/gtk_util.h" #include "googleurl/src/gurl.h" @@ -35,10 +39,13 @@ #include "third_party/skia/include/core/SkColor.h" #if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/frame/browser_view.h" #include "chrome/browser/chromeos/native_dialog_window.h" #include "chrome/browser/chromeos/options/options_window_view.h" #include "views/window/window.h" -#endif // defined(OS_CHROMEOS) +#else +#include "chrome/browser/gtk/browser_window_gtk.h" +#endif using WebKit::WebDragOperationsMask; using WebKit::WebDragOperation; @@ -171,6 +178,40 @@ gboolean PaintNoBackground(GtkWidget* widget, return TRUE; } +#if defined(OS_CHROMEOS) + +TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) { + chromeos::BrowserView* browser_view = static_cast( + window); + return browser_view->GetSelectedTabContents(); +} + +GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) { + gfx::NativeView widget = gtk_window_get_focus(window->GetNativeHandle()); + + if (widget == NULL) { + chromeos::BrowserView* browser_view = static_cast( + window); + widget = browser_view->saved_focused_widget(); + } + + return widget; +} + +#else + +TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) { + BrowserWindowGtk* browser_window = static_cast( + window); + return browser_window->browser()->GetSelectedTabContents(); +} + +GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) { + return gtk_window_get_focus(window->GetNativeHandle()); +} + +#endif + } // namespace namespace event_utils { @@ -774,6 +815,7 @@ void DrawTextEntryBackground(GtkWidget* offscreen_entry, rec->width - 2 * xborder, rec->height - 2 * yborder); + gtk_style_detach(our_style); g_object_unref(our_style); } @@ -959,22 +1001,14 @@ bool URLFromPrimarySelection(Profile* profile, GURL* url) { // Use autocomplete to clean up the text, going so far as to turn it into // a search query if necessary. - AutocompleteController controller(profile); - controller.Start(UTF8ToWide(selection_text), - std::wstring(), // desired_tld - true, // prevent_inline_autocomplete - false, // prefer_keyword - true); // synchronous_only + AutocompleteMatch match; + profile->GetAutocompleteClassifier()->Classify(UTF8ToWide(selection_text), + std::wstring(), false, &match, NULL); g_free(selection_text); - const AutocompleteResult& result = controller.result(); - AutocompleteResult::const_iterator it = result.default_match(); - if (it == result.end()) - return false; - - if (!it->destination_url.is_valid()) + if (!match.destination_url.is_valid()) return false; - *url = it->destination_url; + *url = match.destination_url; return true; } @@ -1131,6 +1165,7 @@ gfx::Rect GetDialogBounds(GtkWidget* dialog) { return gfx::Rect(x, y, width, height); } + #endif string16 GetStockPreferencesMenuLabel() { @@ -1215,4 +1250,38 @@ void ApplyMessageDialogQuirks(GtkWidget* dialog) { } } +// Performs Cut/Copy/Paste operation on the |window|. +// If the current render view is focused, then just call the specified |method| +// against the current render view host, otherwise emit the specified |signal| +// against the focused widget. +// TODO(suzhe): This approach does not work for plugins. +void DoCutCopyPaste(BrowserWindow* window, + void (RenderViewHost::*method)(), + const char* signal) { + GtkWidget* widget = GetBrowserWindowFocusedWidget(window); + if (widget == NULL) + return; // Do nothing if no focused widget. + + TabContents* current_tab = GetBrowserWindowSelectedTabContents(window); + if (current_tab && widget == current_tab->GetContentNativeView()) { + (current_tab->render_view_host()->*method)(); + } else { + guint id; + if ((id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0) + g_signal_emit(widget, id, 0); + } +} + +void DoCut(BrowserWindow* window) { + DoCutCopyPaste(window, &RenderViewHost::Cut, "cut-clipboard"); +} + +void DoCopy(BrowserWindow* window) { + DoCutCopyPaste(window, &RenderViewHost::Copy, "copy-clipboard"); +} + +void DoPaste(BrowserWindow* window) { + DoCutCopyPaste(window, &RenderViewHost::Paste, "paste-clipboard"); +} + } // namespace gtk_util diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h index 77beb1f..c8c3c4f 100644 --- a/chrome/browser/gtk/gtk_util.h +++ b/chrome/browser/gtk/gtk_util.h @@ -21,6 +21,7 @@ typedef struct _cairo cairo_t; typedef struct _GdkColor GdkColor; typedef struct _GtkWidget GtkWidget; +class BrowserWindow; class GtkThemeProvider; class GURL; class Profile; @@ -374,6 +375,11 @@ WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action); // gtk_message_dialog_new. void ApplyMessageDialogQuirks(GtkWidget* dialog); +// Performs Cut/Copy/Paste operation on the |window|. +void DoCut(BrowserWindow* window); +void DoCopy(BrowserWindow* window); +void DoPaste(BrowserWindow* window); + } // namespace gtk_util #endif // CHROME_BROWSER_GTK_GTK_UTIL_H_ diff --git a/chrome/browser/gtk/hover_controller_gtk.h b/chrome/browser/gtk/hover_controller_gtk.h index 4806e34..5504720 100644 --- a/chrome/browser/gtk/hover_controller_gtk.h +++ b/chrome/browser/gtk/hover_controller_gtk.h @@ -8,6 +8,7 @@ #include +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "app/gtk_signal_registrar.h" #include "app/slide_animation.h" diff --git a/chrome/browser/gtk/html_dialog_gtk.cc b/chrome/browser/gtk/html_dialog_gtk.cc index 3c9d1fb..2568e83 100644 --- a/chrome/browser/gtk/html_dialog_gtk.cc +++ b/chrome/browser/gtk/html_dialog_gtk.cc @@ -7,12 +7,12 @@ #include #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/dom_ui/html_dialog_ui.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/tab_contents_container_gtk.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/native_web_keyboard_event.h" #include "ipc/ipc_message.h" diff --git a/chrome/browser/gtk/hung_renderer_dialog_gtk.cc b/chrome/browser/gtk/hung_renderer_dialog_gtk.cc index 5cdca15..5dbed52 100644 --- a/chrome/browser/gtk/hung_renderer_dialog_gtk.cc +++ b/chrome/browser/gtk/hung_renderer_dialog_gtk.cc @@ -6,6 +6,7 @@ #include +#include "app/gtk_signal.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/process_util.h" @@ -42,11 +43,7 @@ class HungRendererDialogGtk { // Create the gtk dialog and add the widgets. void Init(); - static void OnDialogResponseThunk(GtkDialog* dialog, gint response_id, - HungRendererDialogGtk* dialog_gtk) { - dialog_gtk->OnDialogResponse(response_id); - } - void OnDialogResponse(gint response_id); + CHROMEGTK_CALLBACK_1(HungRendererDialogGtk, void, OnDialogResponse, gint); GtkDialog* dialog_; GtkListStore* model_; @@ -78,8 +75,8 @@ void HungRendererDialogGtk::Init() { GTK_RESPONSE_OK, NULL)); gtk_dialog_set_default_response(dialog_, GTK_RESPONSE_OK); - g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk), - this); + g_signal_connect(dialog_, "response", + G_CALLBACK(OnDialogResponseThunk), this); // We have an hbox with the frozen icon on the left. On the right, // we have a vbox with the unresponsive text on top and a table of @@ -184,7 +181,8 @@ void HungRendererDialogGtk::EndForTabContents(TabContents* contents) { // When the user clicks a button on the dialog or closes the dialog, this // callback is called. -void HungRendererDialogGtk::OnDialogResponse(gint response_id) { +void HungRendererDialogGtk::OnDialogResponse(GtkWidget* widget, + gint response_id) { DCHECK(g_instance == this); switch (response_id) { case kKillPagesButtonResponse: diff --git a/chrome/browser/gtk/infobar_arrow_model.h b/chrome/browser/gtk/infobar_arrow_model.h index 369e586..721f32b 100644 --- a/chrome/browser/gtk/infobar_arrow_model.h +++ b/chrome/browser/gtk/infobar_arrow_model.h @@ -7,6 +7,7 @@ #include +#include "app/animation_delegate.h" #include "app/slide_animation.h" #include "third_party/skia/include/core/SkPaint.h" diff --git a/chrome/browser/gtk/infobar_gtk.h b/chrome/browser/gtk/infobar_gtk.h index 4293ea8..d0dd542 100644 --- a/chrome/browser/gtk/infobar_gtk.h +++ b/chrome/browser/gtk/infobar_gtk.h @@ -7,7 +7,6 @@ #pragma once #include "app/gtk_signal.h" -#include "app/slide_animation.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "chrome/browser/gtk/infobar_arrow_model.h" diff --git a/chrome/browser/gtk/instant_confirm_dialog_gtk.cc b/chrome/browser/gtk/instant_confirm_dialog_gtk.cc index c313cec..ac4529a 100644 --- a/chrome/browser/gtk/instant_confirm_dialog_gtk.cc +++ b/chrome/browser/gtk/instant_confirm_dialog_gtk.cc @@ -10,10 +10,9 @@ #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/instant/instant_confirm_dialog.h" -#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/instant/instant_controller.h" #include "chrome/browser/profile.h" #include "chrome/browser/show_options_url.h" -#include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" #include "grit/generated_resources.h" @@ -66,13 +65,8 @@ InstantConfirmDialogGtk::~InstantConfirmDialogGtk() { void InstantConfirmDialogGtk::OnDialogResponse(GtkWidget* dialog, int response) { - if (response == GTK_RESPONSE_ACCEPT) { - PrefService* service = profile_->GetPrefs(); - if (service) { - service->SetBoolean(prefs::kInstantEnabled, true); - service->SetBoolean(prefs::kInstantConfirmDialogShown, true); - } - } + if (response == GTK_RESPONSE_ACCEPT) + InstantController::Enable(profile_); delete this; } diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index b207665..65b9545 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -19,7 +19,6 @@ #include "chrome/browser/alternate_nav_url_fetcher.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/content_setting_bubble_model.h" @@ -45,6 +44,7 @@ #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/extensions/extension_resource.h" @@ -548,6 +548,10 @@ void LocationBarViewGtk::OnChanged() { SetSuggestedText(suggested_text); } +void LocationBarViewGtk::OnSelectionBoundsChanged() { + NOTIMPLEMENTED(); +} + void LocationBarViewGtk::CreateStarButton() { star_image_ = gtk_image_new(); diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index 0759549..77e4134 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -61,6 +61,9 @@ class LocationBarViewGtk : public AutocompleteEditController, // Returns the widget the page info bubble should point to. GtkWidget* location_icon_widget() const { return location_icon_image_; } + // Returns the widget the extension installed bubble should point to. + GtkWidget* location_entry_widget() const { return entry_box_; } + // Returns the current TabContents. TabContents* GetTabContents() const; @@ -100,6 +103,7 @@ class LocationBarViewGtk : public AutocompleteEditController, PageTransition::Type transition, const GURL& alternate_nav_url); virtual void OnChanged(); + virtual void OnSelectionBoundsChanged(); virtual void OnKillFocus(); virtual void OnSetFocus(); virtual void OnInputInProgress(bool in_progress); diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc index 86a1ba1..5823f25 100644 --- a/chrome/browser/gtk/menu_gtk.cc +++ b/chrome/browser/gtk/menu_gtk.cc @@ -20,6 +20,7 @@ #include "chrome/browser/gtk/gtk_util.h" #include "gfx/gtk_util.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "webkit/glue/window_open_disposition.h" bool MenuGtk::block_activation_ = false; @@ -693,7 +694,16 @@ void MenuGtk::ExecuteCommand(menus::MenuModel* model, int id) { if (delegate_) delegate_->CommandWillBeExecuted(); - model->ActivatedAt(id); + GdkEvent* event = gtk_get_current_event(); + if (event && event->type == GDK_BUTTON_RELEASE) { + model->ActivatedAtWithDisposition( + id, event_utils::DispositionFromEventFlags(event->button.state)); + } else { + model->ActivatedAt(id); + } + + if (event) + gdk_event_free(event); } void MenuGtk::OnMenuShow(GtkWidget* widget) { diff --git a/chrome/browser/gtk/meta_frames.cc b/chrome/browser/gtk/meta_frames.cc deleted file mode 100644 index e95ac87..0000000 --- a/chrome/browser/gtk/meta_frames.cc +++ /dev/null @@ -1,25 +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/gtk/meta_frames.h" - -G_BEGIN_DECLS - -G_DEFINE_TYPE(MetaFrames, meta_frames, GTK_TYPE_WINDOW) - -static void meta_frames_class_init(MetaFramesClass* frames_class) { - // Noop since we don't declare anything. -} - -static void meta_frames_init(MetaFrames* button) { -} - -GtkWidget* meta_frames_new(void) { - GtkWindow* window = - GTK_WINDOW(g_object_new(meta_frames_get_type(), NULL)); - window->type = GTK_WINDOW_TOPLEVEL; - return GTK_WIDGET(window); -} - -G_END_DECLS diff --git a/chrome/browser/gtk/meta_frames.h b/chrome/browser/gtk/meta_frames.h deleted file mode 100644 index bc8a493..0000000 --- a/chrome/browser/gtk/meta_frames.h +++ /dev/null @@ -1,39 +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_GTK_META_FRAMES_H_ -#define CHROME_BROWSER_GTK_META_FRAMES_H_ -#pragma once - -#include -#include - -G_BEGIN_DECLS - -// For the sake of gtk+ theme integration, we define a class called -// "MetaFrames," which is the name of a gobject class in the metacity window -// manager. To actually get at those values, we need to have an object whose -// gobject class name string matches the definitions in the gtkrc -// file. MetaFrames derives from GtkWindow. -// -// TODO(erg): http://crbug.com/35317 for getting rid of this hack class, as we -// should be able to use gtk_rc_get_style_by_path() but can't? - -typedef struct _MetaFrames MetaFrames; -typedef struct _MetaFramesClass MetaFramesClass; - -struct _MetaFrames { - GtkWindow window; -}; - -struct _MetaFramesClass { - GtkWindowClass parent_class; -}; - -// Creates a GtkWindow object with the class name "MetaFrames". -GtkWidget* meta_frames_new(); - -G_END_DECLS - -#endif // CHROME_BROWSER_GTK_META_FRAMES_H_ diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.h b/chrome/browser/gtk/notifications/balloon_view_gtk.h index 652a610..dce5869 100644 --- a/chrome/browser/gtk/notifications/balloon_view_gtk.h +++ b/chrome/browser/gtk/notifications/balloon_view_gtk.h @@ -8,7 +8,7 @@ #define CHROME_BROWSER_GTK_NOTIFICATIONS_BALLOON_VIEW_GTK_H_ #pragma once -#include "app/animation.h" +#include "app/animation_delegate.h" #include "app/gtk_signal.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.cc b/chrome/browser/gtk/options/advanced_contents_gtk.cc index f98490e..6ea7a49 100644 --- a/chrome/browser/gtk/options/advanced_contents_gtk.cc +++ b/chrome/browser/gtk/options/advanced_contents_gtk.cc @@ -25,6 +25,7 @@ #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/fonts_languages_window.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" #include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" @@ -43,6 +44,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/process_watcher.h" +#include "chrome/common/url_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -882,9 +884,9 @@ void PrivacySection::OnClearBrowsingDataButtonClicked(GtkButton* widget, // static void PrivacySection::OnLearnMoreLinkClicked(GtkButton *button, PrivacySection* privacy_section) { - browser::ShowOptionsURL( - privacy_section->profile(), - GURL(l10n_util::GetStringUTF8(IDS_LEARN_MORE_PRIVACY_URL))); + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kPrivacyLearnMoreURL)); + browser::ShowOptionsURL(privacy_section->profile(), url); } // static diff --git a/chrome/browser/gtk/options/content_filter_page_gtk.cc b/chrome/browser/gtk/options/content_filter_page_gtk.cc index 6645a22..93c804e 100644 --- a/chrome/browser/gtk/options/content_filter_page_gtk.cc +++ b/chrome/browser/gtk/options/content_filter_page_gtk.cc @@ -6,12 +6,11 @@ #include "app/l10n_util.h" #include "base/command_line.h" -#include "chrome/browser/browser.h" #include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/geolocation/geolocation_exceptions_table_model.h" -#include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/plugin_exceptions_table_model.h" #include "chrome/browser/profile.h" +#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_util.h" @@ -20,8 +19,8 @@ #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/notifications/notification_exceptions_table_model.h" #include "chrome/browser/show_options_url.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -30,7 +29,8 @@ ContentFilterPageGtk::ContentFilterPageGtk(Profile* profile, ContentSettingsType content_type) : OptionsPageBase(profile), content_type_(content_type), - ask_radio_(NULL) { + ask_radio_(NULL), + ignore_toggle_(false) { static const int kTitleIDs[] = { 0, // This dialog isn't used for cookies. IDS_IMAGES_SETTING_LABEL, @@ -83,10 +83,17 @@ GtkWidget* ContentFilterPageGtk::InitGroup() { }; COMPILE_ASSERT(arraysize(kAskIDs) == CONTENT_SETTINGS_NUM_TYPES, kAskIDs_IncorrectSize); - if (kAskIDs[content_type_]) { + int askID = kAskIDs[content_type_]; + if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS && + !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)) { + askID = 0; + } + + if (askID) { ask_radio_ = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(allow_radio_), - l10n_util::GetStringUTF8(kAskIDs[content_type_]).c_str()); + l10n_util::GetStringUTF8(askID).c_str()); gtk_box_pack_start(GTK_BOX(vbox), ask_radio_, FALSE, FALSE, 0); } @@ -106,31 +113,12 @@ GtkWidget* ContentFilterPageGtk::InitGroup() { l10n_util::GetStringUTF8(kBlockIDs[content_type_]).c_str()); gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0); - ContentSetting default_setting; - if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) { - default_setting = profile()->GetGeolocationContentSettingsMap()-> - GetDefaultContentSetting(); - } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { - default_setting = profile()->GetDesktopNotificationService()-> - GetDefaultContentSetting(); - } else { - default_setting = profile()->GetHostContentSettingsMap()-> - GetDefaultContentSetting(content_type_); - } - // Now that these have been added to the view hierarchy, it's safe to call - // SetChecked() on them. - if (default_setting == CONTENT_SETTING_ALLOW) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE); - } else if (default_setting == CONTENT_SETTING_ASK) { - DCHECK(ask_radio_); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_radio_), TRUE); - } else { - DCHECK(default_setting == CONTENT_SETTING_BLOCK); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE); - } + exceptions_button_ = gtk_button_new_with_label( + l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str()); + GtkWidget* hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), exceptions_button_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - // Now that we've set the default value, we can connect to the radio button's - // toggled signal. g_signal_connect(G_OBJECT(allow_radio_), "toggled", G_CALLBACK(OnAllowToggledThunk), this); if (ask_radio_) { @@ -140,15 +128,9 @@ GtkWidget* ContentFilterPageGtk::InitGroup() { g_signal_connect(G_OBJECT(block_radio_), "toggled", G_CALLBACK(OnAllowToggledThunk), this); - GtkWidget* exceptions_button = gtk_button_new_with_label( - l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str()); - g_signal_connect(G_OBJECT(exceptions_button), "clicked", + g_signal_connect(G_OBJECT(exceptions_button_), "clicked", G_CALLBACK(OnExceptionsClickedThunk), this); - GtkWidget* hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), exceptions_button, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - // Add the "Disable individual plug-ins..." link on the plug-ins page. if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) { GtkWidget* plugins_page_link = gtk_chrome_link_button_new( @@ -161,18 +143,75 @@ GtkWidget* ContentFilterPageGtk::InitGroup() { gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); } + // Now that the buttons have been added to the view hierarchy, it's safe to + // call SetChecked() on them. So Update the Buttons. + ignore_toggle_ = true; + UpdateButtonsState(); + ignore_toggle_ = false; + + // Register for CONTENT_SETTINGS_CHANGED notifications to update the UI + // aften content settings change. + registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED, + NotificationService::AllSources()); + return vbox; } +void ContentFilterPageGtk::UpdateButtonsState() { + // Get default_setting. + ContentSetting default_setting; + if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) { + default_setting = profile()->GetGeolocationContentSettingsMap()-> + GetDefaultContentSetting(); + } else if (content_type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { + default_setting = profile()->GetDesktopNotificationService()-> + GetDefaultContentSetting(); + } else { + default_setting = profile()->GetHostContentSettingsMap()-> + GetDefaultContentSetting(content_type_); + } + // Set UI state. + if (default_setting == CONTENT_SETTING_ALLOW) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE); + } else if (default_setting == CONTENT_SETTING_ASK) { + DCHECK(ask_radio_); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_radio_), TRUE); + } else { + DCHECK(default_setting == CONTENT_SETTING_BLOCK); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE); + } + + // Disable the UI if the default content setting is managed. + bool sensitive = !profile()->GetHostContentSettingsMap()-> + IsDefaultContentSettingManaged(content_type_); + gtk_widget_set_sensitive(allow_radio_, sensitive); + gtk_widget_set_sensitive(block_radio_, sensitive); + if (ask_radio_) + gtk_widget_set_sensitive(ask_radio_, sensitive); + gtk_widget_set_sensitive(exceptions_button_, sensitive); +} + void ContentFilterPageGtk::OnAllowToggled(GtkWidget* toggle_button) { + if (ignore_toggle_) + return; + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) { + // When selecting a radio button, we get two signals (one for the old radio + // being toggled off, one for the new one being toggled on.) Ignore the + // signal for toggling off the old button. + return; + } + DCHECK((toggle_button == allow_radio_) || (toggle_button == ask_radio_) || (toggle_button == block_radio_)); + ContentSetting default_setting = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(allow_radio_)) ? CONTENT_SETTING_ALLOW : gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(block_radio_)) ? CONTENT_SETTING_BLOCK : CONTENT_SETTING_ASK; + DCHECK(ask_radio_ || default_setting != CONTENT_SETTING_ASK); if (content_type_ == CONTENT_SETTINGS_TYPE_GEOLOCATION) { profile()->GetGeolocationContentSettingsMap()->SetDefaultContentSetting( @@ -229,3 +268,25 @@ void ContentFilterPageGtk::OnExceptionsClicked(GtkWidget* button) { void ContentFilterPageGtk::OnPluginsPageLinkClicked(GtkWidget* button) { browser::ShowOptionsURL(profile(), GURL(chrome::kChromeUIPluginsURL)); } + +void ContentFilterPageGtk::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + + if (type == NotificationType::CONTENT_SETTINGS_CHANGED) { + NotifyContentSettingsChanged( + Details(details).ptr()); + } else { + OptionsPageBase::Observe(type, source, details); + } +} + +void ContentFilterPageGtk::NotifyContentSettingsChanged( + const HostContentSettingsMap::ContentSettingsDetails *details) { + if (details->type() == CONTENT_SETTINGS_TYPE_DEFAULT || + details->type() == content_type_) { + ignore_toggle_ = true; + UpdateButtonsState(); + ignore_toggle_ = false; + } +} diff --git a/chrome/browser/gtk/options/content_filter_page_gtk.h b/chrome/browser/gtk/options/content_filter_page_gtk.h index 614178e..e3c2d6a 100644 --- a/chrome/browser/gtk/options/content_filter_page_gtk.h +++ b/chrome/browser/gtk/options/content_filter_page_gtk.h @@ -10,7 +10,10 @@ #include "app/gtk_signal.h" #include "chrome/browser/options_page_base.h" +#include "chrome/browser/host_content_settings_map.h" +#include "chrome/common/content_settings.h" #include "chrome/common/content_settings_types.h" +#include "chrome/common/notification_registrar.h" // A page in the content settings window. Used for everything but the Cookies // page (which has a much more complex dialog). A |content_type| is passed into @@ -24,7 +27,19 @@ class ContentFilterPageGtk : public OptionsPageBase { return page_; } + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: + // This method is called during initialization to set the initial state of the + // buttons and called after a default content setting change (either value + // change or "is managed" state). + virtual void UpdateButtonsState(); + + virtual void NotifyContentSettingsChanged( + const HostContentSettingsMap::ContentSettingsDetails *details); + // Builds the content of the dialog. GtkWidget* InitGroup(); @@ -41,6 +56,14 @@ class ContentFilterPageGtk : public OptionsPageBase { GtkWidget* ask_radio_; GtkWidget* block_radio_; + GtkWidget* exceptions_button_; + + NotificationRegistrar registrar_; + + // If state of the UI is not changed by a user-action we need to ignore + // "toggled" events. + bool ignore_toggle_; + DISALLOW_COPY_AND_ASSIGN(ContentFilterPageGtk); }; diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc index c75028a..5cfe3b7 100644 --- a/chrome/browser/gtk/options/content_page_gtk.cc +++ b/chrome/browser/gtk/options/content_page_gtk.cc @@ -9,9 +9,6 @@ #include "app/l10n_util.h" #include "base/command_line.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/defaults.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_theme_provider.h" @@ -22,6 +19,9 @@ #include "chrome/browser/importer/importer_data_types.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/sync/sync_ui_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/gtk/options/content_settings_window_gtk.cc b/chrome/browser/gtk/options/content_settings_window_gtk.cc index 7b2c9e5..d890a2a 100644 --- a/chrome/browser/gtk/options/content_settings_window_gtk.cc +++ b/chrome/browser/gtk/options/content_settings_window_gtk.cc @@ -9,8 +9,6 @@ #include "app/l10n_util.h" #include "base/command_line.h" #include "base/message_loop.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" @@ -18,6 +16,8 @@ #include "chrome/browser/gtk/gtk_tree.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/content_settings_types.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/gtk/options/cookie_filter_page_gtk.cc b/chrome/browser/gtk/options/cookie_filter_page_gtk.cc index 9b63262..66eac73 100644 --- a/chrome/browser/gtk/options/cookie_filter_page_gtk.cc +++ b/chrome/browser/gtk/options/cookie_filter_page_gtk.cc @@ -5,8 +5,8 @@ #include "chrome/browser/gtk/options/cookie_filter_page_gtk.h" #include "app/l10n_util.h" +#include "base/auto_reset.h" #include "base/command_line.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browsing_data_local_storage_helper.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" @@ -16,6 +16,7 @@ #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/profile.h" #include "chrome/browser/show_options_url.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "grit/generated_resources.h" @@ -34,32 +35,40 @@ GtkWidget* WrapInHBox(GtkWidget* widget) { CookieFilterPageGtk::CookieFilterPageGtk(Profile* profile) : OptionsPageBase(profile), - initializing_(true) { + ignore_toggle_(false) { + // The pref members must be initialized first since the pref values are read + // afterwards when we initialize the cookie storing group. + clear_site_data_on_exit_.Init(prefs::kClearSiteDataOnExit, + profile->GetPrefs(), this); + + block_third_party_cookies_.Init(prefs::kBlockThirdPartyCookies, + profile->GetPrefs(), this); + + managed_default_cookies_setting_.Init(prefs::kManagedDefaultCookiesSetting, + profile->GetPrefs(), this); + GtkWidget* title_label = gtk_util::CreateBoldLabel( l10n_util::GetStringUTF8(IDS_MODIFY_COOKIE_STORING_LABEL)); page_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); gtk_box_pack_start(GTK_BOX(page_), title_label, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(page_), InitCookieStoringGroup()); - - clear_site_data_on_exit_.Init(prefs::kClearSiteDataOnExit, - profile->GetPrefs(), NULL); - - // Load initial values - NotifyPrefChanged(NULL); } CookieFilterPageGtk::~CookieFilterPageGtk() { } void CookieFilterPageGtk::NotifyPrefChanged(const std::string* pref_name) { - initializing_ = true; + AutoReset toggle_guard(&ignore_toggle_, true); if (!pref_name || *pref_name == prefs::kClearSiteDataOnExit) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clear_on_close_check_), - clear_site_data_on_exit_.GetValue()); + UpdateUiState(); + } + if (!pref_name || *pref_name == prefs::kManagedDefaultCookiesSetting) { + UpdateUiState(); + } + if (!pref_name || *pref_name == prefs::kBlockThirdPartyCookies) { + UpdateUiState(); } - - initializing_ = false; } void CookieFilterPageGtk::HighlightGroup(OptionsGroup highlight_group) { @@ -82,36 +91,15 @@ GtkWidget* CookieFilterPageGtk::InitCookieStoringGroup() { G_CALLBACK(OnCookiesAllowToggledThunk), this); gtk_box_pack_start(GTK_BOX(vbox), block_radio_, FALSE, FALSE, 0); - // Set up the current value for the button. - const HostContentSettingsMap* settings_map = - profile()->GetHostContentSettingsMap(); - ContentSetting default_setting = - settings_map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES); - // Now that these have been added to the view hierarchy, it's safe to call - // SetChecked() on them. - GtkWidget* radio_button = NULL; - if (default_setting == CONTENT_SETTING_ALLOW) { - radio_button = allow_radio_; - } else if (default_setting == CONTENT_SETTING_BLOCK) { - radio_button = block_radio_; - } else { - DCHECK(default_setting == CONTENT_SETTING_ASK); - radio_button = ask_every_time_radio_; - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE); - - // Exception button. - GtkWidget* exceptions_button = gtk_button_new_with_label( + exceptions_button_ = gtk_button_new_with_label( l10n_util::GetStringUTF8(IDS_COOKIES_EXCEPTIONS_BUTTON).c_str()); - g_signal_connect(G_OBJECT(exceptions_button), "clicked", + g_signal_connect(G_OBJECT(exceptions_button_), "clicked", G_CALLBACK(OnExceptionsClickedThunk), this); - gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(exceptions_button), + gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(exceptions_button_), FALSE, FALSE, 0); block_3rdparty_check_ = gtk_check_button_new_with_label( l10n_util::GetStringUTF8(IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX).c_str()); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_3rdparty_check_), - settings_map->BlockThirdPartyCookies()); g_signal_connect(G_OBJECT(block_3rdparty_check_), "toggled", G_CALLBACK(OnBlockThirdPartyToggledThunk), this); gtk_box_pack_start(GTK_BOX(vbox), block_3rdparty_check_, FALSE, FALSE, 0); @@ -136,11 +124,47 @@ GtkWidget* CookieFilterPageGtk::InitCookieStoringGroup() { gtk_box_pack_start(GTK_BOX(vbox), WrapInHBox(flash_settings_link), FALSE, FALSE, 0); + ignore_toggle_ = true; + UpdateUiState(); + ignore_toggle_ = false; + return vbox; }; +void CookieFilterPageGtk::UpdateUiState() { + // Get default_setting. + ContentSetting default_setting; + default_setting = profile()->GetHostContentSettingsMap()-> + GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES); + + // Set UI state. + if (default_setting == CONTENT_SETTING_ALLOW) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(allow_radio_), TRUE); + } else { + DCHECK(default_setting == CONTENT_SETTING_BLOCK); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(block_radio_), TRUE); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(clear_on_close_check_), + clear_site_data_on_exit_.GetValue()); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(block_3rdparty_check_), + block_third_party_cookies_.GetValue()); + + // Disable the UI if the default content setting is managed. + gtk_widget_set_sensitive(block_3rdparty_check_, + !block_third_party_cookies_.IsManaged()); + bool sensitive = true; + if (profile()->GetHostContentSettingsMap()->IsDefaultContentSettingManaged( + CONTENT_SETTINGS_TYPE_COOKIES)) { + sensitive = false; + } + gtk_widget_set_sensitive(allow_radio_, sensitive); + gtk_widget_set_sensitive(block_radio_, sensitive); + gtk_widget_set_sensitive(exceptions_button_, sensitive); +} + void CookieFilterPageGtk::OnCookiesAllowToggled(GtkWidget* toggle_button) { - if (initializing_) + if (ignore_toggle_) return; if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) { @@ -153,8 +177,6 @@ void CookieFilterPageGtk::OnCookiesAllowToggled(GtkWidget* toggle_button) { ContentSetting setting = CONTENT_SETTING_ALLOW; if (toggle_button == allow_radio_) setting = CONTENT_SETTING_ALLOW; - else if (toggle_button == ask_every_time_radio_) - setting = CONTENT_SETTING_ASK; else if (toggle_button == block_radio_) setting = CONTENT_SETTING_BLOCK; @@ -174,7 +196,7 @@ void CookieFilterPageGtk::OnExceptionsClicked(GtkWidget* button) { } void CookieFilterPageGtk::OnBlockThirdPartyToggled(GtkWidget* toggle_button) { - if (initializing_) + if (ignore_toggle_) return; HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap(); @@ -183,7 +205,7 @@ void CookieFilterPageGtk::OnBlockThirdPartyToggled(GtkWidget* toggle_button) { } void CookieFilterPageGtk::OnClearOnCloseToggled(GtkWidget* toggle_button) { - if (initializing_) + if (ignore_toggle_) return; clear_site_data_on_exit_.SetValue( diff --git a/chrome/browser/gtk/options/cookie_filter_page_gtk.h b/chrome/browser/gtk/options/cookie_filter_page_gtk.h index 2825d0e..37c0ce3 100644 --- a/chrome/browser/gtk/options/cookie_filter_page_gtk.h +++ b/chrome/browser/gtk/options/cookie_filter_page_gtk.h @@ -11,6 +11,7 @@ #include #include "app/gtk_signal.h" +#include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/options_page_base.h" #include "chrome/browser/prefs/pref_member.h" @@ -29,6 +30,9 @@ class CookieFilterPageGtk : public OptionsPageBase { } private: + // Updates the UI state. + virtual void UpdateUiState(); + // Overridden from OptionsPageBase virtual void NotifyPrefChanged(const std::string* pref_name); virtual void HighlightGroup(OptionsGroup highlight_group); @@ -44,7 +48,6 @@ class CookieFilterPageGtk : public OptionsPageBase { // Widgets of the cookie storing group GtkWidget* allow_radio_; - GtkWidget* ask_every_time_radio_; GtkWidget* block_radio_; GtkWidget* exceptions_button_; @@ -55,13 +58,19 @@ class CookieFilterPageGtk : public OptionsPageBase { // The parent GtkTable widget GtkWidget* page_; - // Whether we're currently setting values (and thus should ignore "toggled" - // events). - bool initializing_; + // If state of the UI is not changed by a user-action we need to ignore + // "toggled" events. + bool ignore_toggle_; // Clear locally stored site data on exit pref. BooleanPrefMember clear_site_data_on_exit_; + // Block third-party-cookies. + BooleanPrefMember block_third_party_cookies_; + + // Managed default-cookies-setting. + IntegerPrefMember managed_default_cookies_setting_; + DISALLOW_COPY_AND_ASSIGN(CookieFilterPageGtk); }; diff --git a/chrome/browser/gtk/options/general_page_gtk.cc b/chrome/browser/gtk/options/general_page_gtk.cc index 01aef9e..3ce8f45 100644 --- a/chrome/browser/gtk/options/general_page_gtk.cc +++ b/chrome/browser/gtk/options/general_page_gtk.cc @@ -20,6 +20,7 @@ #include "chrome/browser/gtk/options/options_layout_gtk.h" #include "chrome/browser/gtk/options/url_picker_dialog_gtk.h" #include "chrome/browser/instant/instant_confirm_dialog.h" +#include "chrome/browser/instant/instant_controller.h" #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/session_startup_pref.h" @@ -555,7 +556,7 @@ void GeneralPageGtk::OnInstantToggled(GtkWidget* toggle_button) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(instant_checkbox_), false); browser::ShowInstantConfirmDialogIfNecessary(GetWindow(), profile()); } else { - instant_.SetValue(enabled); + InstantController::Disable(profile()); } // TODO(estade): UMA? diff --git a/chrome/browser/gtk/page_info_bubble_gtk.cc b/chrome/browser/gtk/page_info_bubble_gtk.cc index cfb54de..6bfa77c 100644 --- a/chrome/browser/gtk/page_info_bubble_gtk.cc +++ b/chrome/browser/gtk/page_info_bubble_gtk.cc @@ -11,6 +11,7 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/certificate_viewer.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/gtk/browser_toolbar_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" @@ -23,6 +24,7 @@ #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" +#include "chrome/common/url_constants.h" #include "googleurl/src/gurl.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -270,7 +272,8 @@ void PageInfoBubbleGtk::OnViewCertLinkClicked(GtkWidget* widget) { } void PageInfoBubbleGtk::OnHelpLinkClicked(GtkWidget* widget) { - GURL url = GURL(l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER)); + GURL url = google_util::AppendGoogleLocaleParam( + GURL(chrome::kPageInfoHelpCenterURL)); Browser* browser = BrowserList::GetLastActive(); browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); bubble_->Close(); diff --git a/chrome/browser/gtk/reload_button_gtk.cc b/chrome/browser/gtk/reload_button_gtk.cc index 70ae71e..6725dbb 100644 --- a/chrome/browser/gtk/reload_button_gtk.cc +++ b/chrome/browser/gtk/reload_button_gtk.cc @@ -7,11 +7,11 @@ #include "app/l10n_util.h" #include "base/logging.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/gtk_chrome_button.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/location_bar_view_gtk.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" diff --git a/chrome/browser/gtk/sad_tab_gtk.cc b/chrome/browser/gtk/sad_tab_gtk.cc index 569c53f..80612f7 100644 --- a/chrome/browser/gtk/sad_tab_gtk.cc +++ b/chrome/browser/gtk/sad_tab_gtk.cc @@ -8,9 +8,11 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "chrome/browser/google/google_util.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" @@ -112,7 +114,8 @@ SadTabGtk::~SadTabGtk() { void SadTabGtk::OnLinkButtonClick(GtkWidget* sender) { if (tab_contents_ != NULL) { - tab_contents_->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_CRASH_REASON_URL)), - GURL(), CURRENT_TAB, PageTransition::LINK); + GURL help_url = + google_util::AppendGoogleLocaleParam(GURL(chrome::kCrashReasonURL)); + tab_contents_->OpenURL(help_url, GURL(), CURRENT_TAB, PageTransition::LINK); } } diff --git a/chrome/browser/gtk/slide_animator_gtk.h b/chrome/browser/gtk/slide_animator_gtk.h index df6d29b..dabdd70 100644 --- a/chrome/browser/gtk/slide_animator_gtk.h +++ b/chrome/browser/gtk/slide_animator_gtk.h @@ -17,7 +17,7 @@ #include -#include "app/animation.h" +#include "app/animation_delegate.h" #include "base/scoped_ptr.h" #include "chrome/browser/gtk/owned_widget_gtk.h" diff --git a/chrome/browser/gtk/status_bubble_gtk.cc b/chrome/browser/gtk/status_bubble_gtk.cc index fbb8989..08eab1a 100644 --- a/chrome/browser/gtk/status_bubble_gtk.cc +++ b/chrome/browser/gtk/status_bubble_gtk.cc @@ -8,6 +8,7 @@ #include +#include "app/slide_animation.h" #include "app/text_elider.h" #include "base/i18n/rtl.h" #include "base/message_loop.h" diff --git a/chrome/browser/gtk/status_bubble_gtk.h b/chrome/browser/gtk/status_bubble_gtk.h index 1706665..b951b79 100644 --- a/chrome/browser/gtk/status_bubble_gtk.h +++ b/chrome/browser/gtk/status_bubble_gtk.h @@ -10,8 +10,8 @@ #include +#include "app/animation_delegate.h" #include "app/gtk_signal.h" -#include "app/slide_animation.h" #include "base/scoped_ptr.h" #include "base/timer.h" #include "chrome/browser/gtk/owned_widget_gtk.h" @@ -23,6 +23,7 @@ class GtkThemeProvider; class Profile; +class SlideAnimation; // GTK implementation of StatusBubble. Unlike Windows, our status bubble // doesn't have the nice leave-the-window effect since we can't rely on the diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc index 5df0ea7..8ae9fd5 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc @@ -7,7 +7,6 @@ #include #include "base/callback.h" -#include "chrome/browser/browser.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/tabs/dragged_tab_gtk.h" @@ -15,6 +14,7 @@ #include "chrome/browser/platform_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" namespace { diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h index 38c6525..6d7fcc4 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.h @@ -8,6 +8,7 @@ #include +#include "app/animation_delegate.h" #include "app/slide_animation.h" #include "base/callback.h" #include "base/scoped_ptr.h" diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index 318fcbe..5afd379 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -9,9 +9,9 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "app/slide_animation.h" #include "app/throb_animation.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/defaults.h" #include "chrome/browser/gtk/bookmark_utils_gtk.h" #include "chrome/browser/gtk/custom_button.h" @@ -19,9 +19,11 @@ #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_service.h" #include "gfx/canvas_skia_paint.h" #include "gfx/favicon_size.h" +#include "gfx/platform_font_gtk.h" #include "gfx/skbitmap_operations.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -1070,10 +1072,11 @@ void TabRendererGtk::InitResources() { LoadTabImages(); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - // Force the font size to 9pt, which matches Windows' default font size - // (taken from the system). const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); - title_font_ = new gfx::Font(base_font.GetFontName(), 9); + // Dividing by the pango scale factor maintains an absolute pixel size across + // all DPIs. + int size = static_cast(13 / gfx::PlatformFontGtk::GetPangoScaleFactor()); + title_font_ = new gfx::Font(base_font.GetFontName(), size); title_font_height_ = title_font_->GetHeight(); crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON); diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h index 51f11b7..6849a2a 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -9,9 +9,8 @@ #include #include -#include "app/animation.h" +#include "app/animation_delegate.h" #include "app/gtk_signal.h" -#include "app/slide_animation.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "base/string16.h" @@ -29,6 +28,7 @@ class Size; class CustomDrawButton; class GtkThemeProvider; +class SlideAnimation; class TabContents; class ThemeProvider; class ThrobAnimation; diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 0547815..41d1e27 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -6,6 +6,7 @@ #include +#include "app/animation_delegate.h" #include "app/gtk_dnd_util.h" #include "app/resource_bundle.h" #include "app/slide_animation.h" @@ -21,6 +22,8 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model_delegate.h" #include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" #include "gfx/gtk_util.h" @@ -1612,20 +1615,19 @@ bool TabStripGtk::CompleteDrop(guchar* data) { if (!url.is_valid()) return false; + browser::NavigateParams params(window()->browser(), url, + PageTransition::LINK); + params.tabstrip_index = drop_index; + if (drop_before) { - // Insert a new tab. - TabContents* contents = - model_->delegate()->CreateTabContentsForURL( - url, GURL(), model_->profile(), PageTransition::TYPED, false, - NULL); - model_->AddTabContents(contents, drop_index, PageTransition::GENERATED, - TabStripModel::ADD_SELECTED); + params.disposition = NEW_FOREGROUND_TAB; } else { - model_->GetTabContentsAt(drop_index)->controller().LoadURL( - url, GURL(), PageTransition::GENERATED); - model_->SelectTabContentsAt(drop_index, true); + params.disposition = CURRENT_TAB; + params.source_contents = model_->GetTabContentsAt(drop_index); } + browser::Navigate(¶ms); + return true; } @@ -1974,19 +1976,9 @@ void TabStripGtk::OnNewTabClicked(GtkWidget* widget) { if (!gtk_util::URLFromPrimarySelection(model_->profile(), &url)) return; - TabContents* contents = - model_->delegate()->CreateTabContentsForURL( - url, - GURL(), // referrer - model_->profile(), - PageTransition::TYPED, - false, // defer_load - NULL); // instance - model_->AddTabContents( - contents, - -1, // index - PageTransition::TYPED, - TabStripModel::ADD_SELECTED); + Browser* browser = window_->browser(); + DCHECK(browser); + browser->AddSelectedTabWithURL(url, PageTransition::TYPED); break; } default: diff --git a/chrome/browser/gtk/task_manager_gtk.cc b/chrome/browser/gtk/task_manager_gtk.cc index ad7137d..fcb9817 100644 --- a/chrome/browser/gtk/task_manager_gtk.cc +++ b/chrome/browser/gtk/task_manager_gtk.cc @@ -19,6 +19,7 @@ #include "base/logging.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/defaults.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_tree.h" @@ -426,6 +427,12 @@ void TaskManagerGtk::Init() { kTaskManagerPurgeMemory); } + if (browser_defaults::kShowCancelButtonInTaskManager) { + gtk_dialog_add_button(GTK_DIALOG(dialog_), + l10n_util::GetStringUTF8(IDS_CLOSE).c_str(), + GTK_RESPONSE_DELETE_EVENT); + } + gtk_dialog_add_button(GTK_DIALOG(dialog_), l10n_util::GetStringUTF8(IDS_TASK_MANAGER_KILL).c_str(), kTaskManagerResponseKill); diff --git a/chrome/browser/gtk/translate/translate_infobar_base_gtk.h b/chrome/browser/gtk/translate/translate_infobar_base_gtk.h index ce851f9..8b2303b 100644 --- a/chrome/browser/gtk/translate/translate_infobar_base_gtk.h +++ b/chrome/browser/gtk/translate/translate_infobar_base_gtk.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_GTK_TRANSLATE_TRANSLATE_INFOBAR_BASE_GTK_H_ #pragma once +#include "app/animation_delegate.h" #include "chrome/browser/translate/translate_infobar_view.h" #include "chrome/browser/gtk/infobar_gtk.h" diff --git a/chrome/browser/gtk/view_id_util_browsertest.cc b/chrome/browser/gtk/view_id_util_browsertest.cc index be4f38c..58ff80d 100644 --- a/chrome/browser/gtk/view_id_util_browsertest.cc +++ b/chrome/browser/gtk/view_id_util_browsertest.cc @@ -4,9 +4,9 @@ #include -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/gtk/view_id_util.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h index 9d2fd20..3fe34ba 100644 --- a/chrome/browser/history/history.h +++ b/chrome/browser/history/history.h @@ -408,7 +408,7 @@ class HistoryService : public CancelableRequestProvider, // Implemented by the caller of 'CreateDownload' below, and is called when the // history service has created a new entry for a download in the history db. - typedef Callback2::Type + typedef Callback2::Type DownloadCreateCallback; // Begins a history request to create a new persistent entry for a download. diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc index b35e727..d06aaf8 100644 --- a/chrome/browser/history/history_browsertest.cc +++ b/chrome/browser/history/history_browsertest.cc @@ -4,10 +4,10 @@ #include -#include "chrome/browser/browser.h" #include "chrome/browser/history/history.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/history/redirect_uitest.cc b/chrome/browser/history/redirect_uitest.cc index 55e1961..91b7317 100644 --- a/chrome/browser/history/redirect_uitest.cc +++ b/chrome/browser/history/redirect_uitest.cc @@ -89,7 +89,8 @@ TEST_F(RedirectTest, Client) { EXPECT_TRUE(final_url == tab_url); } -TEST_F(RedirectTest, ClientEmptyReferer) { +// http://code.google.com/p/chromium/issues/detail?id=62772 +TEST_F(RedirectTest, FLAKY_ClientEmptyReferer) { ASSERT_TRUE(test_server_.Start()); // Create the file contents, which will do a redirect to the diff --git a/chrome/browser/history/text_database.cc b/chrome/browser/history/text_database.cc index 60aa7fd..6bf3270 100644 --- a/chrome/browser/history/text_database.cc +++ b/chrome/browser/history/text_database.cc @@ -88,8 +88,8 @@ FilePath TextDatabase::IDToFileName(DBIdent id) { // scheme: the caller should assign IDs as it feels fit with the knowledge // that they will apppear on disk in this form. FilePath::StringType filename(file_base()); - StringAppendF(&filename, FILE_PATH_LITERAL("%d-%02d"), - id / 100, id % 100); + base::StringAppendF(&filename, FILE_PATH_LITERAL("%d-%02d"), + id / 100, id % 100); return FilePath(filename); } diff --git a/chrome/browser/history/top_sites_database.cc b/chrome/browser/history/top_sites_database.cc index 8bfbcaf..4639494 100644 --- a/chrome/browser/history/top_sites_database.cc +++ b/chrome/browser/history/top_sites_database.cc @@ -5,6 +5,7 @@ #include "app/sql/connection.h" #include "app/sql/transaction.h" #include "base/file_util.h" +#include "base/string_split.h" #include "base/string_util.h" #include "chrome/browser/diagnostics/sqlite_diagnostics.h" #include "chrome/browser/history/history_types.h" @@ -134,8 +135,8 @@ std::string TopSitesDatabase::GetRedirects(const MostVisitedURL& url) { void TopSitesDatabase::SetRedirects(const std::string& redirects, MostVisitedURL* url) { std::vector redirects_vector; - SplitStringAlongWhitespace(redirects, &redirects_vector); - for (size_t i = 0; i < redirects_vector.size(); i++) + base::SplitStringAlongWhitespace(redirects, &redirects_vector); + for (size_t i = 0; i < redirects_vector.size(); ++i) url->redirects.push_back(GURL(redirects_vector[i])); } diff --git a/chrome/browser/host_content_settings_map.cc b/chrome/browser/host_content_settings_map.cc index a7dda7e..dc6517c 100644 --- a/chrome/browser/host_content_settings_map.cc +++ b/chrome/browser/host_content_settings_map.cc @@ -43,6 +43,11 @@ const char kDomainWildcard[] = "[*.]"; // The length of kDomainWildcard (without the trailing '\0') const size_t kDomainWildcardLength = arraysize(kDomainWildcard) - 1; +// Base pref path of the prefs that contain the managed default content +// settings values. +const std::string kManagedSettings = + "profile.managed_default_content_settings"; + // The preference keys where resource identifiers are stored for // ContentSettingsType values that support resource identifiers. const char* kResourceTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { @@ -66,6 +71,17 @@ const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { NULL, // Not used for Notifications }; +// The preferences used to manage ContentSettingsTypes. +const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = { + prefs::kManagedDefaultCookiesSetting, + prefs::kManagedDefaultImagesSetting, + prefs::kManagedDefaultJavaScriptSetting, + prefs::kManagedDefaultPluginsSetting, + prefs::kManagedDefaultPopupsSetting, + NULL, // Not used for Geolocation + NULL, // Not used for Notifications +}; + // The default setting for each content type. const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = { CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES @@ -100,6 +116,20 @@ static bool ShouldAllowAllContent(const GURL& url) { url.SchemeIs(chrome::kGearsScheme) || url.SchemeIs(chrome::kUserScriptScheme); } + +// Map ASK for the plugins content type to BLOCK if click-to-play is +// not enabled. +ContentSetting ClickToPlayFixup(ContentSettingsType content_type, + ContentSetting setting) { + if (setting == CONTENT_SETTING_ASK && + content_type == CONTENT_SETTINGS_TYPE_PLUGINS && + !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)) { + return CONTENT_SETTING_BLOCK; + } + return setting; +} + } // namespace @@ -215,6 +245,18 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile) pref_change_registrar_.Add(prefs::kContentSettingsPatterns, this); pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this); + // The following preferences are only used to indicate if a + // default-content-setting is managed and to hold the managed default-setting + // value. If the value for any of the following perferences is set then the + // corresponding default-content-setting is managed. These preferences exist + // in parallel to the preference default-content-settings. If a + // default-content-settings-type is managed any user defined excpetions + // (patterns) for this type are ignored. + pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); + pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, Source(profile_)); } @@ -229,6 +271,19 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false); prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0); + // Preferences for default content setting policies. A policy is not set of + // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. + prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting, + CONTENT_SETTING_DEFAULT); + prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting, + CONTENT_SETTING_DEFAULT); + // Obsolete prefs, for migration: prefs->RegisterIntegerPref(prefs::kCookieBehavior, net::StaticCookiePolicy::ALLOW_ALL_COOKIES); @@ -239,6 +294,8 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { ContentSetting HostContentSettingsMap::GetDefaultContentSetting( ContentSettingsType content_type) const { AutoLock auto_lock(lock_); + if (IsDefaultContentSettingManaged(content_type)) + return managed_default_content_settings_.settings[content_type]; return default_content_settings_.settings[content_type]; } @@ -249,8 +306,10 @@ ContentSetting HostContentSettingsMap::GetContentSetting( ContentSetting setting = GetNonDefaultContentSetting(url, content_type, resource_identifier); - if (setting == CONTENT_SETTING_DEFAULT) + if (setting == CONTENT_SETTING_DEFAULT || + IsDefaultContentSettingManaged(content_type)) { return GetDefaultContentSetting(content_type); + } return setting; } @@ -269,6 +328,12 @@ ContentSetting HostContentSettingsMap::GetNonDefaultContentSetting( DCHECK(!resource_identifier.empty()); } + // Host content settings are ignored if the default_content_setting is + // managed. + if (IsDefaultContentSettingManaged(content_type)) { + return GetDefaultContentSetting(content_type); + } + AutoLock auto_lock(lock_); const std::string host(net::GetHostOrSpecFromURL(url)); @@ -331,10 +396,19 @@ ContentSettings HostContentSettingsMap::GetContentSettings( // If we require a resource identifier, set the content settings to default, // otherwise make the defaults explicit. for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { - if (RequiresResourceIdentifier(ContentSettingsType(j))) + if (RequiresResourceIdentifier(ContentSettingsType(j))) { output.settings[j] = CONTENT_SETTING_DEFAULT; - else if (output.settings[j] == CONTENT_SETTING_DEFAULT) - output.settings[j] = default_content_settings_.settings[j]; + } else { + if (output.settings[j] == CONTENT_SETTING_DEFAULT) { + output.settings[j] = default_content_settings_.settings[j]; + } + // A managed default content setting has the highest priority and hence + // will overwrite any previously set value. + if (IsDefaultContentSettingManaged(ContentSettingsType(j))) { + output.settings[j] = + managed_default_content_settings_.settings[j]; + } + } } return output; } @@ -432,6 +506,10 @@ void HostContentSettingsMap::SetDefaultContentSetting( ContentSetting setting) { DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS || + setting != CONTENT_SETTING_ASK || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)); PrefService* prefs = profile_->GetPrefs(); // The default settings may not be directly modified for OTR sessions. @@ -474,6 +552,10 @@ void HostContentSettingsMap::SetContentSetting( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK_NE(RequiresResourceIdentifier(content_type), resource_identifier.empty()); + DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS || + setting != CONTENT_SETTING_ASK || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClickToPlay)); const Pattern pattern(original_pattern.CanonicalizePattern()); @@ -755,6 +837,26 @@ void HostContentSettingsMap::Observe(NotificationType type, AutoLock auto_lock(lock_); block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean( prefs::kBlockNonsandboxedPlugins); + } else if (prefs::kManagedDefaultCookiesSetting == *name) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES, + profile_->GetPrefs(), + &managed_default_content_settings_); + } else if (prefs::kManagedDefaultImagesSetting == *name) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES, + profile_->GetPrefs(), + &managed_default_content_settings_); + } else if (prefs::kManagedDefaultJavaScriptSetting == *name) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT, + profile_->GetPrefs(), + &managed_default_content_settings_); + } else if (prefs::kManagedDefaultPluginsSetting == *name) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS, + profile_->GetPrefs(), + &managed_default_content_settings_); + } else if (prefs::kManagedDefaultPopupsSetting == *name) { + UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS, + profile_->GetPrefs(), + &managed_default_content_settings_); } else { NOTREACHED() << "Unexpected preference observed"; return; @@ -796,6 +898,10 @@ void HostContentSettingsMap::GetSettingsFromDictionary( if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] == CONTENT_SETTING_ASK) settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK; + + settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] = + ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS, + settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]); } void HostContentSettingsMap::GetResourceSettingsFromDictionary( @@ -820,7 +926,8 @@ void HostContentSettingsMap::GetResourceSettingsFromDictionary( DCHECK(found); (*settings)[ContentSettingsTypeResourceIdentifierPair( ContentSettingsType(type), resource_identifier)] = - ContentSetting(setting); + ClickToPlayFixup(ContentSettingsType(type), + ContentSetting(setting)); } break; @@ -862,6 +969,47 @@ void HostContentSettingsMap::ReadDefaultSettings(bool overwrite) { &default_content_settings_); } ForceDefaultsToBeExplicit(); + + // Read managed default content settings. + ReadManagedDefaultSettings(prefs, &managed_default_content_settings_); +} + +void HostContentSettingsMap::ReadManagedDefaultSettings ( + const PrefService* prefs, ContentSettings* settings) { + for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { + if (kPrefToManageType[type] == NULL) { + // TODO(markusheintz): Handle Geolocation and notification separately. + continue; + } + UpdateManagedDefaultSetting(ContentSettingsType(type), prefs, settings); + } +} + +void HostContentSettingsMap::UpdateManagedDefaultSetting( + ContentSettingsType type, + const PrefService* prefs, + ContentSettings* settings) { + // If a pref to manage a default-content-setting was not set (NOTICE: + // "HasPrefPath" returns false if no value was set for a registered pref) then + // the default value of the preference is used. The default value of a + // preference to manage a default-content-settings is + // CONTENT_SETTING_DEFAULT. This indicates that no managed value is set. If a + // pref was set, than it MUST be managed. + DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) || + prefs->IsManagedPreference(kPrefToManageType[type])); + AutoLock auto_lock(lock_); + settings->settings[type] = IntToContentSetting( + prefs->GetInteger(kPrefToManageType[type])); +} + +bool HostContentSettingsMap::IsDefaultContentSettingManaged( + ContentSettingsType content_type) const { + // All managed_default_content_settings_ are always set explicitly or + // initialized to CONTENT_SETTINGS_DEFAULT. Hence each content settings type + // that is set to CONTENT_SETTINGS_DEFAULT is not managed since it was not set + // explicitly. + return managed_default_content_settings_.settings[content_type] != + CONTENT_SETTING_DEFAULT; } void HostContentSettingsMap::ReadExceptions(bool overwrite) { diff --git a/chrome/browser/host_content_settings_map.h b/chrome/browser/host_content_settings_map.h index 25edb99..449ece2 100644 --- a/chrome/browser/host_content_settings_map.h +++ b/chrome/browser/host_content_settings_map.h @@ -234,6 +234,9 @@ class HostContentSettingsMap // This should only be called on the UI thread. void ResetToDefaults(); + // Returns true if the default setting for the |content_type| is managed. + bool IsDefaultContentSettingManaged(ContentSettingsType content_type) const; + // NotificationObserver implementation. virtual void Observe(NotificationType type, const NotificationSource& source, @@ -269,6 +272,19 @@ class HostContentSettingsMap // true and the preference is missing, the local copy will be cleared as well. void ReadDefaultSettings(bool overwrite); + // Reads managed default content settings from the preference service |prefs|. + // |settings| is set to the respective content setting for managed settings, + // and to CONTENT_SETTING_DEFAULT for other settings. + void ReadManagedDefaultSettings(const PrefService* prefs, + ContentSettings* settings); + + // Updates the managed setting of the default-content-settings-type |type|. + // The updated setting is read from the preference service |prefs| and written + // to |settings|. + void UpdateManagedDefaultSetting(ContentSettingsType type, + const PrefService* prefs, + ContentSettings* settings); + // Reads the host exceptions from the prefereces service. If |overwrite| is // true and the preference is missing, the local copy will be cleared as well. void ReadExceptions(bool overwrite); @@ -300,6 +316,7 @@ class HostContentSettingsMap // Copies of the pref data, so that we can read it on the IO thread. ContentSettings default_content_settings_; + ContentSettings managed_default_content_settings_; HostContentSettings host_content_settings_; // Differences to the preference-stored host content settings for diff --git a/chrome/browser/host_content_settings_map_unittest.cc b/chrome/browser/host_content_settings_map_unittest.cc index b5c74a0..1312d43 100644 --- a/chrome/browser/host_content_settings_map_unittest.cc +++ b/chrome/browser/host_content_settings_map_unittest.cc @@ -4,6 +4,7 @@ #include "chrome/browser/host_content_settings_map.h" +#include "base/auto_reset.h" #include "base/command_line.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -13,6 +14,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/test/testing_pref_service.h" #include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" #include "net/base/static_cookie_policy.h" @@ -48,6 +50,7 @@ class StubSettingsObserver : public NotificationObserver { last_pattern = settings_details.ptr()->pattern(); last_update_all = settings_details.ptr()->update_all(); last_update_all_types = settings_details.ptr()->update_all_types(); + last_type = settings_details.ptr()->type(); // This checks that calling a Get function from an observer doesn't // deadlock. last_notifier->GetContentSettings(GURL("http://random-hostname.com/")); @@ -58,6 +61,7 @@ class StubSettingsObserver : public NotificationObserver { bool last_update_all; bool last_update_all_types; int counter; + ContentSettingsType last_type; private: NotificationRegistrar registrar_; @@ -90,11 +94,18 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) { EXPECT_EQ(CONTENT_SETTING_ALLOW, host_content_settings_map->GetContentSetting( GURL(chrome::kChromeUINewTabURL), CONTENT_SETTINGS_TYPE_IMAGES, "")); - host_content_settings_map->SetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ASK); - EXPECT_EQ(CONTENT_SETTING_ASK, - host_content_settings_map->GetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_PLUGINS)); + { + // Click-to-play needs to be enabled to set the content setting to ASK. + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableClickToPlay); + + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ASK); + EXPECT_EQ(CONTENT_SETTING_ASK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); + } host_content_settings_map->SetDefaultContentSetting( CONTENT_SETTINGS_TYPE_POPUPS, CONTENT_SETTING_ALLOW); EXPECT_EQ(CONTENT_SETTING_ALLOW, @@ -566,9 +577,9 @@ TEST_F(HostContentSettingsMapTest, OffTheRecord) { TEST_F(HostContentSettingsMapTest, MigrateObsoletePrefs) { // This feature is currently behind a flag. - CommandLine cl(*CommandLine::ForCurrentProcess()); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableResourceContentSettings); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableResourceContentSettings); TestingProfile profile; PrefService* prefs = profile.GetPrefs(); @@ -592,7 +603,6 @@ TEST_F(HostContentSettingsMapTest, MigrateObsoletePrefs) { EXPECT_EQ(CONTENT_SETTING_ALLOW, host_content_settings_map->GetContentSetting( host, CONTENT_SETTINGS_TYPE_POPUPS, "")); - *CommandLine::ForCurrentProcess() = cl; } // For a single Unicode encoded pattern, check if it gets converted to punycode @@ -624,9 +634,9 @@ TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeOnly) { // settings for the punycode, and that Unicode pattern gets deleted. TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeAndPunycode) { // This feature is currently behind a flag. - CommandLine cl(*CommandLine::ForCurrentProcess()); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableResourceContentSettings); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableResourceContentSettings); TestingProfile profile; @@ -648,8 +658,6 @@ TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeAndPunycode) { base::JSONWriter::Write(content_setting_prefs, false, &prefs_as_json); EXPECT_STREQ("{\"[*.]xn--ira-ppa.com\":{\"per_plugin\":{\"pluginy\":2}}}", prefs_as_json.c_str()); - - *CommandLine::ForCurrentProcess() = cl; } TEST_F(HostContentSettingsMapTest, NonDefaultSettings) { @@ -676,9 +684,9 @@ TEST_F(HostContentSettingsMapTest, NonDefaultSettings) { TEST_F(HostContentSettingsMapTest, ResourceIdentifier) { // This feature is currently behind a flag. - CommandLine cl(*CommandLine::ForCurrentProcess()); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableResourceContentSettings); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableResourceContentSettings); TestingProfile profile; HostContentSettingsMap* host_content_settings_map = @@ -700,14 +708,13 @@ TEST_F(HostContentSettingsMapTest, ResourceIdentifier) { EXPECT_EQ(CONTENT_SETTING_ALLOW, host_content_settings_map->GetContentSetting( host, CONTENT_SETTINGS_TYPE_PLUGINS, resource2)); - *CommandLine::ForCurrentProcess() = cl; } TEST_F(HostContentSettingsMapTest, ResourceIdentifierPrefs) { // This feature is currently behind a flag. - CommandLine cl(*CommandLine::ForCurrentProcess()); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableResourceContentSettings); + CommandLine* cmd = CommandLine::ForCurrentProcess(); + AutoReset auto_reset(cmd, *cmd); + cmd->AppendSwitch(switches::kEnableResourceContentSettings); TestingProfile profile; scoped_ptr value(base::JSONReader::Read( @@ -742,7 +749,239 @@ TEST_F(HostContentSettingsMapTest, ResourceIdentifierPrefs) { base::JSONWriter::Write(content_setting_prefs, false, &prefs_as_json); EXPECT_STREQ("{\"[*.]example.com\":{\"per_plugin\":{\"otherplugin\":2}}}", prefs_as_json.c_str()); - *CommandLine::ForCurrentProcess() = cl; +} + +// If a default-content-setting is managed, the managed value should be used +// instead of the default value. +TEST_F(HostContentSettingsMapTest, ManagedDefaultContentSetting) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT)); + + // Set managed-default-content-setting through the coresponding preferences. + prefs->SetManagedPref(prefs::kManagedDefaultJavaScriptSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT)); + + // Remove managed-default-content-settings-preferences. + prefs->RemoveManagedPref(prefs::kManagedDefaultJavaScriptSetting); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT)); + + // Set preference to manage the default-content-setting for Plugins. + prefs->SetManagedPref(prefs::kManagedDefaultPluginsSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); + + // Remove the preference to manage the default-content-setting for Plugins. + prefs->RemoveManagedPref(prefs::kManagedDefaultPluginsSetting); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); +} + +TEST_F(HostContentSettingsMapTest, + GetNonDefaultContentSettingsIfTypeManaged) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // Set pattern for JavaScript setting. + HostContentSettingsMap::Pattern pattern("[*.]example.com"); + host_content_settings_map->SetContentSetting(pattern, + CONTENT_SETTINGS_TYPE_JAVASCRIPT, "", CONTENT_SETTING_BLOCK); + + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT)); + + GURL host("http://example.com/"); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + host, CONTENT_SETTINGS_TYPE_JAVASCRIPT, "")); + + // Set managed-default-content-setting for content-settings-type JavaScript. + prefs->SetManagedPref(prefs::kManagedDefaultJavaScriptSetting, + Value::CreateIntegerValue(CONTENT_SETTING_ALLOW)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + host, CONTENT_SETTINGS_TYPE_JAVASCRIPT, "")); +} + +// Managed default content setting should have higher priority +// than user defined patterns. +TEST_F(HostContentSettingsMapTest, + ManagedDefaultContentSettingIgnoreUserPattern) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // Block all JavaScript. + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK); + + // Set an exception to allow "[*.]example.com" + HostContentSettingsMap::Pattern pattern("[*.]example.com"); + host_content_settings_map->SetContentSetting(pattern, + CONTENT_SETTINGS_TYPE_JAVASCRIPT, "", CONTENT_SETTING_ALLOW); + + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_JAVASCRIPT)); + GURL host("http://example.com/"); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + host, CONTENT_SETTINGS_TYPE_JAVASCRIPT, "")); + + // Set managed-default-content-settings-preferences. + prefs->SetManagedPref(prefs::kManagedDefaultJavaScriptSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + host, CONTENT_SETTINGS_TYPE_JAVASCRIPT, "")); + + // Remove managed-default-content-settings-preferences. + prefs->RemoveManagedPref(prefs::kManagedDefaultJavaScriptSetting); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + host, CONTENT_SETTINGS_TYPE_JAVASCRIPT, "")); +} + +// If a default-content-setting is set to managed setting, the user defined +// setting should be preserved. +TEST_F(HostContentSettingsMapTest, OverwrittenDefaultContentSetting) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // Set user defined default-content-setting for Cookies. + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES)); + + // Set preference to manage the default-content-setting for Cookies. + prefs->SetManagedPref(prefs::kManagedDefaultCookiesSetting, + Value::CreateIntegerValue(CONTENT_SETTING_ALLOW)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES)); + + // Remove the preference to manage the default-content-setting for Cookies. + prefs->RemoveManagedPref(prefs::kManagedDefaultCookiesSetting); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES)); + } + +// When a default-content-setting is set to a managed setting a +// CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen +// if the managed setting is removed. +TEST_F(HostContentSettingsMapTest, ObserveManagedSettingsChange) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + StubSettingsObserver observer; + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // TODO(markusheintz): I think it would be better to send notifications only + // for a specific content-settings-type. + + // Set the managed default-content-setting. + prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting, + Value::CreateIntegerValue(CONTENT_SETTING_BLOCK)); + EXPECT_EQ(host_content_settings_map, observer.last_notifier); + EXPECT_EQ(HostContentSettingsMap::Pattern(), observer.last_pattern); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(1, observer.counter); + + // Remove the managed default-content-setting. + prefs->RemoveManagedPref(prefs::kManagedDefaultImagesSetting); + EXPECT_EQ(host_content_settings_map, observer.last_notifier); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_EQ(HostContentSettingsMap::Pattern(), observer.last_pattern); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(2, observer.counter); +} + +// When a default-content-setting is set to a managed setting a +// CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen +// if the managed setting is removed. In this test-case the actual managed +// setting is the same. Just the managed status of the default-content-setting +// changes. +TEST_F(HostContentSettingsMapTest, ObserveManagedSettingsNoChange) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + StubSettingsObserver observer; + TestingPrefService* prefs = profile.GetTestingPrefService(); + + // TODO(markusheintz): I think it would be better to send notifications only + // for a specific content-settings-type. + + // Set the managed default-content-setting. In this case the actual setting + // does not change. + prefs->SetManagedPref(prefs::kManagedDefaultImagesSetting, + Value::CreateIntegerValue(CONTENT_SETTING_ALLOW)); + EXPECT_EQ(host_content_settings_map, observer.last_notifier); + EXPECT_EQ(HostContentSettingsMap::Pattern(), observer.last_pattern); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(1, observer.counter); + + // Remove the managed default-content-setting. + prefs->RemoveManagedPref(prefs::kManagedDefaultImagesSetting); + EXPECT_EQ(host_content_settings_map, observer.last_notifier); + EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type); + EXPECT_EQ(HostContentSettingsMap::Pattern(), observer.last_pattern); + EXPECT_TRUE(observer.last_update_all); + EXPECT_TRUE(observer.last_update_all_types); + EXPECT_EQ(2, observer.counter); +} + +// If a setting for a default-content-setting-type is set while the type is +// managed, then the new setting should be preserved and used after the +// default-content-setting-type is not managed anymore. +TEST_F(HostContentSettingsMapTest, SettingDefaultContentSettingsWhenManaged) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + TestingPrefService* prefs = profile.GetTestingPrefService(); + + prefs->SetManagedPref(prefs::kManagedDefaultPluginsSetting, + Value::CreateIntegerValue(CONTENT_SETTING_ALLOW)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); + + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); + + prefs->RemoveManagedPref(prefs::kManagedDefaultPluginsSetting); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_PLUGINS)); } } // namespace diff --git a/chrome/browser/host_zoom_map.h b/chrome/browser/host_zoom_map.h index 10f512e..6030f4c 100644 --- a/chrome/browser/host_zoom_map.h +++ b/chrome/browser/host_zoom_map.h @@ -16,6 +16,7 @@ #include "base/basictypes.h" #include "base/lock.h" #include "base/ref_counted.h" +#include "chrome/browser/browser_thread.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" @@ -24,8 +25,12 @@ class GURL; class PrefService; class Profile; -class HostZoomMap : public NotificationObserver, - public base::RefCountedThreadSafe { +// HostZoomMap needs to be deleted on the UI thread because it listens +// to notifications on there (and holds a NotificationRegistrar). +class HostZoomMap : + public NotificationObserver, + public base::RefCountedThreadSafe { public: explicit HostZoomMap(Profile* profile); @@ -74,7 +79,8 @@ class HostZoomMap : public NotificationObserver, const NotificationDetails& details); private: - friend class base::RefCountedThreadSafe; + friend struct BrowserThread::DeleteOnThread; + friend class DeleteTask; typedef std::map HostZoomLevels; diff --git a/chrome/browser/idbbindingutilities_browsertest.cc b/chrome/browser/idbbindingutilities_browsertest.cc index 40a2c09..6297d96 100644 --- a/chrome/browser/idbbindingutilities_browsertest.cc +++ b/chrome/browser/idbbindingutilities_browsertest.cc @@ -4,8 +4,8 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/browser.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/utility_process_host.h" #include "chrome/common/indexed_db_key.h" #include "chrome/common/serialized_script_value.h" @@ -13,9 +13,9 @@ #include "chrome/test/ui_test_utils.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h" #include "webkit/glue/idb_bindings.h" #include "webkit/glue/web_io_operators.h" -#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h" using WebKit::WebSerializedScriptValue; diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc index 32f48d3..a9deb82 100644 --- a/chrome/browser/importer/importer.cc +++ b/chrome/browser/importer/importer.cc @@ -9,7 +9,6 @@ #include "base/values.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_navigator.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/browsing_instance.h" @@ -19,6 +18,7 @@ #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/notification_service.h" #include "gfx/codec/png_codec.h" diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc index 365c91c..df541e8 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc @@ -20,6 +20,9 @@ BrowserWebKitClientImpl::BrowserWebKitClientImpl() { file_utilities_.set_sandbox_enabled(false); } +BrowserWebKitClientImpl::~BrowserWebKitClientImpl() { +} + WebKit::WebClipboard* BrowserWebKitClientImpl::clipboard() { NOTREACHED(); return NULL; @@ -144,15 +147,19 @@ int BrowserWebKitClientImpl::databaseDeleteFile( return file_util::Delete(path, false) ? 0 : 1; } +void BrowserWebKitClientImpl::idbShutdown() { + if (indexed_db_key_utility_client_.get()) + indexed_db_key_utility_client_->EndUtilityProcess(); +} + void BrowserWebKitClientImpl::createIDBKeysFromSerializedValuesAndKeyPath( const WebKit::WebVector& values, const WebKit::WebString& keyPath, WebKit::WebVector& keys) { - // TODO(bulach): we need to figure out a way to keep the utility process - // running for longer, and shut it down when no longer used. - scoped_refptr indexed_db_key_utility_client( - new IndexedDBKeyUtilityClient()); - indexed_db_key_utility_client->StartUtilityProcess(); + if (!indexed_db_key_utility_client_.get()) { + indexed_db_key_utility_client_ = new IndexedDBKeyUtilityClient(); + indexed_db_key_utility_client_->StartUtilityProcess(); + } std::vector std_values; size_t size = values.size(); @@ -161,10 +168,8 @@ void BrowserWebKitClientImpl::createIDBKeysFromSerializedValuesAndKeyPath( std_values.push_back(SerializedScriptValue(values[i])); std::vector std_keys; - indexed_db_key_utility_client->CreateIDBKeysFromSerializedValuesAndKeyPath( + indexed_db_key_utility_client_->CreateIDBKeysFromSerializedValuesAndKeyPath( std_values, keyPath, &std_keys); - indexed_db_key_utility_client->EndUtilityProcess(); - keys = std_keys; } diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h index dd291c8..bc0dd5d 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h @@ -6,12 +6,16 @@ #define CHROME_BROWSER_IN_PROCESS_WEBKIT_BROWSER_WEBKITCLIENT_IMPL_H_ #pragma once +#include "base/ref_counted.h" #include "webkit/glue/webfileutilities_impl.h" #include "webkit/glue/webkitclient_impl.h" +class IndexedDBKeyUtilityClient; + class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { public: BrowserWebKitClientImpl(); + virtual ~BrowserWebKitClientImpl(); // WebKitClient methods: virtual WebKit::WebClipboard* clipboard(); @@ -45,6 +49,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository(); virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name, bool sync_dir); + virtual void idbShutdown(); virtual void createIDBKeysFromSerializedValuesAndKeyPath( const WebKit::WebVector& values, const WebKit::WebString& keyPath, @@ -52,6 +57,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { private: webkit_glue::WebFileUtilitiesImpl file_utilities_; + scoped_refptr indexed_db_key_utility_client_; }; #endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_BROWSER_WEBKITCLIENT_IMPL_H_ diff --git a/chrome/browser/in_process_webkit/dom_storage_context.cc b/chrome/browser/in_process_webkit/dom_storage_context.cc index 88f617d..28f1d84 100644 --- a/chrome/browser/in_process_webkit/dom_storage_context.cc +++ b/chrome/browser/in_process_webkit/dom_storage_context.cc @@ -18,6 +18,8 @@ #include "third_party/WebKit/WebKit/chromium/public/WebString.h" #include "webkit/glue/webkit_glue.h" +using WebKit::WebSecurityOrigin; + const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] = FILE_PATH_LITERAL("Local Storage"); @@ -169,8 +171,8 @@ void DOMStorageContext::DeleteDataModifiedSince( file_util::FileEnumerator::FILES); for (FilePath path = file_enumerator.Next(); !path.value().empty(); path = file_enumerator.Next()) { - WebKit::WebSecurityOrigin web_security_origin = - WebKit::WebSecurityOrigin::createFromDatabaseIdentifier( + WebSecurityOrigin web_security_origin = + WebSecurityOrigin::createFromDatabaseIdentifier( webkit_glue::FilePathToWebString(path.BaseName())); if (EqualsASCII(web_security_origin.protocol(), url_scheme_to_be_skipped)) continue; @@ -270,12 +272,13 @@ void DOMStorageContext::ClearLocalState(const FilePath& profile_path, for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); file_path = file_enumerator.Next()) { if (file_path.Extension() == kLocalStorageExtension) { - WebKit::WebSecurityOrigin web_security_origin = - WebKit::WebSecurityOrigin::createFromDatabaseIdentifier( + WebSecurityOrigin web_security_origin = + WebSecurityOrigin::createFromDatabaseIdentifier( webkit_glue::FilePathToWebString(file_path.BaseName())); if (!EqualsASCII(web_security_origin.protocol(), - url_scheme_to_be_skipped)) + url_scheme_to_be_skipped)) { file_util::Delete(file_path, false); + } } } } diff --git a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc index 9804be7..0292641 100644 --- a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc +++ b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc @@ -6,8 +6,8 @@ #include "base/file_path.h" #include "base/ref_counted.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc index 6667d50..920da34 100644 --- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc +++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc @@ -1,6 +1,6 @@ -// 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) 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/in_process_webkit/indexed_db_key_utility_client.h" diff --git a/chrome/browser/instant/instant_browsertest.cc b/chrome/browser/instant/instant_browsertest.cc index ec4fc69..449cf4e 100644 --- a/chrome/browser/instant/instant_browsertest.cc +++ b/chrome/browser/instant/instant_browsertest.cc @@ -6,7 +6,6 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" @@ -17,6 +16,7 @@ #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" @@ -185,7 +185,8 @@ IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_OnChangeEvent) { } #if defined(OS_WIN) -#define MAYBE_OnSubmitEvent OnSubmitEvent +// Disabled, http://crbug.com/62940. +#define MAYBE_OnSubmitEvent DISABLED_OnSubmitEvent #else #define MAYBE_OnSubmitEvent DISABLED_OnSubmitEvent #endif diff --git a/chrome/browser/instant/instant_confirm_dialog.cc b/chrome/browser/instant/instant_confirm_dialog.cc index 5c6c535..e59a30b 100644 --- a/chrome/browser/instant/instant_confirm_dialog.cc +++ b/chrome/browser/instant/instant_confirm_dialog.cc @@ -4,6 +4,8 @@ #include "chrome/browser/instant/instant_confirm_dialog.h" +#include "chrome/browser/instant/instant_controller.h" +#include "chrome/browser/instant/promo_counter.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/common/pref_names.h" @@ -19,8 +21,12 @@ void ShowInstantConfirmDialogIfNecessary(gfx::NativeWindow parent, if (!prefs) return; + PromoCounter* promo_counter = profile->GetInstantPromoCounter(); + if (promo_counter) + promo_counter->Hide(); + if (prefs->GetBoolean(prefs::kInstantConfirmDialogShown)) { - prefs->SetBoolean(prefs::kInstantEnabled, true); + InstantController::Enable(profile); return; } diff --git a/chrome/browser/instant/instant_confirm_dialog.h b/chrome/browser/instant/instant_confirm_dialog.h index 434d65a..bdd5554 100644 --- a/chrome/browser/instant/instant_confirm_dialog.h +++ b/chrome/browser/instant/instant_confirm_dialog.h @@ -22,9 +22,8 @@ void ShowInstantConfirmDialogIfNecessary(gfx::NativeWindow parent, Profile* profile); // Shows the platform specific dialog to confirm if the user really wants to -// enable instant. If the user accepts the dialog implementations must set -// both |prefs::kInstantEnabled| and |prefs::kInstantConfirmDialogShown| to -// true. +// enable instant. If the user accepts the dialog invoke +// InstantController::Enable. void ShowInstantConfirmDialog(gfx::NativeWindow parent, Profile* profile); diff --git a/chrome/browser/instant/instant_controller.cc b/chrome/browser/instant/instant_controller.cc index ab6617a..54c12dd 100644 --- a/chrome/browser/instant/instant_controller.cc +++ b/chrome/browser/instant/instant_controller.cc @@ -5,10 +5,13 @@ #include "chrome/browser/instant/instant_controller.h" #include "base/command_line.h" +#include "base/metrics/histogram.h" +#include "base/rand_util.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/instant/instant_delegate.h" #include "chrome/browser/instant/instant_loader.h" #include "chrome/browser/instant/instant_loader_manager.h" +#include "chrome/browser/instant/promo_counter.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" @@ -24,10 +27,61 @@ // Number of ms to delay between loading urls. static const int kUpdateDelayMS = 200; +static InstantController::Type GetType(Profile* profile) { + return InstantController::IsEnabled(profile, + InstantController::PREDICTIVE_TYPE) ? + InstantController::PREDICTIVE_TYPE : InstantController::VERBATIM_TYPE; +} + +InstantController::InstantController(Profile* profile, + InstantDelegate* delegate) + : delegate_(delegate), + tab_contents_(NULL), + is_active_(false), + commit_on_mouse_up_(false), + last_transition_type_(PageTransition::LINK), + type_(GetType(profile)) { + PrefService* service = profile->GetPrefs(); + if (service) { + // kInstantWasEnabledOnce was added after instant, set it now to make sure + // it is correctly set. + service->SetBoolean(prefs::kInstantEnabledOnce, true); + } +} + +InstantController::~InstantController() { +} + // static void InstantController::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kInstantConfirmDialogShown, false); prefs->RegisterBooleanPref(prefs::kInstantEnabled, false); + prefs->RegisterBooleanPref(prefs::kInstantEnabledOnce, false); + prefs->RegisterInt64Pref(prefs::kInstantEnabledTime, false); + prefs->RegisterIntegerPref(prefs::kInstantType, 0); + PromoCounter::RegisterUserPrefs(prefs, prefs::kInstantPromo); +} + +// static +void InstantController::RecordMetrics(Profile* profile) { + if (!IsEnabled(profile)) + return; + + PrefService* service = profile->GetPrefs(); + if (service) { + int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime); + if (!enable_time) { + service->SetInt64(prefs::kInstantEnabledTime, + base::Time::Now().ToInternalValue()); + } else { + base::TimeDelta delta = + base::Time::Now() - base::Time::FromInternalValue(enable_time); + std::string name = IsEnabled(profile, PREDICTIVE_TYPE) ? + "Instant.EnabledTime.Predictive" : "Instant.EnabledTime.Verbatim"; + // Histogram from 1 hour to 30 days. + UMA_HISTOGRAM_CUSTOM_COUNTS(name, delta.InHours(), 1, 30 * 24, 50); + } + } } // static @@ -38,34 +92,70 @@ bool InstantController::IsEnabled(Profile* profile) { // static bool InstantController::IsEnabled(Profile* profile, Type type) { + // CommandLine takes precedence. CommandLine* cl = CommandLine::ForCurrentProcess(); - if (type == PREDICTIVE_TYPE) { - return (cl->HasSwitch(switches::kEnablePredictiveInstant) || - (profile->GetPrefs() && - profile->GetPrefs()->GetBoolean(prefs::kInstantEnabled))); + if (type == PREDICTIVE_TYPE && + cl->HasSwitch(switches::kEnablePredictiveInstant)) { + return true; + } + if (type == VERBATIM_TYPE && + cl->HasSwitch(switches::kEnableVerbatimInstant)) { + return true; } - return cl->HasSwitch(switches::kEnableVerbatimInstant); -} -static InstantController::Type GetType(Profile* profile) { - return InstantController::IsEnabled(profile, - InstantController::PREDICTIVE_TYPE) ? - InstantController::PREDICTIVE_TYPE : InstantController::VERBATIM_TYPE; + // Then prefs. + PrefService* prefs = profile->GetPrefs(); + if (!prefs->GetBoolean(prefs::kInstantEnabled)) + return false; + + Type pref_type = prefs->GetInteger(prefs::kInstantType) == + static_cast(PREDICTIVE_TYPE) ? PREDICTIVE_TYPE : VERBATIM_TYPE; + return pref_type == type; } -InstantController::InstantController(Profile* profile, - InstantDelegate* delegate) - : delegate_(delegate), - tab_contents_(NULL), - is_active_(false), - commit_on_mouse_up_(false), - last_transition_type_(PageTransition::LINK), - type_(GetType(profile)) { +// static +void InstantController::Enable(Profile* profile) { + PromoCounter* promo_counter = profile->GetInstantPromoCounter(); + if (promo_counter) + promo_counter->Hide(); + + PrefService* service = profile->GetPrefs(); + if (!service) + return; + + service->SetBoolean(prefs::kInstantEnabled, true); + service->SetBoolean(prefs::kInstantConfirmDialogShown, true); + service->SetInt64(prefs::kInstantEnabledTime, + base::Time::Now().ToInternalValue()); + service->SetBoolean(prefs::kInstantEnabledOnce, true); + // Randomly pick a type. We're doing this to get feedback as to which variant + // folks prefer. + service->SetInteger(prefs::kInstantType, + base::RandInt(static_cast(PREDICTIVE_TYPE), + static_cast(LAST_TYPE))); } -InstantController::~InstantController() { +// static +void InstantController::Disable(Profile* profile) { + PrefService* service = profile->GetPrefs(); + if (!service) + return; + + service->SetBoolean(prefs::kInstantEnabled, false); + + int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime); + if (!enable_time) + return; + + base::TimeDelta delta = + base::Time::Now() - base::Time::FromInternalValue(enable_time); + std::string name = IsEnabled(profile, PREDICTIVE_TYPE) ? + "Instant.TimeToDisable.Predictive" : "Instant.TimeToDisable.Verbatim"; + // histogram from 1 minute to 10 days. + UMA_HISTOGRAM_CUSTOM_COUNTS(name, delta.InMinutes(), 1, 60 * 24 * 10, 50); } + void InstantController::Update(TabContents* tab_contents, const AutocompleteMatch& match, const string16& user_text, @@ -82,7 +172,7 @@ void InstantController::Update(TabContents* tab_contents, if (loader_manager_.get() && loader_manager_->active_loader()->url() == url) return; - if (url.is_empty() || !url.is_valid() || !ShouldShowPreviewFor(url)) { + if (url.is_empty() || !url.is_valid() || !ShouldShowPreviewFor(match)) { DestroyPreviewContents(); return; } @@ -93,6 +183,9 @@ void InstantController::Update(TabContents* tab_contents, if (!loader_manager_.get()) loader_manager_.reset(new InstantLoaderManager(this)); + if (!is_active_) + delegate_->PrepareForInstant(); + if (ShouldUpdateNow(template_url_id, match.destination_url)) { UpdateLoader(template_url, match.destination_url, match.transition, user_text, suggested_text); @@ -159,8 +252,10 @@ void InstantController::OnAutocompleteLostFocus( RenderWidgetHostView* rwhv = GetPreviewContents()->GetRenderWidgetHostView(); - if (!view_gaining_focus || !rwhv) - return DestroyPreviewContents(); + if (!view_gaining_focus || !rwhv) { + DestroyPreviewContents(); + return; + } gfx::NativeView tab_view = GetPreviewContents()->GetNativeView(); // Focus is going to the renderer. @@ -169,17 +264,20 @@ void InstantController::OnAutocompleteLostFocus( if (!IsMouseDownFromActivate()) { // If the mouse is not down, focus is not going to the renderer. Someone // else moved focus and we shouldn't commit. - return DestroyPreviewContents(); + DestroyPreviewContents(); + return; } if (IsShowingInstant()) { // We're showing instant results. As instant results may shift when // committing we commit on the mouse up. This way a slow click still // works fine. - return SetCommitOnMouseUp(); + SetCommitOnMouseUp(); + return; } - return CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); + CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); + return; } // Walk up the view hierarchy. If the view gaining focus is a subview of the @@ -193,10 +291,12 @@ void InstantController::OnAutocompleteLostFocus( platform_util::GetParent(view_gaining_focus_ancestor); } - if (view_gaining_focus_ancestor) - return CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); + if (view_gaining_focus_ancestor) { + CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); + return; + } - return DestroyPreviewContents(); + DestroyPreviewContents(); } TabContents* InstantController::ReleasePreviewContents(InstantCommitType type) { @@ -366,8 +466,15 @@ void InstantController::UpdateLoader(const TemplateURL* template_url, delegate_->ShowInstant(new_loader->preview_contents()); } -bool InstantController::ShouldShowPreviewFor(const GURL& url) { - return !url.SchemeIs(chrome::kJavaScriptScheme); +bool InstantController::ShouldShowPreviewFor(const AutocompleteMatch& match) { + if (match.destination_url.SchemeIs(chrome::kJavaScriptScheme)) + return false; + + // Extension keywords don't have a real destionation URL. + if (match.template_url && match.template_url->IsExtensionKeyword()) + return false; + + return true; } void InstantController::BlacklistFromInstant(TemplateURLID id) { diff --git a/chrome/browser/instant/instant_controller.h b/chrome/browser/instant/instant_controller.h index 009340b..1d989cb 100644 --- a/chrome/browser/instant/instant_controller.h +++ b/chrome/browser/instant/instant_controller.h @@ -40,12 +40,16 @@ class InstantController : public InstantLoaderDelegate { public: // Variations of instant support. enum Type { + // NOTE: these values are persisted to prefs. Don't change them! + // Search results are shown for the best guess of what we think the user was // planning on typing. - PREDICTIVE_TYPE, + PREDICTIVE_TYPE = 0, // Search results are shown for exactly what was typed. VERBATIM_TYPE, + + LAST_TYPE = VERBATIM_TYPE, }; InstantController(Profile* profile, InstantDelegate* delegate); @@ -54,12 +58,21 @@ class InstantController : public InstantLoaderDelegate { // Registers instant related preferences. static void RegisterUserPrefs(PrefService* prefs); + // Records instant metrics. + static void RecordMetrics(Profile* profile); + // Returns true if either type of instant is enabled. static bool IsEnabled(Profile* profile); // Returns true if the specified type of instant is enabled. static bool IsEnabled(Profile* profile, Type type); + // Enables instant. + static void Enable(Profile* profile); + + // Disables instant. + static void Disable(Profile* profile); + // Invoked as the user types in the omnibox with the url to navigate to. If // the url is empty and there is a preview TabContents it is destroyed. If url // is non-empty and the preview TabContents has not been created it is @@ -160,8 +173,8 @@ class InstantController : public InstantLoaderDelegate { const string16& user_text, string16* suggested_text); - // Returns true if we should show preview for |url|. - bool ShouldShowPreviewFor(const GURL& url); + // Returns true if we should show preview for |match|. + bool ShouldShowPreviewFor(const AutocompleteMatch& match); // Marks the specified search engine id as not supporting instant. void BlacklistFromInstant(TemplateURLID id); diff --git a/chrome/browser/instant/instant_delegate.h b/chrome/browser/instant/instant_delegate.h index a5c9223..90f58a2 100644 --- a/chrome/browser/instant/instant_delegate.h +++ b/chrome/browser/instant/instant_delegate.h @@ -18,6 +18,11 @@ class Rect; // InstantController for details. class InstantDelegate { public: + // Invoked when instant starts loading, but before the preview tab contents is + // ready to be shown. This may be used to animate between the states. + // This is followed by ShowInstant and/or HideInstant. + virtual void PrepareForInstant() = 0; + // Invoked when the instant TabContents should be shown. virtual void ShowInstant(TabContents* preview_contents) = 0; diff --git a/chrome/browser/instant/instant_loader.cc b/chrome/browser/instant/instant_loader.cc index 7147b7c..a74f26f 100644 --- a/chrome/browser/instant/instant_loader.cc +++ b/chrome/browser/instant/instant_loader.cc @@ -30,6 +30,7 @@ #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/page_transition_types.h" #include "chrome/common/render_messages.h" #include "chrome/common/renderer_preferences.h" @@ -236,9 +237,6 @@ class InstantLoader::TabContentsDelegateImpl : public TabContentsDelegate { virtual bool IsApplication() const { return false; } virtual void ConvertContentsToApplication(TabContents* source) {} virtual bool CanReloadContents(TabContents* source) const { return true; } - virtual gfx::Rect GetRootWindowResizerRect() const { - return gfx::Rect(); - } virtual void ShowHtmlDialog(HtmlDialogUIDelegate* delegate, gfx::NativeWindow parent_window) {} virtual void BeforeUnloadFired(TabContents* tab, @@ -251,11 +249,6 @@ class InstantLoader::TabContentsDelegateImpl : public TabContentsDelegate { virtual void SetFocusToLocationBar(bool select_all) {} virtual bool ShouldFocusPageAfterCrash() { return false; } virtual void RenderWidgetShowing() {} - virtual ExtensionFunctionDispatcher* CreateExtensionFunctionDispatcher( - RenderViewHost* render_view_host, - const std::string& extension_id) { - return NULL; - } virtual bool TakeFocus(bool reverse) { return false; } virtual void LostCapture() { CommitFromMouseReleaseIfNecessary(); @@ -390,6 +383,8 @@ InstantLoader::InstantLoader(InstantLoaderDelegate* delegate, TemplateURLID id) } InstantLoader::~InstantLoader() { + registrar_.RemoveAll(); + // Delete the TabContents before the delegate as the TabContents holds a // reference to the delegate. preview_contents_.reset(NULL); @@ -429,6 +424,20 @@ void InstantLoader::Update(TabContents* tab_contents, tab_contents->view()->GetContainerBounds(&tab_bounds); preview_contents_->view()->SizeContents(tab_bounds.size()); +#if defined(OS_MACOSX) + // If |preview_contents_| does not currently have a RWHV, we will call + // SetTakesFocusOnlyOnMouseDown() as a result of the + // RENDER_VIEW_HOST_CHANGED notification. + if (preview_contents_->GetRenderWidgetHostView()) { + preview_contents_->GetRenderWidgetHostView()-> + SetTakesFocusOnlyOnMouseDown(true); + } + registrar_.Add( + this, + NotificationType::RENDER_VIEW_HOST_CHANGED, + Source(&preview_contents_->controller())); +#endif + preview_contents_->ShowContents(); created_preview_contents = true; } else { @@ -537,6 +546,10 @@ TabContents* InstantLoader::ReleasePreviewContents(InstantCommitType type) { #if defined(OS_MACOSX) preview_contents_->GetRenderWidgetHostView()-> SetTakesFocusOnlyOnMouseDown(false); + registrar_.Remove( + this, + NotificationType::RENDER_VIEW_HOST_CHANGED, + Source(&preview_contents_->controller())); #endif } preview_contents_->set_delegate(NULL); @@ -604,16 +617,26 @@ void InstantLoader::PreviewPainted() { void InstantLoader::ShowPreview() { if (!ready_) { ready_ = true; -#if defined(OS_MACOSX) - if (preview_contents_->GetRenderWidgetHostView()) { - preview_contents_->GetRenderWidgetHostView()-> - SetTakesFocusOnlyOnMouseDown(true); - } -#endif delegate_->ShowInstantLoader(this); } } +void InstantLoader::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { +#if defined(OS_MACOSX) + if (type.value == NotificationType::RENDER_VIEW_HOST_CHANGED) { + if (preview_contents_->GetRenderWidgetHostView()) { + preview_contents_->GetRenderWidgetHostView()-> + SetTakesFocusOnlyOnMouseDown(true); + } + return; + } +#endif + + NOTREACHED() << "Got a notification we didn't register for."; +} + void InstantLoader::PageFinishedLoading() { frame_load_observer_.reset(); // Wait for the user input before showing, this way the page should be up to diff --git a/chrome/browser/instant/instant_loader.h b/chrome/browser/instant/instant_loader.h index 3802bf8..b2dfb66 100644 --- a/chrome/browser/instant/instant_loader.h +++ b/chrome/browser/instant/instant_loader.h @@ -12,6 +12,8 @@ #include "base/timer.h" #include "chrome/browser/instant/instant_commit_type.h" #include "chrome/browser/search_engines/template_url_id.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" #include "chrome/common/page_transition_types.h" #include "gfx/rect.h" #include "googleurl/src/gurl.h" @@ -31,10 +33,10 @@ class TemplateURL; // // If the TemplateURLID supplied to the constructor is zero, then the url is // loaded as is. -class InstantLoader { +class InstantLoader : public NotificationObserver { public: InstantLoader(InstantLoaderDelegate* delegate, TemplateURLID id); - ~InstantLoader(); + virtual ~InstantLoader(); // Invoked to load a URL. |tab_contents| is the TabContents the preview is // going to be shown on top of and potentially replace. @@ -67,6 +69,10 @@ class InstantLoader { // intended to be invoked from InstantLoaderDoesntSupportInstant. void ClearTemplateURLID(); + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + // The preview TabContents; may be null. TabContents* preview_contents() const { return preview_contents_.get(); } @@ -164,6 +170,9 @@ class InstantLoader { // Timer used to update the bounds of the omnibox. base::OneShotTimer update_bounds_timer_; + // Used to get notifications about renderers coming and going. + NotificationRegistrar registrar_; + DISALLOW_COPY_AND_ASSIGN(InstantLoader); }; diff --git a/chrome/browser/instant/instant_opt_in.cc b/chrome/browser/instant/instant_opt_in.cc deleted file mode 100644 index 02db5c5..0000000 --- a/chrome/browser/instant/instant_opt_in.cc +++ /dev/null @@ -1,33 +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/instant/instant_opt_in.h" - -#include "base/command_line.h" -#include "chrome/browser/instant/instant_confirm_dialog.h" -#include "chrome/browser/profile.h" -#include "chrome/common/chrome_switches.h" - -namespace browser { - -static bool dialog_shown = false; - -bool ShouldShowInstantOptIn(Profile* profile) { - if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowInstantOptIn)) - return false; - - // TODO(sky): implement me. - return !dialog_shown; -} - -void UserPickedInstantOptIn(gfx::NativeWindow parent, - Profile* profile, - bool opt_in) { - // TODO: set pref so don't show opt-in again. - dialog_shown = true; - if (opt_in) - browser::ShowInstantConfirmDialogIfNecessary(parent, profile); -} - -} // namespace browser diff --git a/chrome/browser/instant/instant_opt_in.h b/chrome/browser/instant/instant_opt_in.h deleted file mode 100644 index 55c62fb..0000000 --- a/chrome/browser/instant/instant_opt_in.h +++ /dev/null @@ -1,25 +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_INSTANT_INSTANT_OPT_IN_H_ -#define CHROME_BROWSER_INSTANT_INSTANT_OPT_IN_H_ -#pragma once - -#include "gfx/native_widget_types.h" - -class Profile; - -namespace browser { - -// Returns true if the opt-in should be shown. -bool ShouldShowInstantOptIn(Profile* profile); - -// Invoked if the user clicks on the opt-in promo. -void UserPickedInstantOptIn(gfx::NativeWindow parent, - Profile* profile, - bool opt_in); - -} // namespace browser - -#endif // CHROME_BROWSER_INSTANT_INSTANT_OPT_IN_H_ diff --git a/chrome/browser/instant/promo_counter.cc b/chrome/browser/instant/promo_counter.cc new file mode 100644 index 0000000..34c9b2f --- /dev/null +++ b/chrome/browser/instant/promo_counter.cc @@ -0,0 +1,115 @@ +// 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/instant/promo_counter.h" + +#include "base/metrics/histogram.h" +#include "base/values.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profile.h" + +// Pref keys. These are relative to pref_key_. +static const char* kShowKey = ".show"; +static const char* kNumSessionsKey = ".num_sessions"; +static const char* kInitialTimeKey = ".initial_time"; + +// Values used for histograms. These are relative to histogram_key_. +static const char* kHistogramHide = ".hide"; +static const char* kHistogramMaxSessions = ".max_sessions"; +static const char* kHistogramMaxTime = ".max_time"; + +PromoCounter::PromoCounter(Profile* profile, + const std::string& pref_key, + const std::string& histogram_key, + int max_sessions, + int max_days) + : profile_(profile), + pref_key_(pref_key), + histogram_key_(histogram_key), + max_sessions_(max_sessions), + max_days_(max_days), + did_init_(false), + show_(false) { +} + +PromoCounter::~PromoCounter() { +} + +// static +void PromoCounter::RegisterUserPrefs(PrefService* prefs, + const std::string& base_key) { + prefs->RegisterBooleanPref((base_key + kShowKey).c_str(), true); + prefs->RegisterIntegerPref((base_key + kNumSessionsKey).c_str(), 0); + prefs->RegisterInt64Pref((base_key + kInitialTimeKey).c_str(), 0); +} + +bool PromoCounter::ShouldShow(base::Time current_time) { + if (!did_init_) { + did_init_ = true; + Init(current_time); + } + + if (show_ && (current_time - initial_show_).InDays() >= max_days_) + MaxTimeLapsed(current_time); + + return show_; +} + +void PromoCounter::Hide() { + show_ = false; + did_init_ = true; + UMA_HISTOGRAM_CUSTOM_COUNTS(histogram_key_ + kHistogramHide, + (base::Time::Now() - initial_show_).InHours(), + 1, max_days_ * 24, 24); + if (profile_->GetPrefs()) + profile_->GetPrefs()->SetBoolean((pref_key_ + kShowKey).c_str(), false); +} + +void PromoCounter::Init(base::Time current_time) { + PrefService* prefs = profile_->GetPrefs(); + if (!prefs) + return; + + show_ = prefs->GetBoolean((pref_key_ + kShowKey).c_str()); + if (!show_) + return; + + // The user hasn't chosen to opt in or out. Only show the opt-in if it's + // less than max_days_ since we first showed the opt-in, or the user hasn't + // launched the profile max_sessions_ times. + int session_count = prefs->GetInteger((pref_key_ + kNumSessionsKey).c_str()); + int64 initial_show_int = + prefs->GetInt64((pref_key_ + kInitialTimeKey).c_str()); + initial_show_ = base::Time(base::Time::FromInternalValue(initial_show_int)); + if (initial_show_int == 0 || initial_show_ > current_time) { + initial_show_ = base::Time::Now(); + prefs->SetInt64((pref_key_ + kInitialTimeKey).c_str(), + initial_show_.ToInternalValue()); + } + if (session_count >= max_sessions_) { + // Time check is handled in ShouldShow. + MaxSessionsEncountered(current_time); + } else { + // Up the session count. + prefs->SetInteger((pref_key_ + kNumSessionsKey).c_str(), session_count + 1); + } +} + +void PromoCounter::MaxSessionsEncountered(base::Time current_time) { + show_ = false; + UMA_HISTOGRAM_CUSTOM_COUNTS(histogram_key_ + kHistogramMaxSessions, + (current_time - initial_show_).InHours(), 1, + max_days_ * 24, 24); + if (profile_->GetPrefs()) + profile_->GetPrefs()->SetBoolean((pref_key_ + kShowKey).c_str(), false); +} + +void PromoCounter::MaxTimeLapsed(base::Time current_time) { + show_ = false; + UMA_HISTOGRAM_CUSTOM_COUNTS(histogram_key_ + kHistogramMaxTime, + (current_time - initial_show_).InHours(), + 1, max_days_ * 24, 24); + if (profile_->GetPrefs()) + profile_->GetPrefs()->SetBoolean((pref_key_ + kShowKey).c_str(), false); +} diff --git a/chrome/browser/instant/promo_counter.h b/chrome/browser/instant/promo_counter.h new file mode 100644 index 0000000..480f677 --- /dev/null +++ b/chrome/browser/instant/promo_counter.h @@ -0,0 +1,78 @@ +// 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_INSTANT_PROMO_COUNTER_H_ +#define CHROME_BROWSER_INSTANT_PROMO_COUNTER_H_ +#pragma once + +#include + +#include "base/basictypes.h" +#include "base/time.h" + +class PrefService; +class Profile; + +// PromoCounter is used to track whether a promo should be shown. The promo is +// shown for a specified number of days or sessions (launches of chrome). +class PromoCounter { + public: + // Creates a new PromoCounter. |pref_key| is used to store prefs related to + // the promo. |histogram_key| is the key used to store histograms related to + // the promo. See the .cc file for the exact prefs and histogram values used. + // |ShouldShow| returns true until the users restarts chrome |max_sessions| or + // runs Chrome for |max_days|, or |Hide| is invoked. + PromoCounter(Profile* profile, + const std::string& pref_key, + const std::string& histogram_key, + int max_sessions, + int max_days); + ~PromoCounter(); + + // Registers the preferences used by PromoCounter. + static void RegisterUserPrefs(PrefService* prefs, + const std::string& base_key); + + // Returns true if the promo should be shown. + bool ShouldShow(base::Time current_time); + + // Permanently hides the promo. + void Hide(); + + private: + // Called the first time ShouldShow is invoked. Updates the necessary pref + // state and show_. + void Init(base::Time current_time); + + // Invoked if the max number of sessions has been encountered. + void MaxSessionsEncountered(base::Time current_time); + + // Invoked if the max number of days has elapsed. + void MaxTimeLapsed(base::Time current_time); + + Profile* profile_; + + // Base key all prefs are stored under. + const std::string pref_key_; + + // Base key used for histograms. + const std::string histogram_key_; + + // Max number of sessions/days before the promo stops. + const int max_sessions_; + const int max_days_; + + // Has Init been invoked? + bool did_init_; + + // Return value from ShouldShow. + bool show_; + + // Initial time the promo was first shown. + base::Time initial_show_; + + DISALLOW_COPY_AND_ASSIGN(PromoCounter); +}; + +#endif // CHROME_BROWSER_INSTANT_PROMO_COUNTER_H_ diff --git a/chrome/browser/instant/promo_counter_unittest.cc b/chrome/browser/instant/promo_counter_unittest.cc new file mode 100644 index 0000000..43cda77 --- /dev/null +++ b/chrome/browser/instant/promo_counter_unittest.cc @@ -0,0 +1,81 @@ +// 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/instant/promo_counter.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +typedef testing::Test PromoCounterTest; + +// Makes sure ShouldShow returns false after the max number of days. +TEST_F(PromoCounterTest, MaxTimeElapsed) { + TestingProfile profile; + PromoCounter::RegisterUserPrefs(profile.GetPrefs(), "test"); + + base::Time test_time(base::Time::Now()); + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_TRUE(counter.ShouldShow(test_time)); + ASSERT_TRUE(counter.ShouldShow(test_time + base::TimeDelta::FromHours(2))); + ASSERT_FALSE(counter.ShouldShow(test_time + base::TimeDelta::FromDays(4))); +} + +// Makes sure ShouldShow returns false after max number of sessions encountered. +TEST_F(PromoCounterTest, MaxSessionsLapsed) { + TestingProfile profile; + PromoCounter::RegisterUserPrefs(profile.GetPrefs(), "test"); + + base::Time test_time(base::Time::Now()); + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_TRUE(counter.ShouldShow(test_time)); + } + + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_TRUE(counter.ShouldShow(test_time)); + } + + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_FALSE(counter.ShouldShow(test_time)); + } +} + +// Makes sure invoking Hide make ShouldShow return false. +TEST_F(PromoCounterTest, Hide) { + TestingProfile profile; + PromoCounter::RegisterUserPrefs(profile.GetPrefs(), "test"); + + base::Time test_time(base::Time::Now()); + { + PromoCounter counter(&profile, "test", "test", 2, 2); + counter.Hide(); + ASSERT_FALSE(counter.ShouldShow(test_time)); + } + + // Recreate to make sure pref was correctly written. + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_FALSE(counter.ShouldShow(test_time)); + } +} + +// Same as Hide, but invokes ShouldShow first. +TEST_F(PromoCounterTest, Hide2) { + TestingProfile profile; + PromoCounter::RegisterUserPrefs(profile.GetPrefs(), "test"); + + base::Time test_time(base::Time::Now()); + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_TRUE(counter.ShouldShow(test_time)); + counter.Hide(); + ASSERT_FALSE(counter.ShouldShow(test_time)); + } + + { + PromoCounter counter(&profile, "test", "test", 2, 2); + ASSERT_FALSE(counter.ShouldShow(test_time)); + } +} diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index b12b7f0..65be41e 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -4,6 +4,8 @@ #include "chrome/browser/io_thread.h" +#include + #include "base/command_line.h" #include "base/debug/leak_tracker.h" #include "base/logging.h" @@ -21,9 +23,11 @@ #include "chrome/browser/net/connect_interceptor.h" #include "chrome/browser/net/passive_log_collector.h" #include "chrome/browser/net/predictor_api.h" +#include "chrome/browser/prefs/pref_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/net/raw_host_resolver_proc.h" #include "chrome/common/net/url_fetcher.h" +#include "chrome/common/pref_names.h" #include "net/base/dnsrr_resolver.h" #include "net/base/host_cache.h" #include "net/base/host_resolver.h" @@ -207,11 +211,26 @@ IOThread::Globals::Globals() {} IOThread::Globals::~Globals() {} -IOThread::IOThread() +// |local_state| is passed in explicitly in order to (1) reduce implicit +// dependencies and (2) make IOThread more flexible for testing. +IOThread::IOThread(PrefService* local_state) : BrowserProcessSubThread(BrowserThread::IO), globals_(NULL), speculative_interceptor_(NULL), - predictor_(NULL) {} + predictor_(NULL) { + // We call RegisterPrefs() here (instead of inside browser_prefs.cc) to make + // sure that everything is initialized in the right order. + RegisterPrefs(local_state); + auth_schemes_ = local_state->GetString(prefs::kAuthSchemes); + negotiate_disable_cname_lookup_ = local_state->GetBoolean( + prefs::kDisableAuthNegotiateCnameLookup); + negotiate_enable_port_ = local_state->GetBoolean( + prefs::kEnableAuthNegotiatePort); + auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist); + auth_delegate_whitelist_ = local_state->GetString( + prefs::kAuthNegotiateDelegateWhitelist); + gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName); +} IOThread::~IOThread() { // We cannot rely on our base class to stop the thread since we want our @@ -401,41 +420,38 @@ void IOThread::CleanUpAfterMessageLoopDestruction() { base::debug::LeakTracker::CheckForLeaks(); } +// static +void IOThread::RegisterPrefs(PrefService* local_state) { + local_state->RegisterStringPref(prefs::kAuthSchemes, + "basic,digest,ntlm,negotiate"); + local_state->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, + false); + local_state->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false); + local_state->RegisterStringPref(prefs::kAuthServerWhitelist, ""); + local_state->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist, ""); + local_state->RegisterStringPref(prefs::kGSSAPILibraryName, ""); +} + net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory( net::HostResolver* resolver) { - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - // Get the whitelist information from the command line, create an - // HttpAuthFilterWhitelist, and attach it to the HttpAuthHandlerFactory. - net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL; - if (command_line.HasSwitch(switches::kAuthServerWhitelist)) { - auth_filter_default_credentials = new net::HttpAuthFilterWhitelist( - command_line.GetSwitchValueASCII(switches::kAuthServerWhitelist)); - } - net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL; - if (command_line.HasSwitch(switches::kAuthNegotiateDelegateWhitelist)) { - auth_filter_delegate = new net::HttpAuthFilterWhitelist( - command_line.GetSwitchValueASCII( - switches::kAuthNegotiateDelegateWhitelist)); - } + net::HttpAuthFilterWhitelist* auth_filter_default_credentials = + new net::HttpAuthFilterWhitelist(auth_server_whitelist_); + net::HttpAuthFilterWhitelist* auth_filter_delegate = + new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_); globals_->url_security_manager.reset( net::URLSecurityManager::Create(auth_filter_default_credentials, auth_filter_delegate)); - - // Determine which schemes are supported. - std::string csv_auth_schemes = "basic,digest,ntlm,negotiate"; - if (command_line.HasSwitch(switches::kAuthSchemes)) - csv_auth_schemes = StringToLowerASCII( - command_line.GetSwitchValueASCII(switches::kAuthSchemes)); std::vector supported_schemes; - base::SplitString(csv_auth_schemes, ',', &supported_schemes); + base::SplitString(auth_schemes_, ',', &supported_schemes); return net::HttpAuthHandlerRegistryFactory::Create( supported_schemes, globals_->url_security_manager.get(), resolver, - command_line.HasSwitch(switches::kDisableAuthNegotiateCnameLookup), - command_line.HasSwitch(switches::kEnableAuthNegotiatePort)); + gssapi_library_name_, + negotiate_disable_cname_lookup_, + negotiate_enable_port_); } void IOThread::InitNetworkPredictorOnIOThread( diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 99cb281..d7ba9db 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h @@ -8,6 +8,7 @@ #include #include +#include #include "base/basictypes.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" @@ -19,6 +20,7 @@ class ChromeNetLog; class ChromeURLRequestContextGetter; class ListValue; +class PrefService; class URLRequestContext; namespace chrome_browser_net { @@ -48,7 +50,7 @@ class IOThread : public BrowserProcessSubThread { ChromeNetworkDelegate network_delegate; }; - IOThread(); + explicit IOThread(PrefService* local_state); virtual ~IOThread(); @@ -102,6 +104,8 @@ class IOThread : public BrowserProcessSubThread { class ManagedProxyScriptFetcher; typedef std::set ProxyScriptFetchers; + static void RegisterPrefs(PrefService* local_state); + net::HttpAuthHandlerFactory* CreateDefaultAuthHandlerFactory( net::HostResolver* resolver); @@ -134,6 +138,14 @@ class IOThread : public BrowserProcessSubThread { // Observer that logs network changes to the ChromeNetLog. scoped_ptr network_change_observer_; + // Store HTTP Auth-related policies in this thread. + std::string auth_schemes_; + bool negotiate_disable_cname_lookup_; + bool negotiate_enable_port_; + std::string auth_server_whitelist_; + std::string auth_delegate_whitelist_; + std::string gssapi_library_name_; + // These member variables are initialized by a task posted to the IO thread, // which gets posted by calling certain member functions of IOThread. diff --git a/chrome/browser/media_uitest.cc b/chrome/browser/media_uitest.cc index c5c444b..fbbdebc 100644 --- a/chrome/browser/media_uitest.cc +++ b/chrome/browser/media_uitest.cc @@ -2,16 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "app/gfx/gl/gl_implementation.h" #include "base/basictypes.h" #include "base/file_path.h" #include "base/platform_thread.h" #include "base/string_util.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/test_launcher_utils.h" #include "chrome/test/ui/ui_layout_test.h" #include "chrome/test/ui/ui_test.h" #include "net/base/net_util.h" class MediaTest : public UITest { protected: + virtual void SetUp() { + EXPECT_TRUE(test_launcher_utils::OverrideGLImplementation( + &launch_arguments_, + gfx::kGLImplementationOSMesaName)); + +#if defined(OS_MACOSX) + // Accelerated compositing does not work with OSMesa. AcceleratedSurface + // assumes GL contexts are native. + launch_arguments_.AppendSwitch(switches::kDisableAcceleratedCompositing); +#endif + + UITest::SetUp(); + } + void PlayMedia(const char* tag, const char* media_file) { FilePath test_file(test_data_directory_); test_file = test_file.AppendASCII("media/player.html"); @@ -48,28 +65,6 @@ class MediaTest : public UITest { } }; -#if defined(OS_WIN) - -// Tests always fail on windows: http://crbug.com/55477 -#define MAYBE_VideoBearTheora DISABLED_VideoBearTheora -#define MAYBE_VideoBearSilentTheora DISABLED_VideoBearSilentTheora -#define MAYBE_VideoBearWebm DISABLED_VideoBearWebm -#define MAYBE_VideoBearSilentWebm DISABLED_VideoBearSilentWebm -#define MAYBE_VideoBearMp4 DISABLED_VideoBearMp4 -#define MAYBE_VideoBearSilentMp4 DISABLED_VideoBearSilentMp4 -#define MAYBE_VideoBearWav DISABLED_VideoBearWav -#define MAYBE_MediaUILayoutTest DISABLED_MediaUILayoutTest - -#else - -#define MAYBE_VideoBearTheora VideoBearTheora -#define MAYBE_VideoBearSilentTheora VideoBearSilentTheora -#define MAYBE_VideoBearWebm VideoBearWebm -#define MAYBE_VideoBearSilentWebm VideoBearSilentWebm -#define MAYBE_VideoBearMp4 VideoBearMp4 -#define MAYBE_VideoBearSilentMp4 VideoBearSilentMp4 -#define MAYBE_VideoBearWav VideoBearWav - #if defined(OS_LINUX) // Test fails on linux: http://crbug.com/56364 #define MAYBE_MediaUILayoutTest DISABLED_MediaUILayoutTest @@ -77,35 +72,33 @@ class MediaTest : public UITest { #define MAYBE_MediaUILayoutTest MediaUILayoutTest #endif -#endif - -TEST_F(MediaTest, MAYBE_VideoBearTheora) { +TEST_F(MediaTest, VideoBearTheora) { PlayVideo("bear.ogv"); } -TEST_F(MediaTest, MAYBE_VideoBearSilentTheora) { +TEST_F(MediaTest, VideoBearSilentTheora) { PlayVideo("bear_silent.ogv"); } -TEST_F(MediaTest, MAYBE_VideoBearWebm) { +TEST_F(MediaTest, VideoBearWebm) { PlayVideo("bear.webm"); } -TEST_F(MediaTest, MAYBE_VideoBearSilentWebm) { +TEST_F(MediaTest, VideoBearSilentWebm) { PlayVideo("bear_silent.webm"); } #if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) -TEST_F(MediaTest, MAYBE_VideoBearMp4) { +TEST_F(MediaTest, VideoBearMp4) { PlayVideo("bear.mp4"); } -TEST_F(MediaTest, MAYBE_VideoBearSilentMp4) { +TEST_F(MediaTest, VideoBearSilentMp4) { PlayVideo("bear_silent.mp4"); } #endif -TEST_F(MediaTest, MAYBE_VideoBearWav) { +TEST_F(MediaTest, VideoBearWav) { PlayVideo("bear.wav"); } diff --git a/chrome/browser/metrics/histogram_synchronizer.cc b/chrome/browser/metrics/histogram_synchronizer.cc index 0fa0c82..a84d6c7 100644 --- a/chrome/browser/metrics/histogram_synchronizer.cc +++ b/chrome/browser/metrics/histogram_synchronizer.cc @@ -16,17 +16,18 @@ using base::Time; using base::TimeDelta; using base::TimeTicks; +static const int kNeverUsableSequenceNumber = -2; + HistogramSynchronizer::HistogramSynchronizer() : lock_(), received_all_renderer_histograms_(&lock_), callback_task_(NULL), callback_thread_(NULL), - io_message_loop_(NULL), - next_available_sequence_number_(-2), - async_sequence_number_(-2), + next_available_sequence_number_(kNeverUsableSequenceNumber), + async_sequence_number_(kNeverUsableSequenceNumber), async_renderers_pending_(0), async_callback_start_time_(TimeTicks::Now()), - synchronous_sequence_number_(-2), + synchronous_sequence_number_(kNeverUsableSequenceNumber), synchronous_renderers_pending_(0) { DCHECK(histogram_synchronizer_ == NULL); histogram_synchronizer_ = this; @@ -71,7 +72,7 @@ void HistogramSynchronizer::FetchRendererHistogramsSynchronously( } unresponsive_renderer_count = synchronous_renderers_pending_; synchronous_renderers_pending_ = 0; - synchronous_sequence_number_ = 0; + synchronous_sequence_number_ = kNeverUsableSequenceNumber; } UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingSynchronous", unresponsive_renderer_count); @@ -138,7 +139,7 @@ void HistogramSynchronizer::DeserializeHistogramList( if (current_synchronizer == NULL) return; - DCHECK(current_synchronizer->IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); for (std::vector::const_iterator it = histograms.begin(); it < histograms.end(); @@ -152,7 +153,7 @@ void HistogramSynchronizer::DeserializeHistogramList( bool HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) { if (sequence_number == async_sequence_number_) { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if ((async_renderers_pending_ == 0) || (--async_renderers_pending_ > 0)) return false; @@ -173,7 +174,7 @@ bool HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) { DCHECK_EQ(synchronous_renderers_pending_, 0); } - // We could call Signal() without holding the lock. + // We can call Signal() without holding the lock. received_all_renderer_histograms_.Signal(); return true; } @@ -182,7 +183,7 @@ bool HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) { void HistogramSynchronizer::SetCallbackTaskToCallAfterGettingHistograms( MessageLoop* callback_thread, Task* callback_task) { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // Test for the existence of a previous task, and post call to post it if it // exists. We promised to post it after some timeout... and at this point, we @@ -204,7 +205,7 @@ void HistogramSynchronizer::SetCallbackTaskToCallAfterGettingHistograms( void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback( int sequence_number) { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (sequence_number == async_sequence_number_) { CallCallbackTaskAndResetData(); @@ -215,7 +216,7 @@ void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback( // the renderers, call the callback_task if a callback_task exists. This is // called on IO Thread. void HistogramSynchronizer::CallCallbackTaskAndResetData() { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // callback_task_ would be set to NULL, if we have heard from all renderers // and we would have called the callback_task already. @@ -236,6 +237,7 @@ void HistogramSynchronizer::CallCallbackTaskAndResetData() { async_callback_start_time_ = TimeTicks::Now(); callback_task_ = NULL; callback_thread_ = NULL; + async_sequence_number_ = kNeverUsableSequenceNumber; } int HistogramSynchronizer::GetNextAvailableSequenceNumber( @@ -243,14 +245,14 @@ int HistogramSynchronizer::GetNextAvailableSequenceNumber( AutoLock auto_lock(lock_); ++next_available_sequence_number_; if (0 > next_available_sequence_number_) { - // We wrapped around. + // We wrapped around, so we need to bypass the reserved number. next_available_sequence_number_ = chrome::kHistogramSynchronizerReservedSequenceNumber + 1; } DCHECK_NE(next_available_sequence_number_, chrome::kHistogramSynchronizerReservedSequenceNumber); if (requester == ASYNC_HISTOGRAMS) { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); async_sequence_number_ = next_available_sequence_number_; async_renderers_pending_ = 1; } else if (requester == SYNCHRONOUS_HISTOGRAMS) { @@ -263,7 +265,7 @@ int HistogramSynchronizer::GetNextAvailableSequenceNumber( void HistogramSynchronizer::IncrementPendingRenderers( RendererHistogramRequester requester) { if (requester == ASYNC_HISTOGRAMS) { - DCHECK(IsOnIoThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK_GT(async_renderers_pending_, 0); ++async_renderers_pending_; } else { @@ -273,12 +275,5 @@ void HistogramSynchronizer::IncrementPendingRenderers( } } -bool HistogramSynchronizer::IsOnIoThread() { - if (io_message_loop_ == NULL) { - io_message_loop_ = MessageLoop::current(); - } - return (MessageLoop::current() == io_message_loop_); -} - // static HistogramSynchronizer* HistogramSynchronizer::histogram_synchronizer_ = NULL; diff --git a/chrome/browser/metrics/histogram_synchronizer.h b/chrome/browser/metrics/histogram_synchronizer.h index 9190b20..bebd6d2 100644 --- a/chrome/browser/metrics/histogram_synchronizer.h +++ b/chrome/browser/metrics/histogram_synchronizer.h @@ -81,12 +81,6 @@ class HistogramSynchronizer : public // of the given type. void IncrementPendingRenderers(RendererHistogramRequester requester); - // For use ONLY in a DCHECK. This method initializes io_message_loop_ in its - // first call and then compares io_message_loop_ with MessageLoop::current() - // in subsequent calls. This method guarantees we're consistently on the - // singular IO thread and we don't need to worry about locks. - bool IsOnIoThread(); - // This lock_ protects access to next_sequence_number_, // synchronous_renderers_pending_, and synchronous_sequence_number_. Lock lock_; @@ -101,17 +95,12 @@ class HistogramSynchronizer : public Task* callback_task_; MessageLoop* callback_thread_; - // For use ONLY in a DCHECK and is used in IsOnIoThread(). io_message_loop_ is - // initialized during the first call to IsOnIoThread(), and then compares - // MessageLoop::current() against io_message_loop_ in subsequent calls for - // consistency. - MessageLoop* io_message_loop_; - // We don't track the actual renderers that are contacted for an update, only // the count of the number of renderers, and we can sometimes time-out and // give up on a "slow to respond" renderer. We use a sequence_number to be // sure a response from a renderer is associated with the current round of // requests (and not merely a VERY belated prior response). + // All sequence numbers used are non-negative. // next_available_sequence_number_ is the next available number (used to // avoid reuse for a long time). Access is protected by lock_. int next_available_sequence_number_; diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc index 5a7db76..e21f075 100644 --- a/chrome/browser/metrics/metrics_log.cc +++ b/chrome/browser/metrics/metrics_log.cc @@ -19,7 +19,7 @@ #include "chrome/browser/autocomplete/autocomplete.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/gpu_process_host.h" +#include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/logging_chrome.h" @@ -301,9 +301,9 @@ void MetricsLog::RecordEnvironment( { OPEN_ELEMENT_FOR_SCOPE("gpu"); WriteIntAttribute("vendorid", - GpuProcessHost::Get()->gpu_info().vendor_id()); + GpuProcessHostUIShim::Get()->gpu_info().vendor_id()); WriteIntAttribute("deviceid", - GpuProcessHost::Get()->gpu_info().device_id()); + GpuProcessHostUIShim::Get()->gpu_info().device_id()); } { diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc index 27c84c6..184500d 100644 --- a/chrome/browser/metrics/metrics_log_unittest.cc +++ b/chrome/browser/metrics/metrics_log_unittest.cc @@ -213,8 +213,8 @@ TEST(MetricsLogTest, CreateHash) { // the metrics server uses. std::string hash_hex = "0x"; for (size_t j = 0; j < 8; j++) { - StringAppendF(&hash_hex, "%02x", - static_cast(hash_string.data()[j])); + base::StringAppendF(&hash_hex, "%02x", + static_cast(hash_string.data()[j])); } EXPECT_EQ(cases[i].output, hash_hex); } diff --git a/chrome/browser/mime_registry_dispatcher.cc b/chrome/browser/mime_registry_dispatcher.cc new file mode 100644 index 0000000..bc8653f --- /dev/null +++ b/chrome/browser/mime_registry_dispatcher.cc @@ -0,0 +1,96 @@ +// 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/mime_registry_dispatcher.h" + +#include "chrome/browser/browser_thread.h" +#include "chrome/common/render_messages.h" +#include "net/base/mime_util.h" + +MimeRegistryDispatcher::MimeRegistryDispatcher(IPC::Message::Sender* sender) + : message_sender_(sender) { + DCHECK(message_sender_); +} + +MimeRegistryDispatcher::~MimeRegistryDispatcher() { +} + +void MimeRegistryDispatcher::Shutdown() { + message_sender_ = NULL; +} + +bool MimeRegistryDispatcher::OnMessageReceived(const IPC::Message& message) { + // On Windows MIME registry requests may access the Windows Registry so + // they need to run on the FILE thread. + if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { + // Return false if the message is not for us. + if (message.type() != ViewHostMsg_GetMimeTypeFromExtension::ID && + message.type() != ViewHostMsg_GetMimeTypeFromFile::ID && + message.type() != ViewHostMsg_GetPreferredExtensionForMimeType::ID) + return false; + + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + NewRunnableMethod( + this, &MimeRegistryDispatcher::OnMessageReceived, message)); + return true; + } + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(MimeRegistryDispatcher, message) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetMimeTypeFromExtension, + OnGetMimeTypeFromExtension) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetMimeTypeFromFile, + OnGetMimeTypeFromFile) + IPC_MESSAGE_HANDLER_DELAY_REPLY( + ViewHostMsg_GetPreferredExtensionForMimeType, + OnGetPreferredExtensionForMimeType) + IPC_MESSAGE_UNHANDLED((handled = false)) + IPC_END_MESSAGE_MAP() + return handled; +} + +void MimeRegistryDispatcher::OnGetMimeTypeFromExtension( + const FilePath::StringType& ext, IPC::Message* reply_msg) { + std::string mime_type; + net::GetMimeTypeFromExtension(ext, &mime_type); + ViewHostMsg_GetMimeTypeFromExtension::WriteReplyParams(reply_msg, mime_type); + Send(reply_msg); +} + +void MimeRegistryDispatcher::OnGetMimeTypeFromFile( + const FilePath& file_path, IPC::Message* reply_msg) { + std::string mime_type; + net::GetMimeTypeFromFile(file_path, &mime_type); + ViewHostMsg_GetMimeTypeFromFile::WriteReplyParams(reply_msg, mime_type); + Send(reply_msg); +} + +void MimeRegistryDispatcher::OnGetPreferredExtensionForMimeType( + const std::string& mime_type, IPC::Message* reply_msg) { + FilePath::StringType ext; + net::GetPreferredExtensionForMimeType(mime_type, &ext); + ViewHostMsg_GetPreferredExtensionForMimeType::WriteReplyParams( + reply_msg, ext); + Send(reply_msg); +} + +void MimeRegistryDispatcher::Send(IPC::Message* message) { + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { + if (!BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, NewRunnableMethod( + this, &MimeRegistryDispatcher::Send, message))) { + // The IO thread is dead. + delete message; + } + return; + } + + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (message_sender_) + message_sender_->Send(message); + else + delete message; +} diff --git a/chrome/browser/mime_registry_dispatcher.h b/chrome/browser/mime_registry_dispatcher.h new file mode 100644 index 0000000..0bd17dd --- /dev/null +++ b/chrome/browser/mime_registry_dispatcher.h @@ -0,0 +1,37 @@ +// 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_MIME_REGISTRY_DISPATCHER_H_ +#define CHROME_BROWSER_MIME_REGISTRY_DISPATCHER_H_ + +#include "base/file_path.h" +#include "base/ref_counted.h" +#include "ipc/ipc_message.h" + +class MimeRegistryDispatcher + : public base::RefCountedThreadSafe { + public: + explicit MimeRegistryDispatcher(IPC::Message::Sender* sender); + void Shutdown(); + bool OnMessageReceived(const IPC::Message& message); + void Send(IPC::Message* message); + + private: + friend class base::RefCountedThreadSafe; + ~MimeRegistryDispatcher(); + + void OnGetMimeTypeFromExtension(const FilePath::StringType& ext, + IPC::Message* reply); + void OnGetMimeTypeFromFile(const FilePath& file_path, + IPC::Message* reply); + void OnGetPreferredExtensionForMimeType(const std::string& mime_type, + IPC::Message* reply); + + // The sender to be used for sending out IPC messages. + IPC::Message::Sender* message_sender_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(MimeRegistryDispatcher); +}; + +#endif // CHROME_BROWSER_MIME_REGISTRY_DISPATCHER_H_ diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index b5123ef..8200892 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -248,11 +248,35 @@ void NaClProcessHost::SendStartMessage() { #else nacl::FileDescriptor channel; channel.fd = dup(sockets_for_sel_ldr_[i]); + if (channel.fd < 0) { + LOG(ERROR) << "Failed to dup() a file descriptor"; + return; + } channel.auto_close = true; handles_for_sel_ldr.push_back(channel); #endif } +#if defined(OS_MACOSX) + // For dynamic loading support, NaCl requires a file descriptor that + // was created in /tmp, since those created with shm_open() are not + // mappable with PROT_EXEC. Rather than requiring an extra IPC + // round trip out of the sandbox, we create an FD here. + base::SharedMemory memory_buffer; + if (!memory_buffer.CreateAnonymous(/* size= */ 1)) { + LOG(ERROR) << "Failed to allocate memory buffer"; + return; + } + nacl::FileDescriptor memory_fd; + memory_fd.fd = dup(memory_buffer.handle().fd); + if (memory_fd.fd < 0) { + LOG(ERROR) << "Failed to dup() a file descriptor"; + return; + } + memory_fd.auto_close = true; + handles_for_sel_ldr.push_back(memory_fd); +#endif + Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); sockets_for_sel_ldr_.clear(); } diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index a40e548..159c674 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -834,7 +834,7 @@ ChromeURLRequestContext::ChromeURLRequestContext( is_media_ = other->is_media_; is_off_the_record_ = other->is_off_the_record_; blob_storage_context_ = other->blob_storage_context_; - file_system_host_context_ = other->file_system_host_context_; + browser_file_system_context_ = other->browser_file_system_context_; extension_info_map_ = other->extension_info_map_; } @@ -902,7 +902,7 @@ ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile) appcache_service_ = profile->GetAppCacheService(); database_tracker_ = profile->GetDatabaseTracker(); blob_storage_context_ = profile->GetBlobStorageContext(); - file_system_host_context_ = profile->GetFileSystemHostContext(); + browser_file_system_context_ = profile->GetFileSystemContext(); extension_info_map_ = profile->GetExtensionInfoMap(); } @@ -928,7 +928,7 @@ void ChromeURLRequestContextFactory::ApplyProfileParametersToContext( context->set_appcache_service(appcache_service_); context->set_database_tracker(database_tracker_); context->set_blob_storage_context(blob_storage_context_); - context->set_file_system_host_context(file_system_host_context_); + context->set_browser_file_system_context(browser_file_system_context_); context->set_extension_info_map(extension_info_map_); } diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index 51d9246..72a31af 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -13,7 +13,7 @@ #include "chrome/browser/appcache/chrome_appcache_service.h" #include "chrome/browser/chrome_blob_storage_context.h" #include "chrome/browser/extensions/extension_info_map.h" -#include "chrome/browser/file_system/file_system_host_context.h" +#include "chrome/browser/file_system/browser_file_system_context.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/host_zoom_map.h" #include "chrome/browser/io_thread.h" @@ -71,8 +71,8 @@ class ChromeURLRequestContext : public URLRequestContext { } // Gets the file system host context with this context's profile. - FileSystemHostContext* file_system_host_context() const { - return file_system_host_context_.get(); + BrowserFileSystemContext* browser_file_system_context() const { + return browser_file_system_context_.get(); } bool is_off_the_record() const { @@ -174,8 +174,8 @@ class ChromeURLRequestContext : public URLRequestContext { void set_blob_storage_context(ChromeBlobStorageContext* context) { blob_storage_context_ = context; } - void set_file_system_host_context(FileSystemHostContext* context) { - file_system_host_context_ = context; + void set_browser_file_system_context(BrowserFileSystemContext* context) { + browser_file_system_context_ = context; } void set_extension_info_map(ExtensionInfoMap* map) { extension_info_map_ = map; @@ -204,7 +204,7 @@ class ChromeURLRequestContext : public URLRequestContext { scoped_refptr host_content_settings_map_; scoped_refptr host_zoom_map_; scoped_refptr blob_storage_context_; - scoped_refptr file_system_host_context_; + scoped_refptr browser_file_system_context_; scoped_refptr extension_info_map_; bool is_media_; @@ -373,7 +373,7 @@ class ChromeURLRequestContextFactory { scoped_refptr ssl_config_service_; scoped_refptr cookie_monster_delegate_; scoped_refptr blob_storage_context_; - scoped_refptr file_system_host_context_; + scoped_refptr browser_file_system_context_; scoped_refptr extension_info_map_; FilePath profile_dir_path_; diff --git a/chrome/browser/net/chrome_url_request_context_unittest.cc b/chrome/browser/net/chrome_url_request_context_unittest.cc index f0947bd..5faaf44 100644 --- a/chrome/browser/net/chrome_url_request_context_unittest.cc +++ b/chrome/browser/net/chrome_url_request_context_unittest.cc @@ -162,6 +162,7 @@ TEST(ChromeURLRequestContextTest, CreateProxyConfigTest) { CommandLine command_line(tests[i].command_line); // Only configuration-policy and default prefs are needed. PrefService prefs(new TestingPrefService::TestingPrefValueStore( + new policy::ConfigurationPolicyPrefStore(NULL), new policy::ConfigurationPolicyPrefStore(NULL), NULL, new CommandLinePrefStore(&command_line), NULL, NULL, new DefaultPrefStore())); diff --git a/chrome/browser/net/connection_tester_unittest.cc b/chrome/browser/net/connection_tester_unittest.cc index 4191484..5bab81e 100644 --- a/chrome/browser/net/connection_tester_unittest.cc +++ b/chrome/browser/net/connection_tester_unittest.cc @@ -5,6 +5,7 @@ #include "chrome/browser/net/connection_tester.h" #include "chrome/browser/io_thread.h" +#include "chrome/test/testing_pref_service.h" #include "net/base/mock_host_resolver.h" #include "net/test/test_server.h" #include "testing/gtest/include/gtest/gtest.h" @@ -75,7 +76,9 @@ class ConnectionTesterTest : public PlatformTest { ConnectionTesterTest() : test_server_(net::TestServer::TYPE_HTTP, FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))), - message_loop_(MessageLoop::TYPE_IO) { + message_loop_(MessageLoop::TYPE_IO), + pref_service(new TestingPrefService()), + io_thread_(pref_service.get()) { scoped_refptr catchall_resolver( new net::RuleBasedHostResolverProc(NULL)); @@ -89,6 +92,7 @@ class ConnectionTesterTest : public PlatformTest { net::TestServer test_server_; ConnectionTesterDelegate test_delegate_; MessageLoop message_loop_; + scoped_ptr pref_service; IOThread io_thread_; // Needed for creating ProxyScriptFetchers. }; diff --git a/chrome/browser/net/cookie_policy_browsertest.cc b/chrome/browser/net/cookie_policy_browsertest.cc index 822154e..414b8aa 100644 --- a/chrome/browser/net/cookie_policy_browsertest.cc +++ b/chrome/browser/net/cookie_policy_browsertest.cc @@ -4,9 +4,9 @@ #include "base/task.h" #include "base/waitable_event.h" -#include "chrome/browser/browser.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/net/url_request_context_getter.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" diff --git a/chrome/browser/net/gaia/token_service.cc b/chrome/browser/net/gaia/token_service.cc index a2c4cfe..b79a6f4 100644 --- a/chrome/browser/net/gaia/token_service.cc +++ b/chrome/browser/net/gaia/token_service.cc @@ -9,7 +9,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/profile.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/url_request_context_getter.h" #include "chrome/common/notification_service.h" @@ -95,7 +95,7 @@ void TokenService::UpdateCredentials( // Cancels any currently running requests. for (int i = 0; i < kNumServices; i++) { - fetchers_[i].reset(new GaiaAuthenticator2(this, source_, getter_)); + fetchers_[i].reset(new GaiaAuthFetcher(this, source_, getter_)); } } diff --git a/chrome/browser/net/gaia/token_service.h b/chrome/browser/net/gaia/token_service.h index bc17c2b..35e9e85 100644 --- a/chrome/browser/net/gaia/token_service.h +++ b/chrome/browser/net/gaia/token_service.h @@ -42,7 +42,7 @@ #include "base/scoped_ptr.h" #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" @@ -178,7 +178,7 @@ class TokenService : public GaiaAuthConsumer, static const char* kServices[kNumServices]; // A bunch of fetchers suitable for token issuing. We don't care about // the ordering, nor do we care which is for which service. - scoped_ptr fetchers_[kNumServices]; + scoped_ptr fetchers_[kNumServices]; // Map from service to token. std::map token_map_; diff --git a/chrome/browser/net/gaia/token_service_unittest.cc b/chrome/browser/net/gaia/token_service_unittest.cc index 7b89428..d06956f 100644 --- a/chrome/browser/net/gaia/token_service_unittest.cc +++ b/chrome/browser/net/gaia/token_service_unittest.cc @@ -8,7 +8,7 @@ #include "base/command_line.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/test_url_fetcher_factory.h" diff --git a/chrome/browser/net/passive_log_collector.cc b/chrome/browser/net/passive_log_collector.cc index 2aca24f..84a9403 100644 --- a/chrome/browser/net/passive_log_collector.cc +++ b/chrome/browser/net/passive_log_collector.cc @@ -289,6 +289,15 @@ void PassiveLogCollector::SourceTracker::AddToDeletionQueue( } } +void PassiveLogCollector::SourceTracker::EraseFromDeletionQueue( + uint32 source_id) { + DeletionQueue::iterator it = + std::remove(deletion_queue_.begin(), deletion_queue_.end(), + source_id); + DCHECK(it != deletion_queue_.end()); + deletion_queue_.erase(it); +} + void PassiveLogCollector::SourceTracker::AdjustReferenceCountForSource( int offset, uint32 source_id) { DCHECK(offset == -1 || offset == 1) << "invalid offset: " << offset; @@ -306,7 +315,8 @@ void PassiveLogCollector::SourceTracker::AdjustReferenceCountForSource( DCHECK_GE(info.reference_count, 0); info.reference_count += offset; - if (info.reference_count < 0) { + bool released_unmatched_reference = info.reference_count < 0; + if (released_unmatched_reference) { // In general this shouldn't happen, however it is possible to reach this // state if SourceTracker::Clear() was called earlier. LOG(WARNING) << "Released unmatched reference count."; @@ -317,12 +327,10 @@ void PassiveLogCollector::SourceTracker::AdjustReferenceCountForSource( if (info.reference_count == 1 && offset == 1) { // If we just added a reference to a dead source that had no references, // it must have been in the deletion queue, so remove it from the queue. - DeletionQueue::iterator it = - std::remove(deletion_queue_.begin(), deletion_queue_.end(), - source_id); - DCHECK(it != deletion_queue_.end()); - deletion_queue_.erase(it); + EraseFromDeletionQueue(source_id); } else if (info.reference_count == 0) { + if (released_unmatched_reference) + EraseFromDeletionQueue(source_id); // If we just released the final reference to a dead source, go ahead // and delete it right away. DeleteSourceInfo(source_id); diff --git a/chrome/browser/net/passive_log_collector.h b/chrome/browser/net/passive_log_collector.h index d98049d..5d46fb3 100644 --- a/chrome/browser/net/passive_log_collector.h +++ b/chrome/browser/net/passive_log_collector.h @@ -181,6 +181,9 @@ class PassiveLogCollector : public ChromeNetLog::Observer { // Adds |source_id| to the FIFO queue (graveyard) for deletion. void AddToDeletionQueue(uint32 source_id); + // Removes |source_id| from the |deletion_queue_| container. + void EraseFromDeletionQueue(uint32 source_id); + // Adds/Releases a reference from the source with ID |source_id|. // Use |offset=-1| to do a release, and |offset=1| for an addref. void AdjustReferenceCountForSource(int offset, uint32 source_id); diff --git a/chrome/browser/net/passive_log_collector_unittest.cc b/chrome/browser/net/passive_log_collector_unittest.cc index 18530a6..e7d6074 100644 --- a/chrome/browser/net/passive_log_collector_unittest.cc +++ b/chrome/browser/net/passive_log_collector_unittest.cc @@ -438,3 +438,57 @@ TEST(PassiveLogCollectorTest, HoldReferenceToDeletedSource) { GetDeadSources(log.url_request_tracker_).size()); } +// Regression test for http://crbug.com/58847 +TEST(PassiveLogCollectorTest, ReleaseDependencyToUnreferencedSource) { + PassiveLogCollector log; + + // If these constants are weird, the test won't be testing the right thing. + EXPECT_LT(PassiveLogCollector::RequestTracker::kMaxGraveyardSize, + PassiveLogCollector::RequestTracker::kMaxNumSources); + + // Add a "reference" to a non-existant source (sourceID=1706 does not exist). + scoped_refptr params = + new net::NetLogSourceParameter( + "source_dependency", + net::NetLog::Source(net::NetLog::SOURCE_SOCKET, 1263)); + log.OnAddEntry(net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, + base::TimeTicks(), + net::NetLog::Source(net::NetLog::SOURCE_URL_REQUEST, 1706), + net::NetLog::PHASE_NONE, + params); + + // At this point source 1706 has noted 1263 as a dependency. However the + // reference count for 1263 was not adjusted since it doesn't actually exist. + + // Move source 1706 to the graveyard. + log.OnAddEntry(net::NetLog::TYPE_REQUEST_ALIVE, + base::TimeTicks(), + net::NetLog::Source(net::NetLog::SOURCE_URL_REQUEST, 1706), + net::NetLog::PHASE_END, + NULL); + + // Now create a source entry for 1263, such that it is unreferenced and + // waiting to be garbage collected. + log.OnAddEntry(net::NetLog::TYPE_SOCKET_ALIVE, + base::TimeTicks(), + net::NetLog::Source(net::NetLog::SOURCE_SOCKET, 1263), + net::NetLog::PHASE_END, NULL); + + // Add kMaxGraveyardSize unreferenced URL_REQUESTS, so the circular buffer + // containing source 1706. After adding kMaxGraveyardSize - 1 the buffer + // will be full. Now when we add one more more source it will now evict the + // oldest item, which is 1706. In doing so, 1706 will try to release the + // reference it *thinks* it has on 1263. However 1263 has a reference count + // of 0 and is already in a graveyard. + for (size_t i = 0; + i < PassiveLogCollector::RequestTracker::kMaxGraveyardSize; ++i) { + log.OnAddEntry(net::NetLog::TYPE_REQUEST_ALIVE, + base::TimeTicks(), + net::NetLog::Source(net::NetLog::SOURCE_URL_REQUEST, i), + net::NetLog::PHASE_END, + NULL); + } + + // To pass, this should simply not have DCHECK-ed above. +} + diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index fd55d2f..2c8ce5f 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc @@ -361,14 +361,16 @@ void Predictor::GetHtmlReferrerLists(std::string* output) { for (Referrer::iterator future_url = referrer->begin(); future_url != referrer->end(); ++future_url) { output->append(""); - if (first_set_of_futures) - StringAppendF(output, "", - static_cast(referrer->size()), - it->spec().c_str(), - static_cast(referrer->size()), - static_cast(referrer->use_count())); + if (first_set_of_futures) { + base::StringAppendF(output, + "", + static_cast(referrer->size()), + it->spec().c_str(), + static_cast(referrer->size()), + static_cast(referrer->use_count())); + } first_set_of_futures = false; - StringAppendF(output, + base::StringAppendF(output, "", static_cast(future_url->second.navigation_count()), static_cast(future_url->second.preconnection_count()), diff --git a/chrome/browser/net/predictor_api.cc b/chrome/browser/net/predictor_api.cc index a0d885b..290a566 100644 --- a/chrome/browser/net/predictor_api.cc +++ b/chrome/browser/net/predictor_api.cc @@ -14,7 +14,6 @@ #include "base/thread.h" #include "base/values.h" #include "base/waitable_event.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/io_thread.h" @@ -24,6 +23,7 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/net/url_info.cc b/chrome/browser/net/url_info.cc index 505425a..8418b12 100644 --- a/chrome/browser/net/url_info.cc +++ b/chrome/browser/net/url_info.cc @@ -251,10 +251,10 @@ static std::string HoursMinutesSeconds(int seconds) { int print_minutes = minutes % 60; int print_hours = minutes/60; if (print_hours) - StringAppendF(&result, "%.2d:", print_hours); + base::StringAppendF(&result, "%.2d:", print_hours); if (print_hours || print_minutes) - StringAppendF(&result, "%2.2d:", print_minutes); - StringAppendF(&result, "%2.2d", print_seconds); + base::StringAppendF(&result, "%2.2d:", print_minutes); + base::StringAppendF(&result, "%2.2d", print_seconds); return result; } @@ -266,8 +266,8 @@ void UrlInfo::GetHtmlTable(const UrlInfoTable host_infos, if (0 == host_infos.size()) return; output->append(description); - StringAppendF(output, "%" PRIuS " %s", host_infos.size(), - (1 == host_infos.size()) ? "hostname" : "hostnames"); + base::StringAppendF(output, "%" PRIuS " %s", host_infos.size(), + (1 == host_infos.size()) ? "hostname" : "hostnames"); if (brief) { output->append("

"); @@ -291,18 +291,21 @@ void UrlInfo::GetHtmlTable(const UrlInfoTable host_infos, for (UrlInfoTable::const_iterator it(host_infos.begin()); it != host_infos.end(); it++) { queue.sample((it->queue_duration_.InMilliseconds())); - StringAppendF(output, row_format, - RemoveJs(it->url_.spec()).c_str(), - HoursMinutesSeconds(when.sample( - (current_time - it->time_).InSeconds())).c_str(), - it->GetAsciiMotivation().c_str()); + base::StringAppendF( + output, + row_format, + RemoveJs(it->url_.spec()).c_str(), + HoursMinutesSeconds(when.sample( + (current_time - it->time_).InSeconds())).c_str(), + it->GetAsciiMotivation().c_str()); } output->append("
%s%d%s%d%d%d%d%2.3f%s
"); #ifndef NDEBUG - StringAppendF(output, - "Prefetch Queue Durations: min=%d, avg=%d, max=%d

", - queue.minimum(), queue.average(), queue.maximum()); + base::StringAppendF( + output, + "Prefetch Queue Durations: min=%d, avg=%d, max=%d

", + queue.minimum(), queue.average(), queue.maximum()); #endif output->append("
"); diff --git a/chrome/browser/options_util.cc b/chrome/browser/options_util.cc index 56d0c07..5db8902 100644 --- a/chrome/browser/options_util.cc +++ b/chrome/browser/options_util.cc @@ -4,6 +4,7 @@ #include "chrome/browser/options_util.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_prefs.h" @@ -31,6 +32,12 @@ void OptionsUtil::ResetToDefaults(Profile* profile) { prefs::kCookieBehavior, prefs::kDefaultCharset, prefs::kDefaultZoomLevel, + prefs::kDeleteBrowsingHistory, + prefs::kDeleteCache, + prefs::kDeleteCookies, + prefs::kDeleteDownloadHistory, + prefs::kDeleteFormData, + prefs::kDeletePasswords, prefs::kDnsPrefetchingEnabled, #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_OPENBSD) prefs::kCertRevocationCheckingEnabled, @@ -97,6 +104,10 @@ void OptionsUtil::ResetToDefaults(Profile* profile) { // static bool OptionsUtil::ResolveMetricsReportingEnabled(bool enabled) { + // GoogleUpdateSettings touches the disk from the UI thread. MetricsService + // also calls GoogleUpdateSettings below. http://crbug/62626 + base::ThreadRestrictions::ScopedAllowIO allow_io; + GoogleUpdateSettings::SetCollectStatsConsent(enabled); bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent(); diff --git a/chrome/browser/page_info_model.cc b/chrome/browser/page_info_model.cc index 9e821d4..16a8255 100644 --- a/chrome/browser/page_info_model.cc +++ b/chrome/browser/page_info_model.cc @@ -161,12 +161,20 @@ PageInfoModel::PageInfoModel(Profile* profile, icon_id = ICON_STATE_OK; headline.clear(); description.clear(); - if (ssl.security_bits() < 0) { + if (!ssl.cert_id()) { + // Not HTTPS. + DCHECK_EQ(ssl.security_style(), SECURITY_STYLE_UNAUTHENTICATED); + icon_id = ssl.security_style() == SECURITY_STYLE_UNAUTHENTICATED ? + ICON_STATE_WARNING_MAJOR : ICON_STATE_ERROR; + description.assign(l10n_util::GetStringFUTF16( + IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, + subject_name)); + } else if (ssl.security_bits() < 0) { // Security strength is unknown. Say nothing. icon_id = ICON_STATE_ERROR; } else if (ssl.security_bits() == 0) { - icon_id = ssl.security_style() == SECURITY_STYLE_UNAUTHENTICATED ? - ICON_STATE_WARNING_MAJOR : ICON_STATE_ERROR; + DCHECK_NE(ssl.security_style(), SECURITY_STYLE_UNAUTHENTICATED); + icon_id = ICON_STATE_ERROR; description.assign(l10n_util::GetStringFUTF16( IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, subject_name)); diff --git a/chrome/browser/password_manager/password_store_default_unittest.cc b/chrome/browser/password_manager/password_store_default_unittest.cc index d657582..43bed39 100644 --- a/chrome/browser/password_manager/password_store_default_unittest.cc +++ b/chrome/browser/password_manager/password_store_default_unittest.cc @@ -16,6 +16,7 @@ #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" +#include "chrome/test/mock_notification_observer.h" #include "chrome/test/signaling_task.h" #include "chrome/test/testing_profile.h" #include "testing/gmock/include/gmock/gmock.h" @@ -44,13 +45,6 @@ class MockWebDataServiceConsumer : public WebDataServiceConsumer { const WDTypedResult*)); }; -class MockNotificationObserver : public NotificationObserver { - public: - MOCK_METHOD3(Observe, void(NotificationType, - const NotificationSource&, - const NotificationDetails&)); -}; - // This class will add and remove a mock notification observer from // the DB thread. class DBThreadObserverHelper : diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index 55d6391..8379600 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc @@ -14,6 +14,7 @@ #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" +#include "chrome/test/mock_notification_observer.h" #include "chrome/test/signaling_task.h" #include "chrome/test/testing_profile.h" #include "testing/gmock/include/gmock/gmock.h" @@ -44,13 +45,6 @@ class MockWebDataServiceConsumer : public WebDataServiceConsumer { const WDTypedResult*)); }; -class MockNotificationObserver : public NotificationObserver { - public: - MOCK_METHOD3(Observe, void(NotificationType, - const NotificationSource&, - const NotificationDetails&)); -}; - // This class will add and remove a mock notification observer from // the DB thread. class DBThreadObserverHelper diff --git a/chrome/browser/platform_util_linux.cc b/chrome/browser/platform_util_linux.cc index 7f4627c..514e438 100644 --- a/chrome/browser/platform_util_linux.cc +++ b/chrome/browser/platform_util_linux.cc @@ -14,10 +14,10 @@ namespace { -void XDGOpen(const std::string& path) { +void XDGUtil(const std::string& util, const std::string& arg) { std::vector argv; - argv.push_back("xdg-open"); - argv.push_back(path); + argv.push_back(util); + argv.push_back(arg); base::environment_vector env; // xdg-open can fall back on mailcap which eventually might plumb through @@ -41,6 +41,14 @@ void XDGOpen(const std::string& path) { ProcessWatcher::EnsureProcessGetsReaped(handle); } +void XDGOpen(const std::string& path) { + XDGUtil("xdg-open", path); +} + +void XDGEmail(const std::string& email) { + XDGUtil("xdg-email", email); +} + } // namespace namespace platform_util { @@ -61,7 +69,10 @@ void OpenItem(const FilePath& full_path) { } void OpenExternal(const GURL& url) { - XDGOpen(url.spec()); + if (url.SchemeIs("mailto")) + XDGEmail(url.spec()); + else + XDGOpen(url.spec()); } } // namespace platform_util diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index cc6408f..bd37a6f 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -60,18 +60,10 @@ static void NotifyPluginsOfActivation() { // static bool PluginService::enable_chrome_plugins_ = true; -void LoadPluginsFromDiskHook() { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI) && - !BrowserThread::CurrentlyOn(BrowserThread::IO)) << - "Can't load plugins on the IO/UI threads since it's very slow."; -} - // static void PluginService::InitGlobalInstance(Profile* profile) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - NPAPI::PluginList::Singleton()->SetPluginLoadHook(LoadPluginsFromDiskHook); - // We first group the plugins and then figure out which groups to disable. PluginUpdater::GetPluginUpdater()->DisablePluginGroupsFromPrefs(profile); diff --git a/chrome/browser/plugin_service_browsertest.cc b/chrome/browser/plugin_service_browsertest.cc new file mode 100644 index 0000000..8d9e82e --- /dev/null +++ b/chrome/browser/plugin_service_browsertest.cc @@ -0,0 +1,107 @@ +// 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/plugin_service.h" + +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "webkit/glue/plugins/plugin_list.h" + +namespace { + +// We have to mock the Client class up in order to be able to test the +// OpenChannelToPlugin function. The only really needed function of this mockup +// is SetPluginInfo, which gets called in +// PluginService::FinishOpenChannelToPlugin. +class MockPluginProcessHostClient : public PluginProcessHost::Client { + public: + MockPluginProcessHostClient() {} + virtual ~MockPluginProcessHostClient() {} + + MOCK_METHOD0(ID, int()); + MOCK_METHOD0(OffTheRecord, bool()); + MOCK_METHOD1(SetPluginInfo, void(const WebPluginInfo& info)); + MOCK_METHOD1(OnChannelOpened, void(const IPC::ChannelHandle& handle)); + MOCK_METHOD0(OnError, void()); + + private: + DISALLOW_COPY_AND_ASSIGN(MockPluginProcessHostClient); +}; + +class PluginServiceTest : public testing::Test { + public: + PluginServiceTest() + : message_loop_(MessageLoop::TYPE_IO), + ui_thread_(BrowserThread::UI, &message_loop_), + file_thread_(BrowserThread::FILE, &message_loop_), + io_thread_(BrowserThread::IO, &message_loop_) {} + + virtual ~PluginServiceTest() {} + + virtual void SetUp() { + profile_.reset(new TestingProfile()); + + PluginService::InitGlobalInstance(profile_.get()); + plugin_service_ = PluginService::GetInstance(); + ASSERT_TRUE(plugin_service_); + } + + protected: + MessageLoop message_loop_; + PluginService* plugin_service_; + + private: + BrowserThread ui_thread_; + BrowserThread file_thread_; + BrowserThread io_thread_; + scoped_ptr profile_; + + DISALLOW_COPY_AND_ASSIGN(PluginServiceTest); +}; + +// These tests need to be implemented as in process tests because on mac os the +// plugin loading mechanism checks whether plugin paths are in the bundle path +// and the test fails this check when run outside of the browser process. +IN_PROC_BROWSER_TEST_F(PluginServiceTest, StartAndFindPluginProcess) { + // Try to load the default plugin and if this is successful consecutive + // calls to FindPluginProcess should return non-zero values. + PluginProcessHost* default_plugin_process_host = + plugin_service_->FindOrStartPluginProcess( + FilePath(kDefaultPluginLibraryName)); + + EXPECT_EQ(default_plugin_process_host, + plugin_service_->FindPluginProcess(FilePath(kDefaultPluginLibraryName))); +} + +IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) { + MockPluginProcessHostClient mock_client; + EXPECT_CALL(mock_client, SetPluginInfo(testing::_)).Times(1); + plugin_service_->OpenChannelToPlugin(GURL("http://google.com/"), + "audio/mp3", + &mock_client); + message_loop_.RunAllPending(); +} + +IN_PROC_BROWSER_TEST_F(PluginServiceTest, GetFirstAllowedPluginInfo) { + // on ChromeOS the plugin policy gets loaded on the FILE thread and the + // GetFirstAllowedPluginInfo will fail if we don't allow it to finish. + message_loop_.RunAllPending(); + // We should always get a positive response no matter whether we really have + // a plugin to support that particular mime type because the Default plugin + // supports all mime types. + WebPluginInfo plugin_info; + std::string plugin_mime_type; + plugin_service_->GetFirstAllowedPluginInfo(GURL("http://google.com/"), + "application/pdf", + &plugin_info, + &plugin_mime_type); + EXPECT_EQ("application/pdf", plugin_mime_type); +} + +} // namespace diff --git a/chrome/browser/plugin_service_unittest.cc b/chrome/browser/plugin_service_unittest.cc new file mode 100644 index 0000000..4e54526 --- /dev/null +++ b/chrome/browser/plugin_service_unittest.cc @@ -0,0 +1,63 @@ +// 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/plugin_service.h" + +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/plugins/plugin_list.h" + +namespace { + +class PluginServiceTest : public testing::Test { + public: + PluginServiceTest() + : message_loop_(MessageLoop::TYPE_IO), + ui_thread_(BrowserThread::UI, &message_loop_), + file_thread_(BrowserThread::FILE, &message_loop_), + io_thread_(BrowserThread::IO, &message_loop_) {} + + virtual ~PluginServiceTest() {} + + virtual void SetUp() { + profile_.reset(new TestingProfile()); + + PluginService::InitGlobalInstance(profile_.get()); + plugin_service_ = PluginService::GetInstance(); + ASSERT_TRUE(plugin_service_); + } + + protected: + MessageLoop message_loop_; + PluginService* plugin_service_; + + private: + BrowserThread ui_thread_; + BrowserThread file_thread_; + BrowserThread io_thread_; + scoped_ptr profile_; + + DISALLOW_COPY_AND_ASSIGN(PluginServiceTest); +}; + +TEST_F(PluginServiceTest, SetGetChromePluginDataDir) { + // Check that after setting the same plugin dir we just read it is set + // correctly. + FilePath plugin_data_dir = plugin_service_->GetChromePluginDataDir(); + FilePath new_plugin_data_dir(FILE_PATH_LITERAL("/a/bogus/dir")); + plugin_service_->SetChromePluginDataDir(new_plugin_data_dir); + EXPECT_EQ(new_plugin_data_dir, plugin_service_->GetChromePluginDataDir()); + plugin_service_->SetChromePluginDataDir(plugin_data_dir); + EXPECT_EQ(plugin_data_dir, plugin_service_->GetChromePluginDataDir()); +} + +TEST_F(PluginServiceTest, GetUILocale) { + // Check for a non-empty locale string. + EXPECT_NE("", plugin_service_->GetUILocale()); +} + +} // namespace diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc index 72830cd..8336a5d 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.cc +++ b/chrome/browser/policy/configuration_policy_pref_store.cc @@ -4,6 +4,7 @@ #include "chrome/browser/policy/configuration_policy_pref_store.h" +#include "base/command_line.h" #include "base/logging.h" #include "base/path_service.h" #include "base/singleton.h" @@ -19,6 +20,7 @@ #elif defined(OS_POSIX) #include "chrome/browser/policy/config_dir_policy_provider.h" #endif +#include "chrome/browser/policy/device_management_policy_provider.h" #include "chrome/browser/policy/dummy_configuration_policy_provider.h" #include "chrome/browser/search_engines/search_terms_data.h" #include "chrome/browser/search_engines/template_url.h" @@ -29,28 +31,36 @@ namespace policy { -// Manages the lifecycle of the shared platform-specific policy providers -// for managed and recommended policy. Instantiated as a Singleton. +// Manages the lifecycle of the shared platform-specific policy providers for +// managed platform, device management and recommended policy. Instantiated as a +// Singleton. class ConfigurationPolicyProviderKeeper { public: ConfigurationPolicyProviderKeeper() - : managed_provider_(CreateManagedProvider()), + : managed_platform_provider_(CreateManagedPlatformProvider()), + device_management_provider_(CreateDeviceManagementProvider()), recommended_provider_(CreateRecommendedProvider()) {} virtual ~ConfigurationPolicyProviderKeeper() {} - ConfigurationPolicyProvider* managed_provider() const { - return managed_provider_.get(); + ConfigurationPolicyProvider* managed_platform_provider() const { + return managed_platform_provider_.get(); } - ConfigurationPolicyProvider* recommended_provider() const { + ConfigurationPolicyProvider* device_management_provider() const { + return device_management_provider_.get(); + } + +ConfigurationPolicyProvider* recommended_provider() const { return recommended_provider_.get(); } private: - scoped_ptr managed_provider_; + scoped_ptr managed_platform_provider_; + scoped_ptr device_management_provider_; scoped_ptr recommended_provider_; - static ConfigurationPolicyProvider* CreateManagedProvider(); + static ConfigurationPolicyProvider* CreateManagedPlatformProvider(); + static ConfigurationPolicyProvider* CreateDeviceManagementProvider(); static ConfigurationPolicyProvider* CreateRecommendedProvider(); DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderKeeper); @@ -58,7 +68,19 @@ class ConfigurationPolicyProviderKeeper { ConfigurationPolicyProvider* - ConfigurationPolicyProviderKeeper::CreateManagedProvider() { + ConfigurationPolicyProviderKeeper::CreateDeviceManagementProvider() { + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list = + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDeviceManagementUrl)) { + return new DeviceManagementPolicyProvider(policy_list); + } else { + return new DummyConfigurationPolicyProvider(policy_list); + } +} + +ConfigurationPolicyProvider* + ConfigurationPolicyProviderKeeper::CreateManagedPlatformProvider() { const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list = ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(); #if defined(OS_WIN) @@ -144,6 +166,28 @@ const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry prefs::kDevToolsDisabled }, { Value::TYPE_BOOLEAN, kPolicyBlockThirdPartyCookies, prefs::kBlockThirdPartyCookies}, + { Value::TYPE_INTEGER, kPolicyDefaultCookiesSetting, + prefs::kManagedDefaultCookiesSetting}, + { Value::TYPE_INTEGER, kPolicyDefaultImagesSetting, + prefs::kManagedDefaultImagesSetting}, + { Value::TYPE_INTEGER, kPolicyDefaultJavaScriptSetting, + prefs::kManagedDefaultJavaScriptSetting}, + { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting, + prefs::kManagedDefaultPluginsSetting}, + { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting, + prefs::kManagedDefaultPopupsSetting}, + { Value::TYPE_STRING, kPolicyAuthSchemes, + prefs::kAuthSchemes }, + { Value::TYPE_BOOLEAN, kPolicyDisableAuthNegotiateCnameLookup, + prefs::kDisableAuthNegotiateCnameLookup }, + { Value::TYPE_BOOLEAN, kPolicyEnableAuthNegotiatePort, + prefs::kEnableAuthNegotiatePort }, + { Value::TYPE_STRING, kPolicyAuthServerWhitelist, + prefs::kAuthServerWhitelist }, + { Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist, + prefs::kAuthNegotiateDelegateWhitelist }, + { Value::TYPE_STRING, kPolicyGSSAPILibraryName, + prefs::kGSSAPILibraryName }, #if defined(OS_CHROMEOS) { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend, @@ -177,7 +221,7 @@ const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry }; /* static */ -ConfigurationPolicyProvider::PolicyDefinitionList* +const ConfigurationPolicyProvider::PolicyDefinitionList* ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() { static ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[] = { { kPolicyHomePage, Value::TYPE_STRING, key::kHomepageLocation }, @@ -239,6 +283,28 @@ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() { key::kDeveloperToolsDisabled }, { kPolicyBlockThirdPartyCookies, Value::TYPE_BOOLEAN, key::kBlockThirdPartyCookies }, + { kPolicyDefaultCookiesSetting, Value::TYPE_INTEGER, + key::kDefaultCookiesSetting}, + { kPolicyDefaultImagesSetting, Value::TYPE_INTEGER, + key::kDefaultImagesSetting}, + { kPolicyDefaultJavaScriptSetting, Value::TYPE_INTEGER, + key::kDefaultJavaScriptSetting}, + { kPolicyDefaultPluginsSetting, Value::TYPE_INTEGER, + key::kDefaultPluginsSetting}, + { kPolicyDefaultPopupsSetting, Value::TYPE_INTEGER, + key::kDefaultPopupsSetting}, + { kPolicyAuthSchemes, Value::TYPE_STRING, key::kAuthSchemes }, + { kPolicyDisableAuthNegotiateCnameLookup, Value::TYPE_BOOLEAN, + key::kDisableAuthNegotiateCnameLookup }, + { kPolicyEnableAuthNegotiatePort, Value::TYPE_BOOLEAN, + key::kEnableAuthNegotiatePort }, + { kPolicyAuthServerWhitelist, Value::TYPE_STRING, + key::kAuthServerWhitelist }, + { kPolicyAuthNegotiateDelegateWhitelist, Value::TYPE_STRING, + key::kAuthNegotiateDelegateWhitelist }, + { kPolicyGSSAPILibraryName, Value::TYPE_STRING, + key::kGSSAPILibraryName }, + #if defined(OS_CHROMEOS) { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN, @@ -300,10 +366,19 @@ void ConfigurationPolicyPrefStore::Apply(ConfigurationPolicyType policy, // static ConfigurationPolicyPrefStore* -ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore() { +ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() { + ConfigurationPolicyProviderKeeper* keeper = + Singleton::get(); + return new ConfigurationPolicyPrefStore(keeper->managed_platform_provider()); +} + +// static +ConfigurationPolicyPrefStore* +ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore() { ConfigurationPolicyProviderKeeper* keeper = Singleton::get(); - return new ConfigurationPolicyPrefStore(keeper->managed_provider()); + return new ConfigurationPolicyPrefStore( + keeper->device_management_provider()); } // static diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h index 066952b..e4792c6 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.h +++ b/chrome/browser/policy/configuration_policy_pref_store.h @@ -6,8 +6,9 @@ #define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PREF_STORE_H_ #pragma once -#include #include +#include + #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" @@ -37,14 +38,18 @@ class ConfigurationPolicyPrefStore : public PrefStore, // ConfigurationPolicyStore methods: virtual void Apply(ConfigurationPolicyType setting, Value* value); - // Creates a ConfigurationPolicyPrefStore that reads managed policy. - static ConfigurationPolicyPrefStore* CreateManagedPolicyPrefStore(); + // Creates a ConfigurationPolicyPrefStore that reads managed platform policy. + static ConfigurationPolicyPrefStore* CreateManagedPlatformPolicyPrefStore(); + + // Creates a ConfigurationPolicyPrefStore that supplies policy from + // the device management server. + static ConfigurationPolicyPrefStore* CreateDeviceManagementPolicyPrefStore(); // Creates a ConfigurationPolicyPrefStore that reads recommended policy. static ConfigurationPolicyPrefStore* CreateRecommendedPolicyPrefStore(); // Returns the default policy definition list for Chrome. - static ConfigurationPolicyProvider::PolicyDefinitionList* + static const ConfigurationPolicyProvider::PolicyDefinitionList* GetChromePolicyDefinitionList(); // Returns the set of preference paths that can be affected by a proxy diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc index 0809c00..2595f83 100644 --- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc +++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc @@ -106,7 +106,17 @@ INSTANTIATE_TEST_CASE_P( TypeAndName(kPolicyProxyBypassList, prefs::kProxyBypassList), TypeAndName(kPolicyApplicationLocale, - prefs::kApplicationLocale))); + prefs::kApplicationLocale), + TypeAndName(kPolicyApplicationLocale, + prefs::kApplicationLocale), + TypeAndName(kPolicyAuthSchemes, + prefs::kAuthSchemes), + TypeAndName(kPolicyAuthServerWhitelist, + prefs::kAuthServerWhitelist), + TypeAndName(kPolicyAuthNegotiateDelegateWhitelist, + prefs::kAuthNegotiateDelegateWhitelist), + TypeAndName(kPolicyGSSAPILibraryName, + prefs::kGSSAPILibraryName))); // Test cases for boolean-valued policy settings. class ConfigurationPolicyPrefStoreBooleanTest @@ -161,7 +171,13 @@ INSTANTIATE_TEST_CASE_P( TypeAndName(kPolicyJavascriptEnabled, prefs::kWebKitJavascriptEnabled), TypeAndName(kPolicySavingBrowserHistoryDisabled, - prefs::kSavingBrowserHistoryDisabled))); + prefs::kSavingBrowserHistoryDisabled), + TypeAndName(kPolicySavingBrowserHistoryDisabled, + prefs::kSavingBrowserHistoryDisabled), + TypeAndName(kPolicyDisableAuthNegotiateCnameLookup, + prefs::kDisableAuthNegotiateCnameLookup), + TypeAndName(kPolicyEnableAuthNegotiatePort, + prefs::kEnableAuthNegotiatePort))); #if defined(OS_CHROMEOS) INSTANTIATE_TEST_CASE_P( diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc index 2b77db8..ce7106f 100644 --- a/chrome/browser/policy/configuration_policy_provider.cc +++ b/chrome/browser/policy/configuration_policy_provider.cc @@ -23,4 +23,19 @@ void ConfigurationPolicyProvider::NotifyStoreOfPolicyChange() { NotificationService::NoDetails()); } +void ConfigurationPolicyProvider::DecodePolicyValueTree( + DictionaryValue* policies, + ConfigurationPolicyStoreInterface* store) { + const PolicyDefinitionList* policy_list(policy_definition_list()); + for (const PolicyDefinitionList::Entry* i = policy_list->begin; + i != policy_list->end; ++i) { + Value* value; + if (policies->Get(i->name, &value) && value->IsType(i->value_type)) + store->Apply(i->policy_type, value->DeepCopy()); + } + + // TODO(mnissler): Handle preference overrides once |ConfigurationPolicyStore| + // supports it. +} + } // namespace policy diff --git a/chrome/browser/policy/configuration_policy_provider.h b/chrome/browser/policy/configuration_policy_provider.h index 7969988..e3989b9 100644 --- a/chrome/browser/policy/configuration_policy_provider.h +++ b/chrome/browser/policy/configuration_policy_provider.h @@ -52,6 +52,9 @@ class ConfigurationPolicyProvider { // soon as possible. virtual void NotifyStoreOfPolicyChange(); + // Decodes the value tree and writes the configuration to the given |store|. + void DecodePolicyValueTree(DictionaryValue* policies, + ConfigurationPolicyStoreInterface* store); protected: const PolicyDefinitionList* policy_definition_list() const { return policy_definition_list_; diff --git a/chrome/browser/policy/configuration_policy_store_interface.h b/chrome/browser/policy/configuration_policy_store_interface.h index 7bdcf74..cfb943e 100644 --- a/chrome/browser/policy/configuration_policy_store_interface.h +++ b/chrome/browser/policy/configuration_policy_store_interface.h @@ -51,8 +51,19 @@ enum ConfigurationPolicyType { kPolicySavingBrowserHistoryDisabled, kPolicyDeveloperToolsDisabled, kPolicyBlockThirdPartyCookies, + kPolicyDefaultCookiesSetting, + kPolicyDefaultImagesSetting, + kPolicyDefaultJavaScriptSetting, + kPolicyDefaultPluginsSetting, + kPolicyDefaultPopupsSetting, kPolicyExtensionInstallForceList, kPolicyChromeOsLockOnIdleSuspend, + kPolicyAuthSchemes, + kPolicyDisableAuthNegotiateCnameLookup, + kPolicyEnableAuthNegotiatePort, + kPolicyAuthServerWhitelist, + kPolicyAuthNegotiateDelegateWhitelist, + kPolicyGSSAPILibraryName, }; static const int kPolicyNoProxyServerMode = 0; diff --git a/chrome/browser/policy/device_management_backend_impl_browsertest.cc b/chrome/browser/policy/device_management_backend_impl_browsertest.cc index 43df7be..770317b 100644 --- a/chrome/browser/policy/device_management_backend_impl_browsertest.cc +++ b/chrome/browser/policy/device_management_backend_impl_browsertest.cc @@ -8,6 +8,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/policy/device_management_backend_mock.h" #include "chrome/test/in_process_browser_test.h" +#include "net/test/test_server.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_job.h" #include "testing/gtest/include/gtest/gtest.h" @@ -81,10 +82,6 @@ class DeviceManagementBackendImplIntegrationTest : public InProcessBrowserTest { } protected: - DeviceManagementBackendImplIntegrationTest() { - URLFetcher::enable_interception_for_tests(true); - } - std::string token_; }; @@ -93,7 +90,8 @@ static void QuitMessageLoop() { } IN_PROC_BROWSER_TEST_F(DeviceManagementBackendImplIntegrationTest, - RegisterAndFetchPolicy) { + CannedResponses) { + URLFetcher::enable_interception_for_tests(true); DeviceManagementBackendImpl service(kServiceUrl); { @@ -138,4 +136,51 @@ IN_PROC_BROWSER_TEST_F(DeviceManagementBackendImplIntegrationTest, } } +IN_PROC_BROWSER_TEST_F(DeviceManagementBackendImplIntegrationTest, + WithTestServer) { + net::TestServer test_server( + net::TestServer::TYPE_HTTP, + FilePath(FILE_PATH_LITERAL("chrome/test/data/policy"))); + ASSERT_TRUE(test_server.Start()); + DeviceManagementBackendImpl service( + test_server.GetURL("device_management").spec()); + + { + DeviceRegisterResponseDelegateMock delegate; + EXPECT_CALL(delegate, HandleRegisterResponse(_)) + .WillOnce(DoAll(Invoke(this, &DeviceManagementBackendImplIntegrationTest + ::CaptureToken), + InvokeWithoutArgs(QuitMessageLoop))); + em::DeviceRegisterRequest request; + service.ProcessRegisterRequest("token", "device id", request, &delegate); + MessageLoop::current()->Run(); + } + + { + em::DevicePolicyResponse expected_response; + + DevicePolicyResponseDelegateMock delegate; + EXPECT_CALL(delegate, HandlePolicyResponse(_)) + .WillOnce(InvokeWithoutArgs(QuitMessageLoop)); + em::DevicePolicyRequest request; + request.set_policy_scope("chrome"); + em::DevicePolicySettingRequest* setting_request = + request.add_setting_request(); + setting_request->set_key("policy"); + service.ProcessPolicyRequest(token_, request, &delegate); + + MessageLoop::current()->Run(); + } + + { + DeviceUnregisterResponseDelegateMock delegate; + EXPECT_CALL(delegate, HandleUnregisterResponse(_)) + .WillOnce(InvokeWithoutArgs(QuitMessageLoop)); + em::DeviceUnregisterRequest request; + service.ProcessUnregisterRequest(token_, request, &delegate); + + MessageLoop::current()->Run(); + } +} + } // namespace policy diff --git a/chrome/browser/policy/device_management_policy_cache.cc b/chrome/browser/policy/device_management_policy_cache.cc index b70ced4..d9ed7a6 100644 --- a/chrome/browser/policy/device_management_policy_cache.cc +++ b/chrome/browser/policy/device_management_policy_cache.cc @@ -9,19 +9,22 @@ #include "base/file_util.h" #include "base/logging.h" +#include "base/task.h" #include "base/values.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/policy/proto/device_management_local.pb.h" using google::protobuf::RepeatedField; using google::protobuf::RepeatedPtrField; namespace policy { -// A task implementation that saves policy information to a file. +// Saves policy information to a file. class PersistPolicyTask : public Task { public: PersistPolicyTask(const FilePath& path, - const em::DevicePolicyResponse* policy); + const em::DevicePolicyResponse* policy, + const base::Time& timestamp); private: // Task override. @@ -29,17 +32,23 @@ class PersistPolicyTask : public Task { const FilePath path_; scoped_ptr policy_; + const base::Time timestamp_; }; PersistPolicyTask::PersistPolicyTask(const FilePath& path, - const em::DevicePolicyResponse* policy) + const em::DevicePolicyResponse* policy, + const base::Time& timestamp) : path_(path), - policy_(policy) { + policy_(policy), + timestamp_(timestamp) { } void PersistPolicyTask::Run() { std::string data; - if (!policy_->SerializeToString(&data)) { + em::CachedDevicePolicyResponse cached_policy; + cached_policy.mutable_policy()->CopyFrom(*policy_); + cached_policy.set_timestamp(timestamp_.ToInternalValue()); + if (!cached_policy.SerializeToString(&data)) { LOG(WARNING) << "Failed to serialize policy data"; return; } @@ -70,29 +79,41 @@ void DeviceManagementPolicyCache::LoadPolicyFromFile() { return; } - em::DevicePolicyResponse policy; - if (!policy.ParseFromArray(data.c_str(), data.size())) { + em::CachedDevicePolicyResponse cached_policy; + if (!cached_policy.ParseFromArray(data.c_str(), data.size())) { LOG(WARNING) << "Failed to parse policy data read from " << backing_file_path_.value(); return; } + // Reject files that claim to be from the future. + base::Time timestamp = base::Time::FromInternalValue( + cached_policy.timestamp()); + if (timestamp > base::Time::NowFromSystemTime()) { + LOG(WARNING) << "Rejected policy data from " << backing_file_path_.value() + << ", file is from the future."; + return; + } + // Decode and swap in the new policy information. - scoped_ptr value(DecodePolicy(policy)); + scoped_ptr value(DecodePolicy(cached_policy.policy())); { AutoLock lock(lock_); if (!fresh_policy_) policy_.reset(value.release()); + last_policy_refresh_time_ = timestamp; } } void DeviceManagementPolicyCache::SetPolicy( const em::DevicePolicyResponse& policy) { DictionaryValue* value = DeviceManagementPolicyCache::DecodePolicy(policy); + base::Time now(base::Time::Now()); { AutoLock lock(lock_); policy_.reset(value); fresh_policy_ = true; + last_policy_refresh_time_ = now; } em::DevicePolicyResponse* policy_copy = new em::DevicePolicyResponse; @@ -100,7 +121,8 @@ void DeviceManagementPolicyCache::SetPolicy( BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - new PersistPolicyTask(backing_file_path_, policy_copy)); + new PersistPolicyTask(backing_file_path_, policy_copy, + base::Time::NowFromSystemTime())); } DictionaryValue* DeviceManagementPolicyCache::GetPolicy() { @@ -156,7 +178,7 @@ Value* DeviceManagementPolicyCache::DecodeValue(const em::GenericValue& value) { list->Append(Value::CreateBooleanValue(*i)); return list; } - case em::GenericValue::VALUE_TYPE_INT64_ARRAY_: { + case em::GenericValue::VALUE_TYPE_INT64_ARRAY: { ListValue* list = new ListValue; RepeatedField::const_iterator i; for (i = value.int64_array().begin(); diff --git a/chrome/browser/policy/device_management_policy_cache.h b/chrome/browser/policy/device_management_policy_cache.h index a50402f..5136059 100644 --- a/chrome/browser/policy/device_management_policy_cache.h +++ b/chrome/browser/policy/device_management_policy_cache.h @@ -10,6 +10,7 @@ #include "base/lock.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "base/time.h" #include "chrome/browser/policy/proto/device_management_backend.pb.h" class DictionaryValue; @@ -39,6 +40,11 @@ class DeviceManagementPolicyCache { // to the caller. DictionaryValue* GetPolicy(); + // Returns the time as which the policy was last fetched. + base::Time last_policy_refresh_time() const { + return last_policy_refresh_time_; + } + private: friend class DeviceManagementPolicyCacheDecodeTest; FRIEND_TEST_ALL_PREFIXES(DeviceManagementPolicyCacheDecodeTest, DecodePolicy); @@ -69,6 +75,9 @@ class DeviceManagementPolicyCache { // Tracks whether the store received a SetPolicy() call, which overrides any // information loaded from the file. bool fresh_policy_; + + // The time at which the policy was last refreshed. + base::Time last_policy_refresh_time_; }; } // namespace policy diff --git a/chrome/browser/policy/device_management_policy_cache_unittest.cc b/chrome/browser/policy/device_management_policy_cache_unittest.cc index 3f9ba42..6654d38 100644 --- a/chrome/browser/policy/device_management_policy_cache_unittest.cc +++ b/chrome/browser/policy/device_management_policy_cache_unittest.cc @@ -5,12 +5,14 @@ #include "chrome/browser/policy/device_management_policy_cache.h" #include +#include #include "base/file_util.h" #include "base/message_loop.h" #include "base/scoped_temp_dir.h" #include "base/values.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/policy/proto/device_management_local.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace policy { @@ -50,11 +52,15 @@ class DeviceManagementPolicyCacheTest loop_.RunAllPending(); } - void WritePolicy(const em::DevicePolicyResponse& policy) { + void WritePolicy(const em::DevicePolicyResponse& policy, + const base::Time& timestamp) { std::string data; - EXPECT_TRUE(policy.SerializeToString(&data)); - EXPECT_EQ(static_cast(data.size()), - file_util::WriteFile(test_file(), data.c_str(), data.size())); + em::CachedDevicePolicyResponse cached_policy; + cached_policy.mutable_policy()->CopyFrom(policy); + cached_policy.set_timestamp(timestamp.ToInternalValue()); + EXPECT_TRUE(cached_policy.SerializeToString(&data)); + int size = static_cast(data.size()); + EXPECT_EQ(size, file_util::WriteFile(test_file(), data.c_str(), size)); } FilePath test_file() { @@ -75,6 +81,7 @@ TEST_F(DeviceManagementPolicyCacheTest, Empty) { DictionaryValue empty; scoped_ptr policy(cache.GetPolicy()); EXPECT_TRUE(empty.Equals(policy.get())); + EXPECT_EQ(base::Time(), cache.last_policy_refresh_time()); } TEST_F(DeviceManagementPolicyCacheTest, LoadNoFile) { @@ -83,21 +90,37 @@ TEST_F(DeviceManagementPolicyCacheTest, LoadNoFile) { DictionaryValue empty; scoped_ptr policy(cache.GetPolicy()); EXPECT_TRUE(empty.Equals(policy.get())); + EXPECT_EQ(base::Time(), cache.last_policy_refresh_time()); +} + +TEST_F(DeviceManagementPolicyCacheTest, RejectFuture) { + em::DevicePolicyResponse policy_response; + WritePolicy(policy_response, base::Time::NowFromSystemTime() + + base::TimeDelta::FromMinutes(5)); + DeviceManagementPolicyCache cache(test_file()); + cache.LoadPolicyFromFile(); + DictionaryValue empty; + scoped_ptr policy(cache.GetPolicy()); + EXPECT_TRUE(empty.Equals(policy.get())); + EXPECT_EQ(base::Time(), cache.last_policy_refresh_time()); } TEST_F(DeviceManagementPolicyCacheTest, LoadWithFile) { - WritePolicy(em::DevicePolicyResponse()); + em::DevicePolicyResponse policy_response; + WritePolicy(policy_response, base::Time::NowFromSystemTime()); DeviceManagementPolicyCache cache(test_file()); cache.LoadPolicyFromFile(); DictionaryValue empty; scoped_ptr policy(cache.GetPolicy()); EXPECT_TRUE(empty.Equals(policy.get())); + EXPECT_NE(base::Time(), cache.last_policy_refresh_time()); + EXPECT_GE(base::Time::Now(), cache.last_policy_refresh_time()); } TEST_F(DeviceManagementPolicyCacheTest, LoadWithData) { em::DevicePolicyResponse policy; AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); - WritePolicy(policy); + WritePolicy(policy, base::Time::NowFromSystemTime()); DeviceManagementPolicyCache cache(test_file()); cache.LoadPolicyFromFile(); DictionaryValue expected; @@ -160,7 +183,7 @@ TEST_F(DeviceManagementPolicyCacheTest, PersistPolicy) { TEST_F(DeviceManagementPolicyCacheTest, FreshPolicyOverride) { em::DevicePolicyResponse policy; AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); - WritePolicy(policy); + WritePolicy(policy, base::Time::NowFromSystemTime()); DeviceManagementPolicyCache cache(test_file()); em::DevicePolicyResponse updated_policy; @@ -252,7 +275,7 @@ TEST_F(DeviceManagementPolicyCacheDecodeTest, BoolArray) { } TEST_F(DeviceManagementPolicyCacheDecodeTest, Int64Array) { - value_.set_value_type(em::GenericValue::VALUE_TYPE_INT64_ARRAY_); + value_.set_value_type(em::GenericValue::VALUE_TYPE_INT64_ARRAY); value_.add_int64_array(42); value_.add_int64_array(17); ListValue* list = new ListValue; diff --git a/chrome/browser/policy/device_management_policy_provider.cc b/chrome/browser/policy/device_management_policy_provider.cc new file mode 100644 index 0000000..babc5a4 --- /dev/null +++ b/chrome/browser/policy/device_management_policy_provider.cc @@ -0,0 +1,190 @@ +// 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/policy/device_management_policy_provider.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/task.h" +#include "base/time.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/policy/device_management_backend.h" +#include "chrome/browser/policy/device_management_backend_impl.h" +#include "chrome/browser/policy/device_management_policy_cache.h" +#include "chrome/browser/policy/device_token_fetcher.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" + +namespace { + +const char kChromePolicyScope[] = "cros/device"; +const char kChromeDevicePolicySettingKey[] = "chrome-policy"; +const int64 kPolicyRefreshRateInMinutes = 3 * 60; // 3 hours + +} // namespace + +namespace policy { + +// Ensures that the portion of the policy provider implementation that requires +// the IOThread is deferred until the IOThread is fully initialized. The policy +// provider posts this task on the UI thread during its constructor, thereby +// guaranteeing that the code won't get executed until after the UI and IO +// threads are fully constructed. +class DeviceManagementPolicyProvider::InitializeAfterIOThreadExistsTask + : public Task { + public: + explicit InitializeAfterIOThreadExistsTask( + base::WeakPtr provider) + : provider_(provider) { + } + + // Task implementation: + virtual void Run() { + DeviceManagementPolicyProvider* provider = provider_.get(); + if (provider) + provider->InitializeAfterIOThreadExists(); + } + + private: + base::WeakPtr provider_; +}; + +DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, + DeviceManagementBackend* backend, + const FilePath& storage_dir) + : ConfigurationPolicyProvider(policy_list), + backend_(backend), + storage_dir_(GetOrCreateDeviceManagementDir(storage_dir)), + policy_request_pending_(false) { + Initialize(); +} + +DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list) + : ConfigurationPolicyProvider(policy_list), + policy_request_pending_(false) { + FilePath user_dir; + if (!PathService::Get(chrome::DIR_USER_DATA, &user_dir)) + NOTREACHED(); + storage_dir_ = GetOrCreateDeviceManagementDir(user_dir); + Initialize(); +} + +DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() {} + +bool DeviceManagementPolicyProvider::Provide( + ConfigurationPolicyStoreInterface* policy_store) { + scoped_ptr policies(cache_->GetPolicy()); + DecodePolicyValueTree(policies.get(), policy_store); + return true; +} + +void DeviceManagementPolicyProvider::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if ((type == NotificationType::DEVICE_TOKEN_AVAILABLE) && + (token_fetcher_.get() == Source(source).ptr())) { + if (!policy_request_pending_) { + if (IsPolicyStale()) + SendPolicyRequest(); + } + } else { + NOTREACHED(); + } +} + +void DeviceManagementPolicyProvider::HandlePolicyResponse( + const em::DevicePolicyResponse& response) { + cache_->SetPolicy(response); + NotifyStoreOfPolicyChange(); + policy_request_pending_ = false; +} + +void DeviceManagementPolicyProvider::OnError( + DeviceManagementBackend::ErrorCode code) { + LOG(WARNING) << "could not provide policy from the device manager (error = " + << code << ")"; + policy_request_pending_ = false; + // TODO(danno): do something sensible in the error case, perhaps retry later? +} + +DeviceManagementBackend* DeviceManagementPolicyProvider::GetBackend() { + if (!backend_.get()) { + backend_.reset(new DeviceManagementBackendImpl( + GetDeviceManagementURL())); + } + return backend_.get(); +} + +void DeviceManagementPolicyProvider::Initialize() { + registrar_.Add(this, + NotificationType::DEVICE_TOKEN_AVAILABLE, + NotificationService::AllSources()); + + const FilePath policy_path = storage_dir_.Append( + FILE_PATH_LITERAL("Policy")); + cache_.reset(new DeviceManagementPolicyCache(policy_path)); + cache_->LoadPolicyFromFile(); + + // Defer initialization that requires the IOThread until after the IOThread + // has been initialized. + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + new InitializeAfterIOThreadExistsTask(AsWeakPtr())); +} + +void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { + const FilePath token_path = storage_dir_.Append( + FILE_PATH_LITERAL("Token")); + token_fetcher_ = new DeviceTokenFetcher(GetBackend(), token_path); + token_fetcher_->StartFetching(); +} + +void DeviceManagementPolicyProvider::SendPolicyRequest() { + if (!policy_request_pending_) { + em::DevicePolicyRequest policy_request; + policy_request.set_policy_scope(kChromePolicyScope); + em::DevicePolicySettingRequest* setting = + policy_request.add_setting_request(); + setting->set_key(kChromeDevicePolicySettingKey); + GetBackend()->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), + policy_request, + this); + policy_request_pending_ = true; + } +} + +bool DeviceManagementPolicyProvider::IsPolicyStale() const { + base::Time now(base::Time::NowFromSystemTime()); + base::Time last_policy_refresh_time = + cache_->last_policy_refresh_time(); + base::Time policy_expiration_time = + last_policy_refresh_time + base::TimeDelta::FromMinutes( + kPolicyRefreshRateInMinutes); + return (now > policy_expiration_time); +} + +// static +std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() { + return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kDeviceManagementUrl); +} + +// static +FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir( + const FilePath& user_data_dir) { + const FilePath device_management_dir = user_data_dir.Append( + FILE_PATH_LITERAL("Device Management")); + if (!file_util::DirectoryExists(device_management_dir)) { + if (!file_util::CreateDirectory(device_management_dir)) + NOTREACHED(); + } + return device_management_dir; +} + +} // namespace policy diff --git a/chrome/browser/policy/device_management_policy_provider.h b/chrome/browser/policy/device_management_policy_provider.h new file mode 100644 index 0000000..73a1257 --- /dev/null +++ b/chrome/browser/policy/device_management_policy_provider.h @@ -0,0 +1,116 @@ +// 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_POLICY_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_ +#define CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_ +#pragma once + +#include + +#include "base/file_path.h" +#include "base/scoped_ptr.h" +#include "base/weak_ptr.h" +#include "chrome/browser/policy/configuration_policy_provider.h" +#include "chrome/browser/policy/device_management_backend.h" +#include "chrome/common/notification_details.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_source.h" + +namespace policy { + +class DeviceManagementBackend; +class DeviceManagementPolicyCache; +class DeviceTokenFetcher; + +// Provides policy fetched from the device management server. With the exception +// of the Provide method, which can be called on the FILE thread, all public +// methods must be called on the UI thread. +class DeviceManagementPolicyProvider + : public ConfigurationPolicyProvider, + public NotificationObserver, + public DeviceManagementBackend::DevicePolicyResponseDelegate, + public base::SupportsWeakPtr { + public: + explicit DeviceManagementPolicyProvider( + const PolicyDefinitionList* policy_list); + virtual ~DeviceManagementPolicyProvider(); + + // ConfigurationPolicyProvider implementation: + virtual bool Provide(ConfigurationPolicyStoreInterface* store); + + // NotificationObserver implementation: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // DevicePolicyResponseDelegate implementation: + virtual void HandlePolicyResponse( + const em::DevicePolicyResponse& response); + virtual void OnError(DeviceManagementBackend::ErrorCode code); + + // True if a policy request has been sent to the device management backend + // server and no response or error has yet been received. + bool IsPolicyRequestPending() const { return policy_request_pending_; } + + protected: + friend class DeviceManagementPolicyProviderTest; + + // Called only by unit tests, this constructor allows the caller to specify in + // |backend| the device management backend to which policy requests are + // sent. The provider takes over ownership of |backend|. The directory + // specified in |storage_dir| is used to store the device token and persisted + // policy, rather than the user's data directory. + DeviceManagementPolicyProvider( + const PolicyDefinitionList* policy_list, + DeviceManagementBackend* backend, + const FilePath& storage_dir); + + private: + class InitializeAfterIOThreadExistsTask; + + // Returns the device management backend to use for backend requests, lazily + // creating a new one if one doesn't already exist. + DeviceManagementBackend* GetBackend(); + + // Called by constructors to perform shared initialization. Initialization + // requiring the IOThread must not be performed directly in this method, + // rather must be deferred until the IOThread is fully initialized. This is + // the case in InitializeAfterIOThreadExists. + void Initialize(); + + // Called by a deferred task posted to the UI thread to complete the portion + // of initialization that requires the IOThread. + void InitializeAfterIOThreadExists(); + + // Sends a request to the device manager backend to fetch policy if one isn't + // already outstanding. + void SendPolicyRequest(); + + // True if policy must be re-fetched because the cached policy is too old or + // its time stamp is invalid. + bool IsPolicyStale() const; + + // Provides the URL at which requests are sent to from the device management + // backend. + static std::string GetDeviceManagementURL(); + + // Returns the path to the sub-directory in the user data directory + // in which device management persistent state is stored. + static FilePath GetOrCreateDeviceManagementDir( + const FilePath& user_data_dir); + + scoped_ptr backend_; + scoped_ptr cache_; + scoped_refptr token_fetcher_; + NotificationRegistrar registrar_; + FilePath storage_dir_; + bool policy_request_pending_; + + DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyProvider); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_ diff --git a/chrome/browser/policy/device_management_policy_provider_unittest.cc b/chrome/browser/policy/device_management_policy_provider_unittest.cc new file mode 100644 index 0000000..903db44 --- /dev/null +++ b/chrome/browser/policy/device_management_policy_provider_unittest.cc @@ -0,0 +1,147 @@ +// 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 "base/message_loop.h" +#include "base/scoped_temp_dir.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/net/gaia/token_service.h" +#include "chrome/browser/policy/configuration_policy_pref_store.h" +#include "chrome/browser/policy/device_management_policy_provider.h" +#include "chrome/browser/policy/mock_configuration_policy_store.h" +#include "chrome/browser/policy/mock_device_management_backend.h" +#include "chrome/common/net/gaia/gaia_constants.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/policy_constants.h" +#include "chrome/test/device_management_test_util.h" +#include "chrome/test/mock_notification_observer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +using ::testing::_; +using ::testing::Mock; + +class DeviceManagementPolicyProviderTest : public testing::Test { + public: + DeviceManagementPolicyProviderTest() + : ui_thread_(BrowserThread::UI, &loop_), + file_thread_(BrowserThread::FILE, &loop_) {} + + virtual ~DeviceManagementPolicyProviderTest() {} + + virtual void SetUp() { + EXPECT_TRUE(storage_dir_.CreateUniqueTempDir()); + CreateNewBackend(); + CreateNewProvider(); + } + + void CreateNewBackend() { + backend_ = new MockDeviceManagementBackend; + backend_->AddBooleanPolicy(key::kDisableSpdy, true); + } + + void CreateNewProvider() { + provider_.reset(new DeviceManagementPolicyProvider( + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), + backend_, + storage_dir_.path())); + loop_.RunAllPending(); + } + + void SimulateSuccessfulLoginAndRunPending() { + loop_.RunAllPending(); + SimulateSuccessfulLogin(); + loop_.RunAllPending(); + } + + void SimulateSuccessfulInitialPolicyFetch() { + MockConfigurationPolicyStore store; + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); + EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(1); + provider_->Provide(&store); + ASSERT_EQ(1U, store.policy_map().size()); + Mock::VerifyAndClearExpectations(backend_); + Mock::VerifyAndClearExpectations(&store); + } + + virtual void TearDown() { + loop_.RunAllPending(); + } + + protected: + MockDeviceManagementBackend* backend_; // weak + scoped_ptr provider_; + + private: + MessageLoop loop_; + BrowserThread ui_thread_; + BrowserThread file_thread_; + ScopedTempDir storage_dir_; + + DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyProviderTest); +}; + +// If there's no login and no previously-fetched policy, the provider should +// provide an empty policy. +TEST_F(DeviceManagementPolicyProviderTest, InitialProvideNoLogin) { + MockConfigurationPolicyStore store; + backend_->AllShouldSucceed(); + EXPECT_CALL(store, Apply(_, _)).Times(0); + provider_->Provide(&store); + EXPECT_TRUE(store.policy_map().empty()); +} + +// If the login is successful and there's no previously-fetched policy, the +// policy should be fetched from the server and should be available the first +// time the Provide method is called. +TEST_F(DeviceManagementPolicyProviderTest, InitialProvideWithLogin) { + SimulateSuccessfulInitialPolicyFetch(); +} + +// If the login succeeds but the device management backend is unreachable, +// there should be no policy provided if there's no previously-fetched policy, +TEST_F(DeviceManagementPolicyProviderTest, EmptyProvideWithFailedBackend) { + MockConfigurationPolicyStore store; + backend_->AllShouldFail(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _)).Times(0); + SimulateSuccessfulLoginAndRunPending(); + EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(0); + provider_->Provide(&store); + EXPECT_TRUE(store.policy_map().empty()); +} + +// If a policy has been fetched previously, if should be available even before +// the login succeeds or the device management backend is available. +TEST_F(DeviceManagementPolicyProviderTest, SecondProvide) { + // Pre-fetch and persist a policy + SimulateSuccessfulInitialPolicyFetch(); + + // Simulate a app relaunch by constructing a new provider. Policy should be + // immediately provided and no refresh should be triggered. + CreateNewBackend(); + EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _)).Times(0); + CreateNewProvider(); + MockConfigurationPolicyStore store; + EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(1); + provider_->Provide(&store); +} + +// When policy is successfully fetched from the device management server, it +// should force a policy refresh. +TEST_F(DeviceManagementPolicyProviderTest, FetchTriggersRefresh) { + MockNotificationObserver observer; + NotificationRegistrar registrar; + registrar.Add(&observer, + NotificationType::POLICY_CHANGED, + NotificationService::AllSources()); + EXPECT_CALL(observer, + Observe(_, _, _)).Times(1); + SimulateSuccessfulInitialPolicyFetch(); +} + +} diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc index 9362747..982d86f 100644 --- a/chrome/browser/policy/device_token_fetcher.cc +++ b/chrome/browser/policy/device_token_fetcher.cc @@ -7,8 +7,9 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/singleton.h" +#include "chrome/browser/guid.h" #include "chrome/browser/net/gaia/token_service.h" -#include "chrome/browser/policy/mock_device_management_backend.h" +#include "chrome/browser/policy/proto/device_management_local.pb.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/notification_details.h" @@ -16,48 +17,39 @@ #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" -namespace { - -static const char kPlaceholderDeviceID[] = "placeholder_device_id"; - -} // namespace - namespace policy { -bool UserDirDeviceTokenPathProvider::GetPath(FilePath* path) const { - FilePath dir_path; - if ( PathService::Get(chrome::DIR_USER_DATA, &dir_path)) - return false; - *path = dir_path.Append(FILE_PATH_LITERAL("DeviceManagementToken")); - return true; -} +namespace em = enterprise_management; DeviceTokenFetcher::DeviceTokenFetcher( DeviceManagementBackend* backend, - StoredDeviceTokenPathProvider* path_provider) - : backend_(backend), - path_provider_(path_provider), - state_(kStateLoadDeviceTokenFromDisk), + const FilePath& token_path) + : token_path_(token_path), + backend_(backend), + state_(kStateNotStarted), device_token_load_complete_event_(true, false) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // The token fetcher gets initialized AuthTokens for the device management + // server are available. Install a notification observer to ensure that the + // device management token gets fetched after the AuthTokens are available. + registrar_.Add(this, + NotificationType::TOKEN_AVAILABLE, + NotificationService::AllSources()); } void DeviceTokenFetcher::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { - DCHECK(CalledOnValidThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (type == NotificationType::TOKEN_AVAILABLE) { const Source token_service(source); const TokenService::TokenAvailableDetails* token_details = Details(details).ptr(); - if (token_details->service() == GaiaConstants::kDeviceManagementService && - state_ < kStateHasAuthToken) { - DCHECK_EQ(kStateFetchingAuthToken, state_); - SetState(kStateHasAuthToken); - em::DeviceRegisterRequest register_request; - backend_->ProcessRegisterRequest(token_details->token(), - GetDeviceID(), - register_request, - this); + if (token_details->service() == GaiaConstants::kDeviceManagementService) { + if (!HasAuthToken()) { + auth_token_ = token_details->token(); + SendServerRequestIfPossible(); + } } } else { NOTREACHED(); @@ -66,19 +58,17 @@ void DeviceTokenFetcher::Observe(NotificationType type, void DeviceTokenFetcher::HandleRegisterResponse( const em::DeviceRegisterResponse& response) { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(kStateHasAuthToken, state_); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_EQ(kStateRequestingDeviceTokenFromServer, state_); if (response.has_device_management_token()) { device_token_ = response.device_management_token(); - FilePath device_token_path; - if (path_provider_->GetPath(&device_token_path)) { - BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, - NewRunnableFunction(&WriteDeviceTokenToDisk, - device_token_path, - device_token_)); - } + BrowserThread::PostTask( + BrowserThread::FILE, + FROM_HERE, + NewRunnableFunction(&WriteDeviceTokenToDisk, + token_path_, + device_token_, + device_id_)); SetState(kStateHasDeviceToken); } else { NOTREACHED(); @@ -87,50 +77,102 @@ void DeviceTokenFetcher::HandleRegisterResponse( } void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) { - DCHECK(CalledOnValidThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // For privacy reasons, delete all identifying data when this device is not + // managed. + if (code == DeviceManagementBackend::kErrorServiceManagementNotSupported) { + device_token_ = std::string(); + device_id_ = std::string(); + file_util::Delete(token_path_, false); + } SetState(kStateFailure); } void DeviceTokenFetcher::StartFetching() { - DCHECK(CalledOnValidThread()); - if (state_ < kStateHasDeviceToken) { - FilePath device_token_path; - FetcherState new_state = kStateFailure; - if (path_provider_->GetPath(&device_token_path)) { - if (file_util::PathExists(device_token_path)) { - std::string device_token; - if (file_util::ReadFileToString(device_token_path, &device_token_)) { - new_state = kStateHasDeviceToken; - } - } - if (new_state != kStateHasDeviceToken) { - new_state = kStateFetchingAuthToken; - // The policy provider gets initialized with the PrefService and Profile - // before ServiceTokens are available. Install a notification observer - // to ensure that the device management token gets fetched after the - // AuthTokens are available if it's needed. - registrar_.Add(this, - NotificationType::TOKEN_AVAILABLE, - NotificationService::AllSources()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (state_ == kStateNotStarted) { + SetState(kStateLoadDeviceTokenFromDisk); + // The file calls for loading the persisted token must be deferred to the + // FILE thread. + BrowserThread::PostTask( + BrowserThread::FILE, + FROM_HERE, + NewRunnableMethod(this, + &DeviceTokenFetcher::AttemptTokenLoadFromDisk)); + } +} + +void DeviceTokenFetcher::AttemptTokenLoadFromDisk() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + if (file_util::PathExists(token_path_)) { + std::string data; + em::DeviceCredentials device_credentials; + if (file_util::ReadFileToString(token_path_, &data) && + device_credentials.ParseFromArray(data.c_str(), data.size())) { + device_token_ = device_credentials.device_token(); + device_id_ = device_credentials.device_id(); + if (!device_token_.empty() && !device_id_.empty()) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + NewRunnableMethod(this, + &DeviceTokenFetcher::SetState, + kStateHasDeviceToken)); + return; } } - SetState(new_state); + } + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + NewRunnableMethod(this, + &DeviceTokenFetcher::MakeReadyToRequestDeviceToken)); +} + +void DeviceTokenFetcher::MakeReadyToRequestDeviceToken() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + SetState(kStateReadyToRequestDeviceTokenFromServer); + SendServerRequestIfPossible(); +} + +void DeviceTokenFetcher::SendServerRequestIfPossible() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (state_ == kStateReadyToRequestDeviceTokenFromServer + && HasAuthToken()) { + em::DeviceRegisterRequest register_request; + SetState(kStateRequestingDeviceTokenFromServer); + backend_->ProcessRegisterRequest(auth_token_, + GetDeviceID(), + register_request, + this); } } bool DeviceTokenFetcher::IsTokenPending() { - DCHECK(CalledOnValidThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return !device_token_load_complete_event_.IsSignaled(); } std::string DeviceTokenFetcher::GetDeviceToken() { - DCHECK(CalledOnValidThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); device_token_load_complete_event_.Wait(); return device_token_; } +std::string DeviceTokenFetcher::GetDeviceID() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // As long as access to this is only allowed from the UI thread, no explicit + // locking is necessary to prevent the ID from being generated twice. + if (device_id_.empty()) + device_id_ = GenerateNewDeviceID(); + return device_id_; +} + void DeviceTokenFetcher::SetState(FetcherState state) { - DCHECK(CalledOnValidThread()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (state_ == state) + return; state_ = state; if (state == kStateFailure) { device_token_load_complete_event_.Signal(); @@ -143,23 +185,33 @@ void DeviceTokenFetcher::SetState(FetcherState state) { } } +void DeviceTokenFetcher::GetDeviceTokenPath(FilePath* token_path) const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + *token_path = token_path_; +} + bool DeviceTokenFetcher::IsTokenValid() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return state_ == kStateHasDeviceToken; } // static void DeviceTokenFetcher::WriteDeviceTokenToDisk( const FilePath& path, - const std::string& device_token) { - file_util::WriteFile(path, - device_token.c_str(), - device_token.length()); + const std::string& device_token, + const std::string& device_id) { + em::DeviceCredentials device_credentials; + device_credentials.set_device_token(device_token); + device_credentials.set_device_id(device_id); + std::string data; + bool no_error = device_credentials.SerializeToString(&data); + DCHECK(no_error); + file_util::WriteFile(path, data.c_str(), data.length()); } // static -std::string DeviceTokenFetcher::GetDeviceID() { - // TODO(danno): fetch a real device_id - return kPlaceholderDeviceID; +std::string DeviceTokenFetcher::GenerateNewDeviceID() { + return guid::GenerateGUID(); } -} +} // namespace policy diff --git a/chrome/browser/policy/device_token_fetcher.h b/chrome/browser/policy/device_token_fetcher.h index f5a0770..066e300 100644 --- a/chrome/browser/policy/device_token_fetcher.h +++ b/chrome/browser/policy/device_token_fetcher.h @@ -9,60 +9,33 @@ #include #include "base/file_path.h" -#include "base/non_thread_safe.h" +#include "base/ref_counted.h" #include "base/waitable_event.h" +#include "chrome/browser/policy/device_management_backend.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" -#include "chrome/browser/policy/device_management_backend.h" namespace policy { namespace em = enterprise_management; -// Abstracts how the path is determined where the DeviceTokenFetcher stores the -// device token once it has been returned from the server. Tests provide a mock -// implementation to the DeviceTokenFetcher that doesn't write to DIR_USER_DATA. -class StoredDeviceTokenPathProvider { - public: - virtual ~StoredDeviceTokenPathProvider() {} - - // Sets |path| to contain the path at which to use to store the device - // management token file. Returns true if successful, otherwise false. - virtual bool GetPath(FilePath* path) const = 0; - protected: - StoredDeviceTokenPathProvider() {} - private: - DISALLOW_COPY_AND_ASSIGN(StoredDeviceTokenPathProvider); -}; - -// Provides a path to the device token that's inside DIR_USER_DATA. -class UserDirDeviceTokenPathProvider : public StoredDeviceTokenPathProvider { - public: - UserDirDeviceTokenPathProvider() {} - virtual ~UserDirDeviceTokenPathProvider() {} - virtual bool GetPath(FilePath* path) const; - private: - DISALLOW_COPY_AND_ASSIGN(UserDirDeviceTokenPathProvider); -}; - // Fetches the device token that can be used for policy requests with the device // management server, either from disk if it already has been successfully // requested, otherwise from the device management server. An instance of the // fetcher is shared as a singleton by all users of the device management token // to ensure they all get the same token. class DeviceTokenFetcher - : public NonThreadSafe, - public NotificationObserver, - public DeviceManagementBackend::DeviceRegisterResponseDelegate { + : public NotificationObserver, + public DeviceManagementBackend::DeviceRegisterResponseDelegate, + public base::RefCountedThreadSafe { public: - // Requests to the device management server are sent through |backend|. The - // DeviceTokenFetcher assumes ownership of |backend|, which is passed in - // explicitly to simplify mocking of the backend for unit testing. The - // fetcher uses |path_provider| to determine the directory in which the device - // token is stored once it's retrieved from the server. The fetcher assumes - // ownership of |path_provider|. + // Requests to the device management server are sent through |backend|, which + // is passed in explicitly to simplify mocking of the backend for unit + // testing. The fetcher uses the directory in |token_dir| in which to store + // the device token once it's retrieved from the server. Should only be called + // by unit tests. DeviceTokenFetcher(DeviceManagementBackend* backend, - StoredDeviceTokenPathProvider* path_provider); + const FilePath& token_path); virtual ~DeviceTokenFetcher() {} // NotificationObserver method overrides: @@ -76,7 +49,7 @@ class DeviceTokenFetcher virtual void OnError(DeviceManagementBackend::ErrorCode code); // Called by subscribers of the device management token to indicate that they - // will need the token in the future. + // will need the token in the future. Must be called on the UI thread. void StartFetching(); // Returns true if there is a pending token request to the device management @@ -88,16 +61,26 @@ class DeviceTokenFetcher // case that the token could not be fetched, an empty string is returned. std::string GetDeviceToken(); + // Returns the device ID for this device. If no such ID has been set yet, a + // new ID is generated and returned. + std::string GetDeviceID(); + + // True if the fetcher has a valid AuthToken for the device management server. + bool HasAuthToken() const { return !auth_token_.empty(); } + // True if the device token has been fetched and is valid. bool IsTokenValid() const; private: + friend class DeviceTokenFetcherTest; + // The different states that the fetcher can be in during the process of // getting the device token. enum FetcherState { + kStateNotStarted, kStateLoadDeviceTokenFromDisk, - kStateFetchingAuthToken, - kStateHasAuthToken, + kStateReadyToRequestDeviceTokenFromServer, + kStateRequestingDeviceTokenFromServer, kStateHasDeviceToken, kStateFailure }; @@ -107,19 +90,45 @@ class DeviceTokenFetcher // are unblocked. void SetState(FetcherState state); + // Returns the full path to the file that persists the device manager token. + void GetDeviceTokenPath(FilePath* token_path) const; + + // Tries to load the device token from disk. Must be called on the FILE + // thread. + void AttemptTokenLoadFromDisk(); + + // Called if it's not possible to load the device token from disk. Sets the + // fetcher in a state that's ready to register the device with the device + // management server and receive the device token in return. If the AuthToken + // for the device management server is available, initiate the server + // request. + void MakeReadyToRequestDeviceToken(); + + // Issues a registration request to the server if both the fetcher is in the + // ready-to-request state and the device management server AuthToken is + // available. + void SendServerRequestIfPossible(); + // Saves the device management token to disk once it has been retrieved from // the server. Must be called on the FILE thread. static void WriteDeviceTokenToDisk(const FilePath& path, - const std::string& token); + const std::string& token, + const std::string& device_id); - // Returns the device ID used to register the device with the device + // Generates a new device ID used to register the device with the device // management server and generate the device token. - static std::string GetDeviceID(); + static std::string GenerateNewDeviceID(); - scoped_ptr backend_; - scoped_ptr path_provider_; + FilePath token_path_; + DeviceManagementBackend* backend_; // weak FetcherState state_; std::string device_token_; + std::string device_id_; + + // Contains the AuthToken for the device management server. Empty if the + // AuthToken hasn't been issued yet or that was an error getting the + // AuthToken. + std::string auth_token_; // An event that is signaled only once the device token has been fetched // or it has been determined that there was an error during fetching. diff --git a/chrome/browser/policy/device_token_fetcher_unittest.cc b/chrome/browser/policy/device_token_fetcher_unittest.cc index 3d15d1b..ea1e41d 100644 --- a/chrome/browser/policy/device_token_fetcher_unittest.cc +++ b/chrome/browser/policy/device_token_fetcher_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 + #include "base/file_util.h" #include "base/message_loop.h" #include "base/scoped_temp_dir.h" @@ -9,12 +11,8 @@ #include "chrome/browser/net/gaia/token_service.h" #include "chrome/browser/policy/device_token_fetcher.h" #include "chrome/browser/policy/mock_device_management_backend.h" -#include "chrome/common/net/gaia/gaia_constants.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_observer.h" #include "chrome/common/notification_service.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/notification_type.h" +#include "chrome/test/device_management_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,29 +21,6 @@ namespace policy { using testing::_; using testing::Mock; -class MockDeviceTokenPathProvider - : public StoredDeviceTokenPathProvider { - public: - MockDeviceTokenPathProvider() { - EXPECT_TRUE(temp_user_data_dir_.CreateUniqueTempDir()); - } - - virtual ~MockDeviceTokenPathProvider() {} - - virtual bool GetPath(FilePath* path) const { - if (!file_util::PathExists(temp_user_data_dir_.path())) - return false; - *path = temp_user_data_dir_.path().Append( - FILE_PATH_LITERAL("temp_token_file")); - return true; - } - - private: - ScopedTempDir temp_user_data_dir_; - - DISALLOW_COPY_AND_ASSIGN(MockDeviceTokenPathProvider); -}; - class MockTokenAvailableObserver : public NotificationObserver { public: MockTokenAvailableObserver() {} @@ -62,56 +37,81 @@ class MockTokenAvailableObserver : public NotificationObserver { class DeviceTokenFetcherTest : public testing::Test { protected: - DeviceTokenFetcherTest() { - backend_ = new MockDeviceManagementBackend(); - path_provider_ = new MockDeviceTokenPathProvider(); - fetcher_.reset(new DeviceTokenFetcher(backend_, path_provider_)); + DeviceTokenFetcherTest() + : ui_thread_(BrowserThread::UI, &loop_), + file_thread_(BrowserThread::FILE, &loop_) { + EXPECT_TRUE(temp_user_data_dir_.CreateUniqueTempDir()); + fetcher_ = NewTestFetcher(temp_user_data_dir_.path()); fetcher_->StartFetching(); } - virtual void SetUp() { - ui_thread_.reset(new BrowserThread(BrowserThread::UI, &loop_)); - file_thread_.reset(new BrowserThread(BrowserThread::FILE, &loop_)); - } - virtual void TearDown() { loop_.RunAllPending(); } - void SimulateSuccessfulLogin() { - const std::string service(GaiaConstants::kDeviceManagementService); - const std::string auth_token(kFakeGaiaAuthToken); - const Source source(NULL); - TokenService::TokenAvailableDetails details(service, auth_token); - NotificationService::current()->Notify( - NotificationType::TOKEN_AVAILABLE, - source, - Details(&details)); + void SimulateSuccessfulLoginAndRunPending() { + loop_.RunAllPending(); + SimulateSuccessfulLogin(); loop_.RunAllPending(); } - MockDeviceManagementBackend* backend_; // weak - MockDeviceTokenPathProvider* path_provider_; // weak - scoped_ptr fetcher_; + DeviceTokenFetcher* NewTestFetcher(const FilePath& token_dir) { + backend_.reset(new MockDeviceManagementBackend()); + return new DeviceTokenFetcher( + backend_.get(), + token_dir.Append(FILE_PATH_LITERAL("test-token-file.txt"))); + } + + static void GetDeviceTokenPath(const DeviceTokenFetcher* fetcher, + FilePath* path) { + fetcher->GetDeviceTokenPath(path); + } + + const std::string& device_id(const DeviceTokenFetcher* fetcher) { + return fetcher->device_id_; + } - private: MessageLoop loop_; - scoped_ptr ui_thread_; - scoped_ptr file_thread_; + scoped_ptr backend_; + ScopedTempDir temp_user_data_dir_; + scoped_refptr fetcher_; - static const char kFakeGaiaAuthToken[]; + private: + BrowserThread ui_thread_; + BrowserThread file_thread_; }; -const char DeviceTokenFetcherTest::kFakeGaiaAuthToken[] = "0123456789abcdef"; - TEST_F(DeviceTokenFetcherTest, IsPending) { ASSERT_TRUE(fetcher_->IsTokenPending()); - SimulateSuccessfulLogin(); + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); + ASSERT_FALSE(fetcher_->IsTokenPending()); +} + +TEST_F(DeviceTokenFetcherTest, StoreAndLoad) { + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); + std::string device_token = fetcher_->GetDeviceToken(); + std::string device_id = fetcher_->GetDeviceID(); + ASSERT_NE("", device_id); + + FilePath token_path; + GetDeviceTokenPath(fetcher_, &token_path); + scoped_refptr fetcher2( + new DeviceTokenFetcher(backend_.get(), token_path)); + fetcher2->StartFetching(); + loop_.RunAllPending(); + ASSERT_EQ(device_id, fetcher2->GetDeviceID()); + ASSERT_EQ(device_token, fetcher2->GetDeviceToken()); } TEST_F(DeviceTokenFetcherTest, SimpleFetchSingleLogin) { - SimulateSuccessfulLogin(); + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); ASSERT_TRUE(fetcher_->IsTokenValid()); const std::string token(fetcher_->GetDeviceToken()); @@ -119,12 +119,14 @@ TEST_F(DeviceTokenFetcherTest, SimpleFetchSingleLogin) { } TEST_F(DeviceTokenFetcherTest, SimpleFetchDoubleLogin) { - SimulateSuccessfulLogin(); + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); const std::string token(fetcher_->GetDeviceToken()); EXPECT_NE("", token); - SimulateSuccessfulLogin(); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); const std::string token2(fetcher_->GetDeviceToken()); EXPECT_NE("", token2); @@ -138,29 +140,21 @@ TEST_F(DeviceTokenFetcherTest, FetchBetweenBrowserLaunchAndNotify) { NotificationType::DEVICE_TOKEN_AVAILABLE, NotificationService::AllSources()); EXPECT_CALL(observer, Observe(_, _, _)).Times(1); - - SimulateSuccessfulLogin(); + backend_->AllShouldSucceed(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); const std::string token(fetcher_->GetDeviceToken()); EXPECT_NE("", token); - Mock::VerifyAndClearExpectations(&observer); - EXPECT_CALL(observer, Observe(_, _, _)).Times(1); // Swap out the fetchers, including copying the device management token on // disk to where the new fetcher expects it. - backend_ = new MockDeviceManagementBackend(); - FilePath old_path; - ASSERT_TRUE(path_provider_->GetPath(&old_path)); - MockDeviceTokenPathProvider* new_provider = - new MockDeviceTokenPathProvider(); - FilePath new_path; - ASSERT_TRUE(new_provider->GetPath(&new_path)); - ASSERT_TRUE(file_util::Move(old_path, new_path)); - path_provider_ = new_provider; - fetcher_.reset(new DeviceTokenFetcher(backend_, path_provider_)); - + fetcher_ = NewTestFetcher( + temp_user_data_dir_.path()); fetcher_->StartFetching(); + ASSERT_TRUE(fetcher_->IsTokenPending()); + loop_.RunAllPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); const std::string token2(fetcher_->GetDeviceToken()); EXPECT_NE("", token2); @@ -168,11 +162,24 @@ TEST_F(DeviceTokenFetcherTest, FetchBetweenBrowserLaunchAndNotify) { } TEST_F(DeviceTokenFetcherTest, FailedServerRequest) { - backend_->SetFailure(true); - SimulateSuccessfulLogin(); + backend_->AllShouldFail(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); ASSERT_FALSE(fetcher_->IsTokenPending()); const std::string token(fetcher_->GetDeviceToken()); EXPECT_EQ("", token); } +TEST_F(DeviceTokenFetcherTest, UnmanagedDevice) { + backend_->UnmanagedDevice(); + EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(1); + SimulateSuccessfulLoginAndRunPending(); + ASSERT_FALSE(fetcher_->IsTokenPending()); + ASSERT_EQ("", fetcher_->GetDeviceToken()); + ASSERT_EQ("", device_id(fetcher_)); + FilePath token_path; + GetDeviceTokenPath(fetcher_, &token_path); + ASSERT_FALSE(file_util::PathExists(token_path)); +} + } // namespace policy diff --git a/chrome/browser/policy/file_based_policy_provider.cc b/chrome/browser/policy/file_based_policy_provider.cc index 5a92105..578277d 100644 --- a/chrome/browser/policy/file_based_policy_provider.cc +++ b/chrome/browser/policy/file_based_policy_provider.cc @@ -58,21 +58,6 @@ bool FileBasedPolicyProvider::Provide( return true; } -void FileBasedPolicyProvider::DecodePolicyValueTree( - DictionaryValue* policies, - ConfigurationPolicyStoreInterface* store) { - const PolicyDefinitionList* policy_list(policy_definition_list()); - for (const PolicyDefinitionList::Entry* i = policy_list->begin; - i != policy_list->end; ++i) { - Value* value; - if (policies->Get(i->name, &value) && value->IsType(i->value_type)) - store->Apply(i->policy_type, value->DeepCopy()); - } - - // TODO(mnissler): Handle preference overrides once |ConfigurationPolicyStore| - // supports it. -} - // FileBasedPolicyLoader implementation: FileBasedPolicyLoader::FileBasedPolicyLoader( diff --git a/chrome/browser/policy/file_based_policy_provider.h b/chrome/browser/policy/file_based_policy_provider.h index 49af11f..a4e989d 100644 --- a/chrome/browser/policy/file_based_policy_provider.h +++ b/chrome/browser/policy/file_based_policy_provider.h @@ -67,10 +67,6 @@ class FileBasedPolicyProvider virtual bool Provide(ConfigurationPolicyStoreInterface* store); private: - // Decodes the value tree and writes the configuration to the given |store|. - void DecodePolicyValueTree(DictionaryValue* policies, - ConfigurationPolicyStoreInterface* store); - // Watches for changes to the configuration directory. scoped_refptr watcher_; diff --git a/chrome/browser/policy/mock_configuration_policy_store.cc b/chrome/browser/policy/mock_configuration_policy_store.cc new file mode 100644 index 0000000..bda4688 --- /dev/null +++ b/chrome/browser/policy/mock_configuration_policy_store.cc @@ -0,0 +1,33 @@ +// 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/policy/mock_configuration_policy_store.h" + +namespace policy { + +using ::testing::_; +using ::testing::Invoke; + +MockConfigurationPolicyStore::MockConfigurationPolicyStore() { + ON_CALL(*this, Apply(_, _)).WillByDefault( + Invoke(this, &MockConfigurationPolicyStore::ApplyToMap)); +} + +MockConfigurationPolicyStore::~MockConfigurationPolicyStore() { + STLDeleteValues(&policy_map_); +} + +const Value* MockConfigurationPolicyStore::Get( + ConfigurationPolicyType type) const { + PolicyMap::const_iterator entry(policy_map_.find(type)); + return entry == policy_map_.end() ? NULL : entry->second; +} + +void MockConfigurationPolicyStore::ApplyToMap( + ConfigurationPolicyType policy, Value* value) { + std::swap(policy_map_[policy], value); + delete value; +} + +} // namespace policy diff --git a/chrome/browser/policy/mock_configuration_policy_store.h b/chrome/browser/policy/mock_configuration_policy_store.h index 87dc646..472357d 100644 --- a/chrome/browser/policy/mock_configuration_policy_store.h +++ b/chrome/browser/policy/mock_configuration_policy_store.h @@ -10,7 +10,9 @@ #include #include "base/stl_util-inl.h" +#include "base/values.h" #include "chrome/browser/policy/configuration_policy_store_interface.h" +#include "testing/gmock/include/gmock/gmock.h" namespace policy { @@ -20,27 +22,22 @@ class MockConfigurationPolicyStore : public ConfigurationPolicyStoreInterface { public: typedef std::map PolicyMap; - MockConfigurationPolicyStore() {} - ~MockConfigurationPolicyStore() { - STLDeleteValues(&policy_map_); - } + MockConfigurationPolicyStore(); + virtual ~MockConfigurationPolicyStore(); const PolicyMap& policy_map() const { return policy_map_; } // Get a value for the given policy. Returns NULL if that key doesn't exist. - const Value* Get(ConfigurationPolicyType type) const { - PolicyMap::const_iterator entry(policy_map_.find(type)); - return entry == policy_map_.end() ? NULL : entry->second; - } - + const Value* Get(ConfigurationPolicyType type) const; // ConfigurationPolicyStore implementation. - virtual void Apply(ConfigurationPolicyType policy, Value* value) { - std::swap(policy_map_[policy], value); - delete value; - } + void ApplyToMap(ConfigurationPolicyType policy, Value* value); + + MOCK_METHOD2(Apply, void(ConfigurationPolicyType policy, Value* value)); private: PolicyMap policy_map_; + + DISALLOW_COPY_AND_ASSIGN(MockConfigurationPolicyStore); }; } // namespace policy diff --git a/chrome/browser/policy/mock_device_management_backend.cc b/chrome/browser/policy/mock_device_management_backend.cc index 61a20e9..613022f 100644 --- a/chrome/browser/policy/mock_device_management_backend.cc +++ b/chrome/browser/policy/mock_device_management_backend.cc @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/logging.h" #include "chrome/browser/policy/mock_device_management_backend.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/stl_util-inl.h" + namespace { static const char kFakeDeviceManagementToken[] = "FAKE_DEVICE_TOKEN_"; @@ -14,48 +17,105 @@ static char next_token_suffix_ = '0'; namespace policy { -using enterprise_management::DeviceRegisterRequest; -using enterprise_management::DeviceUnregisterRequest; -using enterprise_management::DevicePolicyRequest; -using enterprise_management::DeviceRegisterResponse; -using enterprise_management::DeviceUnregisterResponse; -using enterprise_management::DevicePolicyResponse; +using ::testing::_; +using ::testing::Invoke; + +using em::DeviceRegisterRequest; +using em::DeviceUnregisterRequest; +using em::DevicePolicyRequest; +using em::DeviceRegisterResponse; +using em::DeviceUnregisterResponse; +using em::DevicePolicyResponse; MockDeviceManagementBackend::MockDeviceManagementBackend() - : DeviceManagementBackend(), - failure_(false) { + : DeviceManagementBackend() { + policy_setting_ = policy_response_.add_setting(); + policy_setting_->set_policy_key("chrome-policy"); + policy_setting_->set_watermark("fresh"); +} + +MockDeviceManagementBackend::~MockDeviceManagementBackend() { +} + +void MockDeviceManagementBackend::AllShouldSucceed() { + ON_CALL(*this, ProcessRegisterRequest(_, _, _, _)). + WillByDefault(Invoke( + this, + &MockDeviceManagementBackend::SimulateSuccessfulRegisterRequest)); + ON_CALL(*this, ProcessPolicyRequest(_, _, _)). + WillByDefault(Invoke( + this, + &MockDeviceManagementBackend::SimulateSuccessfulPolicyRequest)); +} + +void MockDeviceManagementBackend::AllShouldFail() { + ON_CALL(*this, ProcessRegisterRequest(_, _, _, _)). + WillByDefault(Invoke( + this, + &MockDeviceManagementBackend::SimulateFailedRegisterRequest)); + ON_CALL(*this, ProcessPolicyRequest(_, _, _)). + WillByDefault(Invoke( + this, + &MockDeviceManagementBackend::SimulateFailedPolicyRequest)); +} + +void MockDeviceManagementBackend::UnmanagedDevice() { + ON_CALL(*this, ProcessRegisterRequest(_, _, _, _)). + WillByDefault(Invoke( + this, + &MockDeviceManagementBackend::SimulateUnmanagedRegisterRequest)); +} + +void MockDeviceManagementBackend::AddBooleanPolicy(const char* policy_name, + bool value) { + em::GenericSetting* policy_value = policy_setting_->mutable_policy_value(); + em::GenericNamedValue* named_value = policy_value->add_named_value(); + named_value->set_name(policy_name); + named_value->mutable_value()->set_value_type( + em::GenericValue::VALUE_TYPE_BOOL); + named_value->mutable_value()->set_bool_value(value); } -void MockDeviceManagementBackend::ProcessRegisterRequest( +void MockDeviceManagementBackend::SimulateSuccessfulRegisterRequest( const std::string& auth_token, const std::string& device_id, - const DeviceRegisterRequest& request, + const em::DeviceRegisterRequest& request, DeviceRegisterResponseDelegate* delegate) { - if (failure_) { - delegate->OnError(kErrorRequestInvalid); - } else { - DeviceRegisterResponse response; - std::string token(kFakeDeviceManagementToken); - token += next_token_suffix_++; - response.set_device_management_token(token); - delegate->HandleRegisterResponse(response); - } -} - -void MockDeviceManagementBackend::ProcessUnregisterRequest( + DeviceRegisterResponse response; + std::string token(kFakeDeviceManagementToken); + token += next_token_suffix_++; + response.set_device_management_token(token); + delegate->HandleRegisterResponse(response); +} + +void MockDeviceManagementBackend::SimulateSuccessfulPolicyRequest( const std::string& device_management_token, - const DeviceUnregisterRequest& request, - DeviceUnregisterResponseDelegate* delegate) { - // TODO(danno): need a mock implementation for the backend here. - NOTREACHED(); + const em::DevicePolicyRequest& request, + DevicePolicyResponseDelegate* delegate) { + delegate->HandlePolicyResponse(policy_response_); } -void MockDeviceManagementBackend::ProcessPolicyRequest( +void MockDeviceManagementBackend::SimulateFailedRegisterRequest( + const std::string& auth_token, + const std::string& device_id, + const em::DeviceRegisterRequest& request, + DeviceRegisterResponseDelegate* delegate) { + delegate->OnError(kErrorRequestFailed); +} + +void MockDeviceManagementBackend::SimulateFailedPolicyRequest( const std::string& device_management_token, - const DevicePolicyRequest& request, + const em::DevicePolicyRequest& request, DevicePolicyResponseDelegate* delegate) { - // TODO(danno): need a mock implementation for the backend here. - NOTREACHED(); + delegate->OnError(kErrorRequestFailed); +} + +void MockDeviceManagementBackend::SimulateUnmanagedRegisterRequest( + const std::string& auth_token, + const std::string& device_id, + const em::DeviceRegisterRequest& request, + DeviceRegisterResponseDelegate* delegate) { + delegate->OnError(kErrorServiceManagementNotSupported); } } // namespace diff --git a/chrome/browser/policy/mock_device_management_backend.h b/chrome/browser/policy/mock_device_management_backend.h index 290e615..f0612f4 100644 --- a/chrome/browser/policy/mock_device_management_backend.h +++ b/chrome/browser/policy/mock_device_management_backend.h @@ -6,9 +6,13 @@ #define CHROME_BROWSER_POLICY_MOCK_DEVICE_MANAGEMENT_BACKEND_H_ #pragma once +#include #include +#include "base/values.h" #include "chrome/browser/policy/device_management_backend.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" namespace policy { @@ -21,29 +25,63 @@ class MockDeviceManagementBackend : public DeviceManagementBackend { public: MockDeviceManagementBackend(); - virtual ~MockDeviceManagementBackend() {} - - void SetFailure(bool failure) { failure_ = failure; } + virtual ~MockDeviceManagementBackend(); // DeviceManagementBackend method overrides: - virtual void ProcessRegisterRequest( + MOCK_METHOD4(ProcessRegisterRequest, void( const std::string& auth_token, const std::string& device_id, const em::DeviceRegisterRequest& request, - DeviceRegisterResponseDelegate* delegate); + DeviceRegisterResponseDelegate* delegate)); - virtual void ProcessUnregisterRequest( + MOCK_METHOD3(ProcessUnregisterRequest, void( const std::string& device_management_token, const em::DeviceUnregisterRequest& request, - DeviceUnregisterResponseDelegate* delegate); + DeviceUnregisterResponseDelegate* delegate)); + + MOCK_METHOD3(ProcessPolicyRequest, void( + const std::string& device_management_token, + const em::DevicePolicyRequest& request, + DevicePolicyResponseDelegate* delegate)); + + void AllShouldSucceed(); + void AllShouldFail(); + void UnmanagedDevice(); + + void SimulateSuccessfulRegisterRequest( + const std::string& auth_token, + const std::string& device_id, + const em::DeviceRegisterRequest& request, + DeviceRegisterResponseDelegate* delegate); - virtual void ProcessPolicyRequest( + void SimulateSuccessfulPolicyRequest( const std::string& device_management_token, const em::DevicePolicyRequest& request, DevicePolicyResponseDelegate* delegate); + void SimulateFailedRegisterRequest( + const std::string& auth_token, + const std::string& device_id, + const em::DeviceRegisterRequest& request, + DeviceRegisterResponseDelegate* delegate); + + void SimulateFailedPolicyRequest( + const std::string& device_management_token, + const em::DevicePolicyRequest& request, + DevicePolicyResponseDelegate* delegate); + + void SimulateUnmanagedRegisterRequest( + const std::string& auth_token, + const std::string& device_id, + const em::DeviceRegisterRequest& request, + DeviceRegisterResponseDelegate* delegate); + + void AddBooleanPolicy(const char* policy_name, bool value); + private: - bool failure_; + em::DevicePolicyResponse policy_response_; + em::DevicePolicySetting* policy_setting_; + DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementBackend); }; diff --git a/chrome/browser/policy/proto/device_management_backend.proto b/chrome/browser/policy/proto/device_management_backend.proto index 6b0cc8d..0f2451b 100644 --- a/chrome/browser/policy/proto/device_management_backend.proto +++ b/chrome/browser/policy/proto/device_management_backend.proto @@ -17,7 +17,7 @@ message GenericValue { VALUE_TYPE_DOUBLE = 4; VALUE_TYPE_BYTES = 5; VALUE_TYPE_BOOL_ARRAY = 6; - VALUE_TYPE_INT64_ARRAY_ = 7; + VALUE_TYPE_INT64_ARRAY = 7; VALUE_TYPE_STRING_ARRAY = 8; VALUE_TYPE_DOUBLE_ARRAY = 9; } @@ -146,6 +146,8 @@ message DeviceManagementResponse { DEVICE_MANAGEMENT_TOKEN_INVALID = 3; // Returned when device registration is pending approval (if required). ACTIVATION_PENDING = 4; + // Returned when the policy is not found. + POLICY_NOT_FOUND = 5; } // Error code for this request. diff --git a/chrome/browser/policy/proto/device_management_local.proto b/chrome/browser/policy/proto/device_management_local.proto new file mode 100644 index 0000000..ad7fc05 --- /dev/null +++ b/chrome/browser/policy/proto/device_management_local.proto @@ -0,0 +1,26 @@ +// 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package enterprise_management; + +import "device_management_backend.proto"; + +// Wrapper around DevicePolicyResponse for caching on disk. +message CachedDevicePolicyResponse { + // The DevicePolicyResponse wrapped by this message. + required DevicePolicyResponse policy = 1; + // Timestamp noting when this policy was cached. + optional uint64 timestamp = 2; +} + +// Encapsulates a device ID and the associated device token. +message DeviceCredentials { + optional string device_id = 1; + optional string device_token = 2; +} + diff --git a/chrome/browser/policy/proto/device_management_proto.gyp b/chrome/browser/policy/proto/device_management_proto.gyp new file mode 100644 index 0000000..0fc6f82 --- /dev/null +++ b/chrome/browser/policy/proto/device_management_proto.gyp @@ -0,0 +1,80 @@ +# 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. + +{ + 'variables': { + 'chromium_code': 1, + 'protoc_out_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out', + }, + 'targets': [ + { + # Protobuf compiler / generate rule for the device management protocol. + 'target_name': 'device_management_proto', + 'type': 'none', + 'sources': [ + 'device_management_backend.proto', + 'device_management_local.proto', + ], + 'rules': [ + { + 'rule_name': 'genproto', + 'extension': 'proto', + 'inputs': [ + '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)', + ], + 'variables': { + # The protoc compiler requires a proto_path argument with the + # directory containing the .proto file. There's no generator + # variable that corresponds to this, so fake it. + 'rule_input_relpath': 'chrome/browser/policy/proto', + }, + 'outputs': [ + '<(PRODUCT_DIR)/pyproto/device_management_pb/<(RULE_INPUT_ROOT)_pb2.py', + '<(protoc_out_dir)/<(rule_input_relpath)/<(RULE_INPUT_ROOT).pb.h', + '<(protoc_out_dir)/<(rule_input_relpath)/<(RULE_INPUT_ROOT).pb.cc', + ], + 'action': [ + '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)', + '--proto_path=.', + './<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)', + '--cpp_out=<(protoc_out_dir)/<(rule_input_relpath)', + '--python_out=<(PRODUCT_DIR)/pyproto/device_management_pb', + ], + 'message': 'Generating C++ and Python code from <(RULE_INPUT_PATH)', + }, + ], + 'dependencies': [ + '../../../../third_party/protobuf/protobuf.gyp:protoc#host', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(protoc_out_dir)', + ] + }, + }, + { + 'target_name': 'device_management_proto_cpp', + 'type': 'none', + 'export_dependent_settings': [ + '../../../../third_party/protobuf/protobuf.gyp:protobuf_lite', + 'device_management_proto', + ], + 'dependencies': [ + '../../../../third_party/protobuf/protobuf.gyp:protobuf_lite', + 'device_management_proto', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(protoc_out_dir)', + ] + }, + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/chrome/browser/popup_blocker_browsertest.cc b/chrome/browser/popup_blocker_browsertest.cc index 2276f5f..9a99d7f 100644 --- a/chrome/browser/popup_blocker_browsertest.cc +++ b/chrome/browser/popup_blocker_browsertest.cc @@ -7,11 +7,11 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/message_loop.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/ppapi_plugin_process_host.cc b/chrome/browser/ppapi_plugin_process_host.cc new file mode 100644 index 0000000..ba47b86 --- /dev/null +++ b/chrome/browser/ppapi_plugin_process_host.cc @@ -0,0 +1,104 @@ +// 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/ppapi_plugin_process_host.h" + +#include "base/command_line.h" +#include "base/file_path.h" +#include "base/process_util.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/render_messages.h" +#include "ipc/ipc_channel_handle.h" +#include "ipc/ipc_switches.h" +#include "ppapi/proxy/ppapi_messages.h" + +PpapiPluginProcessHost::PpapiPluginProcessHost(ResourceMessageFilter* filter) + : BrowserChildProcessHost(ChildProcessInfo::PPAPI_PLUGIN_PROCESS, + filter->resource_dispatcher_host()), + filter_(filter) { +} + +PpapiPluginProcessHost::~PpapiPluginProcessHost() { +} + +void PpapiPluginProcessHost::Init(const FilePath& path, + IPC::Message* reply_msg) { + plugin_path_ = path; + reply_msg_.reset(reply_msg); + + if (!CreateChannel()) { + ReplyToRenderer(IPC::ChannelHandle()); + return; + } + + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + CommandLine::StringType plugin_launcher = + browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher); + + FilePath exe_path = ChildProcessHost::GetChildPath(plugin_launcher.empty()); + if (exe_path.empty()) { + ReplyToRenderer(IPC::ChannelHandle()); + return; + } + + CommandLine* cmd_line = new CommandLine(exe_path); + cmd_line->AppendSwitchASCII(switches::kProcessType, + switches::kPpapiPluginProcess); + cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); + + if (!plugin_launcher.empty()) + cmd_line->PrependWrapper(plugin_launcher); + + // On posix, having a plugin launcher means we need to use another process + // instead of just forking the zygote. + Launch( +#if defined(OS_WIN) + FilePath(), +#elif defined(OS_POSIX) + plugin_launcher.empty(), + base::environment_vector(), +#endif + cmd_line); +} + +void PpapiPluginProcessHost::OnProcessLaunched() { +} + +URLRequestContext* PpapiPluginProcessHost::GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data) { + return NULL; +} + +void PpapiPluginProcessHost::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PpapiPluginProcessHost, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PluginLoaded, OnPluginLoaded) + IPC_MESSAGE_UNHANDLED_ERROR(); + IPC_END_MESSAGE_MAP() +} + +void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) { + PpapiMsg_LoadPlugin* msg = new PpapiMsg_LoadPlugin(plugin_path_, + filter_->id()); + if (!Send(msg)) // Just send an empty handle on failure. + ReplyToRenderer(IPC::ChannelHandle()); + // This function will result in OnChannelCreated getting called to finish. +} + +void PpapiPluginProcessHost::OnChannelError() { + if (reply_msg_.get()) + ReplyToRenderer(IPC::ChannelHandle()); +} + +void PpapiPluginProcessHost::OnPluginLoaded(const IPC::ChannelHandle& handle) { + ReplyToRenderer(handle); +} + +void PpapiPluginProcessHost::ReplyToRenderer(const IPC::ChannelHandle& handle) { + DCHECK(reply_msg_.get()); + ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(reply_msg_.get(), + handle); + filter_->Send(reply_msg_.release()); +} diff --git a/chrome/browser/ppapi_plugin_process_host.h b/chrome/browser/ppapi_plugin_process_host.h new file mode 100644 index 0000000..956148c --- /dev/null +++ b/chrome/browser/ppapi_plugin_process_host.h @@ -0,0 +1,57 @@ +// 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_PPAPI_PLUGIN_PROCESS_HOST_H_ +#define CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "chrome/browser/browser_child_process_host.h" + +class ResourceMessageFilter; + +namespace IPC { +struct ChannelHandle; +class Message; +} + +class PpapiPluginProcessHost : public BrowserChildProcessHost { + public: + explicit PpapiPluginProcessHost(ResourceMessageFilter* filter); + virtual ~PpapiPluginProcessHost(); + + void Init(const FilePath& path, IPC::Message* reply_msg); + + private: + virtual bool CanShutdown() { return true; } + virtual void OnProcessLaunched(); + virtual URLRequestContext* GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data); + + virtual void OnMessageReceived(const IPC::Message& msg); + virtual void OnChannelConnected(int32 peer_pid); + virtual void OnChannelError(); + + // IPC message handlers. + void OnPluginLoaded(const IPC::ChannelHandle& handle); + + // Sends the reply_msg_ to the renderer with the given channel info. + void ReplyToRenderer(const IPC::ChannelHandle& handle); + + ResourceMessageFilter* filter_; + + // Path to the plugin library. + FilePath plugin_path_; + + // When we're waiting for initialization of the plugin, this contains the + // reply message for the renderer to tell it that it can continue. + scoped_ptr reply_msg_; + + DISALLOW_COPY_AND_ASSIGN(PpapiPluginProcessHost); +}; + +#endif // CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_ + diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 9f23e54..0572dbb 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -9,7 +9,6 @@ #include "chrome/browser/background_contents_service.h" #include "chrome/browser/background_mode_manager.h" #include "chrome/browser/bookmarks/bookmark_utils.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/dom_ui/flags_ui.h" @@ -49,6 +48,7 @@ #include "chrome/browser/tabs/pinned_tab_codec.h" #include "chrome/browser/task_manager/task_manager.h" #include "chrome/browser/translate/translate_prefs.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/upgrade_detector.h" #if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port @@ -61,13 +61,13 @@ #endif #if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/cros_settings_provider_user.h" #include "chrome/browser/chromeos/login/apply_services_customization.h" #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/preferences.h" #include "chrome/browser/chromeos/status/input_method_menu_button.h" +#include "chrome/browser/chromeos/user_cros_settings_provider.h" #endif namespace browser { diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc index 5a9a7eb..2bebe5b 100644 --- a/chrome/browser/prefs/command_line_pref_store.cc +++ b/chrome/browser/prefs/command_line_pref_store.cc @@ -16,12 +16,21 @@ const CommandLinePrefStore::StringSwitchToPreferenceMapEntry { switches::kProxyServer, prefs::kProxyServer }, { switches::kProxyPacUrl, prefs::kProxyPacUrl }, { switches::kProxyBypassList, prefs::kProxyBypassList }, + { switches::kAuthSchemes, prefs::kAuthSchemes }, + { switches::kAuthServerWhitelist, prefs::kAuthServerWhitelist }, + { switches::kAuthNegotiateDelegateWhitelist, + prefs::kAuthNegotiateDelegateWhitelist }, + { switches::kGSSAPILibraryName, prefs::kGSSAPILibraryName }, }; const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry CommandLinePrefStore::boolean_switch_map_[] = { { switches::kNoProxyServer, prefs::kNoProxyServer, true }, { switches::kProxyAutoDetect, prefs::kProxyAutoDetect, true }, + { switches::kDisableAuthNegotiateCnameLookup, + prefs::kDisableAuthNegotiateCnameLookup, true }, + { switches::kEnableAuthNegotiatePort, prefs::kEnableAuthNegotiatePort, + true }, }; CommandLinePrefStore::CommandLinePrefStore(const CommandLine* command_line) diff --git a/chrome/browser/prefs/pref_notifier.h b/chrome/browser/prefs/pref_notifier.h index 98dc1e3..7334a51 100644 --- a/chrome/browser/prefs/pref_notifier.h +++ b/chrome/browser/prefs/pref_notifier.h @@ -27,7 +27,11 @@ class PrefNotifier : public NonThreadSafe, public NotificationObserver { public: // PrefStores must be listed here in order from highest to lowest priority. - // MANAGED contains all managed (policy) preference values. + // MANAGED_PLATFORM contains all managed preference values that are + // provided by a platform-specific policy mechanism (e.g. Windows + // Group Policy). + // DEVICE_MANAGEMENT contains all managed preference values supplied + // by the device management server (cloud policy). // EXTENSION contains preference values set by extensions. // COMMAND_LINE contains preference values set by command-line switches. // USER contains all user-set preference values. @@ -39,7 +43,8 @@ class PrefNotifier : public NonThreadSafe, // INVALID_STORE is not associated with an actual PrefStore but used as // an invalid marker, e.g. as a return value. INVALID_STORE = -1, - MANAGED_STORE = 0, + MANAGED_PLATFORM_STORE = 0, + DEVICE_MANAGEMENT_STORE, EXTENSION_STORE, COMMAND_LINE_STORE, USER_STORE, diff --git a/chrome/browser/prefs/pref_notifier_unittest.cc b/chrome/browser/prefs/pref_notifier_unittest.cc index 0af137c..a755f7a 100644 --- a/chrome/browser/prefs/pref_notifier_unittest.cc +++ b/chrome/browser/prefs/pref_notifier_unittest.cc @@ -61,7 +61,8 @@ class MockPrefNotifier : public PrefNotifier { class MockPrefValueStore : public PrefValueStore { public: MockPrefValueStore() - : PrefValueStore(NULL, NULL, NULL, NULL, NULL, new DefaultPrefStore()) {} + : PrefValueStore(NULL, NULL, NULL, NULL, NULL, NULL, + new DefaultPrefStore()) {} virtual ~MockPrefValueStore() {} diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc index bdf1ed8..8662f88 100644 --- a/chrome/browser/prefs/pref_service.cc +++ b/chrome/browser/prefs/pref_service.cc @@ -623,8 +623,10 @@ const Value* PrefService::Preference::GetValue() const { } bool PrefService::Preference::IsManaged() const { - return pref_service_->pref_value_store_-> - PrefValueInManagedStore(name_.c_str()); + PrefValueStore* pref_value_store = + pref_service_->pref_value_store_; + return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) || + pref_value_store->PrefValueInDeviceManagementStore(name_.c_str()); } bool PrefService::Preference::HasExtensionSetting() const { diff --git a/chrome/browser/prefs/pref_service_unittest.cc b/chrome/browser/prefs/pref_service_unittest.cc index 54cc3dd..e7c737c 100644 --- a/chrome/browser/prefs/pref_service_unittest.cc +++ b/chrome/browser/prefs/pref_service_unittest.cc @@ -191,7 +191,7 @@ TEST(PrefServiceTest, Observers) { TEST(PrefServiceTest, ProxyFromCommandLineNotPolicy) { CommandLine command_line(CommandLine::NO_PROGRAM); command_line.AppendSwitch(switches::kProxyAutoDetect); - TestingPrefService prefs(NULL, &command_line); + TestingPrefService prefs(NULL, NULL, &command_line); browser::RegisterUserPrefs(&prefs); EXPECT_TRUE(prefs.GetBoolean(prefs::kProxyAutoDetect)); const PrefService::Preference* pref = @@ -219,7 +219,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) { // First verify that command-line options are set correctly when // there is no policy in effect. - TestingPrefService prefs(NULL, &command_line); + TestingPrefService prefs(NULL, NULL, &command_line); browser::RegisterUserPrefs(&prefs); EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); @@ -230,7 +230,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) { // Try a second time time with the managed PrefStore in place, the // manual proxy policy should have removed all traces of the command // line and replaced them with the policy versions. - TestingPrefService prefs2(provider.get(), &command_line); + TestingPrefService prefs2(provider.get(), NULL, &command_line); browser::RegisterUserPrefs(&prefs2); EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); @@ -252,7 +252,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesUnrelatedCommandLineOptions) { // First verify that command-line options are set correctly when // there is no policy in effect. - TestingPrefService prefs(NULL, &command_line); + TestingPrefService prefs(NULL, NULL, &command_line); browser::RegisterUserPrefs(&prefs); EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); @@ -264,7 +264,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesUnrelatedCommandLineOptions) { // no proxy policy should have removed all traces of the command // line proxy settings, even though they were not the specific one // set in policy. - TestingPrefService prefs2(provider.get(), &command_line); + TestingPrefService prefs2(provider.get(), NULL, &command_line); browser::RegisterUserPrefs(&prefs2); EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); @@ -284,7 +284,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineNoProxy) { // First verify that command-line options are set correctly when // there is no policy in effect. - TestingPrefService prefs(NULL, &command_line); + TestingPrefService prefs(NULL, NULL, &command_line); browser::RegisterUserPrefs(&prefs); EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_TRUE(prefs.GetBoolean(prefs::kNoProxyServer)); @@ -295,7 +295,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineNoProxy) { // Try a second time time with the managed PrefStore in place, the // auto-detect should be overridden. The default pref store must be // in place with the appropriate default value for this to work. - TestingPrefService prefs2(provider.get(), &command_line); + TestingPrefService prefs2(provider.get(), NULL, &command_line); browser::RegisterUserPrefs(&prefs2); EXPECT_TRUE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); @@ -315,7 +315,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineAutoDetect) { // First verify that the auto-detect is set if there is no managed // PrefStore. - TestingPrefService prefs(NULL, &command_line); + TestingPrefService prefs(NULL, NULL, &command_line); browser::RegisterUserPrefs(&prefs); EXPECT_TRUE(prefs.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); @@ -326,7 +326,7 @@ TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineAutoDetect) { // Try a second time time with the managed PrefStore in place, the // auto-detect should be overridden. The default pref store must be // in place with the appropriate default value for this to work. - TestingPrefService prefs2(provider.get(), &command_line); + TestingPrefService prefs2(provider.get(), NULL, &command_line); browser::RegisterUserPrefs(&prefs2); EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); EXPECT_TRUE(prefs2.GetBoolean(prefs::kNoProxyServer)); diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc index 0fd6126..53690c4 100644 --- a/chrome/browser/prefs/pref_value_store.cc +++ b/chrome/browser/prefs/pref_value_store.cc @@ -47,6 +47,7 @@ PrefValueStore* PrefValueStore::CreatePrefValueStore( #else using policy::ConfigurationPolicyPrefStore; ConfigurationPolicyPrefStore* managed = NULL; + ConfigurationPolicyPrefStore* device_management = NULL; ExtensionPrefStore* extension = NULL; CommandLinePrefStore* command_line = NULL; ConfigurationPolicyPrefStore* recommended = NULL; @@ -57,15 +58,23 @@ PrefValueStore* PrefValueStore::CreatePrefValueStore( DefaultPrefStore* default_store = new DefaultPrefStore(); if (!user_only) { - managed = ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore(); + managed = + ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore(); + device_management = + ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(); extension = new ExtensionPrefStore(profile, PrefNotifier::EXTENSION_STORE); command_line = new CommandLinePrefStore(CommandLine::ForCurrentProcess()); recommended = ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore(); } +<<<<<<< HEAD return new PrefValueStore(managed, extension, command_line, user, recommended, default_store); #endif +======= + return new PrefValueStore(managed, device_management, extension, + command_line, user, recommended, default_store); +>>>>>>> chromium.org at r66597 } PrefValueStore::~PrefValueStore() {} @@ -199,8 +208,12 @@ bool PrefValueStore::RemoveUserPrefValue(const char* name) { return false; } -bool PrefValueStore::PrefValueInManagedStore(const char* name) const { - return PrefValueInStore(name, PrefNotifier::MANAGED_STORE); +bool PrefValueStore::PrefValueInManagedPlatformStore(const char* name) const { + return PrefValueInStore(name, PrefNotifier::MANAGED_PLATFORM_STORE); +} + +bool PrefValueStore::PrefValueInDeviceManagementStore(const char* name) const { + return PrefValueInStore(name, PrefNotifier::DEVICE_MANAGEMENT_STORE); } bool PrefValueStore::PrefValueInExtensionStore(const char* name) const { @@ -295,6 +308,7 @@ bool PrefValueStore::GetValueFromStore( return false; } +<<<<<<< HEAD #ifndef ANDROID void PrefValueStore::RefreshPolicyPrefsCompletion( PrefStore* new_managed_pref_store, @@ -332,23 +346,37 @@ void PrefValueStore::RefreshPolicyPrefsCompletion( callback->Run(changed_paths); } +======= +>>>>>>> chromium.org at r66597 void PrefValueStore::RefreshPolicyPrefsOnFileThread( BrowserThread::ID calling_thread_id, - PrefStore* new_managed_pref_store, + PrefStore* new_managed_platform_pref_store, + PrefStore* new_device_management_pref_store, PrefStore* new_recommended_pref_store, AfterRefreshCallback* callback_pointer) { scoped_ptr callback(callback_pointer); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - scoped_ptr managed_pref_store(new_managed_pref_store); + scoped_ptr managed_platform_pref_store( + new_managed_platform_pref_store); + scoped_ptr device_management_pref_store( + new_device_management_pref_store); scoped_ptr recommended_pref_store(new_recommended_pref_store); - PrefStore::PrefReadError read_error = new_managed_pref_store->ReadPrefs(); + PrefStore::PrefReadError read_error = + new_managed_platform_pref_store->ReadPrefs(); if (read_error != PrefStore::PREF_READ_ERROR_NONE) { LOG(ERROR) << "refresh of managed policy failed: PrefReadError = " << read_error; return; } + read_error = new_device_management_pref_store->ReadPrefs(); + if (read_error != PrefStore::PREF_READ_ERROR_NONE) { + LOG(ERROR) << "refresh of device management policy failed: " + << "PrefReadError = " << read_error; + return; + } + read_error = new_recommended_pref_store->ReadPrefs(); if (read_error != PrefStore::PREF_READ_ERROR_NONE) { LOG(ERROR) << "refresh of recommended policy failed: PrefReadError = " @@ -360,11 +388,86 @@ void PrefValueStore::RefreshPolicyPrefsOnFileThread( calling_thread_id, FROM_HERE, NewRunnableMethod(this, &PrefValueStore::RefreshPolicyPrefsCompletion, - managed_pref_store.release(), + managed_platform_pref_store.release(), + device_management_pref_store.release(), recommended_pref_store.release(), callback.release())); } +void PrefValueStore::RefreshPolicyPrefsCompletion( + PrefStore* new_managed_platform_pref_store, + PrefStore* new_device_management_pref_store, + PrefStore* new_recommended_pref_store, + AfterRefreshCallback* callback_pointer) { + scoped_ptr callback(callback_pointer); + + // Determine the paths of all the changed preferences values in the three + // policy-related stores (managed platform, device management and + // recommended). + DictionaryValue* managed_platform_prefs_before( + pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE]->prefs()); + DictionaryValue* managed_platform_prefs_after( + new_managed_platform_pref_store->prefs()); + DictionaryValue* device_management_prefs_before( + pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE]->prefs()); + DictionaryValue* device_management_prefs_after( + new_device_management_pref_store->prefs()); + DictionaryValue* recommended_prefs_before( + pref_stores_[PrefNotifier::RECOMMENDED_STORE]->prefs()); + DictionaryValue* recommended_prefs_after(new_recommended_pref_store->prefs()); + + std::vector changed_managed_platform_paths; + managed_platform_prefs_before->GetDifferingPaths(managed_platform_prefs_after, + &changed_managed_platform_paths); + + std::vector changed_device_management_paths; + device_management_prefs_before->GetDifferingPaths( + device_management_prefs_after, + &changed_device_management_paths); + + std::vector changed_recommended_paths; + recommended_prefs_before->GetDifferingPaths(recommended_prefs_after, + &changed_recommended_paths); + + // Merge all three vectors of changed value paths together, filtering + // duplicates in a post-processing step. + std::vector all_changed_managed_platform_paths( + changed_managed_platform_paths.size() + + changed_device_management_paths.size()); + + std::vector::iterator last_insert = + std::merge(changed_managed_platform_paths.begin(), + changed_managed_platform_paths.end(), + changed_device_management_paths.begin(), + changed_device_management_paths.end(), + all_changed_managed_platform_paths.begin()); + all_changed_managed_platform_paths.resize( + last_insert - all_changed_managed_platform_paths.begin()); + + std::vector changed_paths( + all_changed_managed_platform_paths.size() + + changed_recommended_paths.size()); + last_insert = std::merge(all_changed_managed_platform_paths.begin(), + all_changed_managed_platform_paths.end(), + changed_recommended_paths.begin(), + changed_recommended_paths.end(), + changed_paths.begin()); + changed_paths.resize(last_insert - changed_paths.begin()); + + last_insert = unique(changed_paths.begin(), changed_paths.end()); + changed_paths.resize(last_insert - changed_paths.begin()); + + // Replace the old stores with the new and send notification of the changed + // preferences. + pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE].reset( + new_managed_platform_pref_store); + pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE].reset( + new_device_management_pref_store); + pref_stores_[PrefNotifier::RECOMMENDED_STORE].reset( + new_recommended_pref_store); + callback->Run(changed_paths); +} + void PrefValueStore::RefreshPolicyPrefs( AfterRefreshCallback* callback) { using policy::ConfigurationPolicyPrefStore; @@ -375,8 +478,10 @@ void PrefValueStore::RefreshPolicyPrefs( // created and the refreshed policy read into them. The new stores // are swapped with the old from a Task on the UI thread after the // load is complete. - PrefStore* new_managed_pref_store( - ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore()); + PrefStore* new_managed_platform_pref_store( + ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore()); + PrefStore* new_device_management_pref_store( + ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore()); PrefStore* new_recommended_pref_store( ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore()); BrowserThread::ID current_thread_id; @@ -386,7 +491,8 @@ void PrefValueStore::RefreshPolicyPrefs( NewRunnableMethod(this, &PrefValueStore::RefreshPolicyPrefsOnFileThread, current_thread_id, - new_managed_pref_store, + new_managed_platform_pref_store, + new_device_management_pref_store, new_recommended_pref_store, callback)); } @@ -399,7 +505,8 @@ bool PrefValueStore::HasPolicyConflictingUserProxySettings() { ConfigurationPolicyPrefStore::GetProxyPreferenceSet(&proxy_prefs); ConfigurationPolicyPrefStore::ProxyPreferenceSet::const_iterator i; for (i = proxy_prefs.begin(); i != proxy_prefs.end(); ++i) { - if (PrefValueInManagedStore(*i) && + if ((PrefValueInManagedPlatformStore(*i) || + PrefValueInDeviceManagementStore(*i)) && PrefValueInStoreRange(*i, PrefNotifier::COMMAND_LINE_STORE, PrefNotifier::USER_STORE)) @@ -409,7 +516,8 @@ bool PrefValueStore::HasPolicyConflictingUserProxySettings() { return false; } -PrefValueStore::PrefValueStore(PrefStore* managed_prefs, +PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs, + PrefStore* device_management_prefs, PrefStore* extension_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, @@ -418,7 +526,10 @@ PrefValueStore::PrefValueStore(PrefStore* managed_prefs, // NULL default pref store is usually bad, but may be OK for some unit tests. if (!default_prefs) LOG(WARNING) << "default pref store is null"; - pref_stores_[PrefNotifier::MANAGED_STORE].reset(managed_prefs); + pref_stores_[PrefNotifier::MANAGED_PLATFORM_STORE].reset( + managed_platform_prefs); + pref_stores_[PrefNotifier::DEVICE_MANAGEMENT_STORE].reset( + device_management_prefs); pref_stores_[PrefNotifier::EXTENSION_STORE].reset(extension_prefs); pref_stores_[PrefNotifier::COMMAND_LINE_STORE].reset(command_line_prefs); pref_stores_[PrefNotifier::USER_STORE].reset(user_prefs); diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h index 1fae500..8ab6842 100644 --- a/chrome/browser/prefs/pref_value_store.h +++ b/chrome/browser/prefs/pref_value_store.h @@ -100,10 +100,10 @@ class PrefValueStore : public base::RefCountedThreadSafe { virtual bool PrefHasChanged(const char* path, PrefNotifier::PrefStoreType new_store); - // Returns true if the PrefValueStore is read-only. - // Because the managed and recommended PrefStores are always read-only, the - // PrefValueStore as a whole is read-only if the PrefStore containing the user - // preferences is read-only. + // Returns true if the PrefValueStore is read-only. Because the managed + // platform, device management and recommended PrefStores are always + // read-only, the PrefValueStore as a whole is read-only if the PrefStore + // containing the user preferences is read-only. bool ReadOnly(); // Alters the user-defined value of a preference. Even if the preference is @@ -127,7 +127,8 @@ class PrefValueStore : public base::RefCountedThreadSafe { // These methods return true if a preference with the given name is in the // indicated pref store, even if that value is currently being overridden by // a higher-priority source. - bool PrefValueInManagedStore(const char* name) const; + bool PrefValueInManagedPlatformStore(const char* name) const; + bool PrefValueInDeviceManagementStore(const char* name) const; bool PrefValueInExtensionStore(const char* name) const; bool PrefValueInUserStore(const char* name) const; @@ -163,6 +164,7 @@ class PrefValueStore : public base::RefCountedThreadSafe { // lifecycle is managed in another thread. typedef Callback1 >::Type AfterRefreshCallback; +<<<<<<< HEAD #ifndef ANDROID // Called as a result of a notification of policy change. Triggers a // reload of managed preferences from policy from a Task on the FILE @@ -170,6 +172,14 @@ class PrefValueStore : public base::RefCountedThreadSafe { // called with the set of preferences changed by the policy refresh. // |callback| is called on the caller's thread as a Task after // RefreshPolicyPrefs has returned. +======= + // Called as a result of a notification of policy change. Triggers a reload of + // managed platform, device management and recommended preferences from policy + // from a Task on the FILE thread. The Task will take ownership of the + // |callback|. |callback| is called with the set of preferences changed by the + // policy refresh. |callback| is called on the caller's thread as a Task + // after RefreshPolicyPrefs has returned. +>>>>>>> chromium.org at r66597 void RefreshPolicyPrefs(AfterRefreshCallback* callback); #endif @@ -180,7 +190,10 @@ class PrefValueStore : public base::RefCountedThreadSafe { protected: // In decreasing order of precedence: - // |managed_prefs| contains all managed (policy) preference values. + // |managed_platform_prefs| contains all managed platform (non-cloud policy) + // preference values. + // |device_management_prefs| contains all device management (cloud policy) + // preference values. // |extension_prefs| contains preference values set by extensions. // |command_line_prefs| contains preference values set by command-line // switches. @@ -192,7 +205,8 @@ class PrefValueStore : public base::RefCountedThreadSafe { // This constructor should only be used internally, or by subclasses in // testing. The usual way to create a PrefValueStore is by creating a // PrefService. - PrefValueStore(PrefStore* managed_prefs, + PrefValueStore(PrefStore* managed_platform_prefs, + PrefStore* device_management_prefs, PrefStore* extension_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, @@ -226,7 +240,8 @@ class PrefValueStore : public base::RefCountedThreadSafe { // that initiated the policy refresh. RefreshPolicyPrefsCompletion takes // ownership of the |callback| object. void RefreshPolicyPrefsCompletion( - PrefStore* new_managed_pref_store, + PrefStore* new_managed_platform_pref_store, + PrefStore* new_device_management_pref_store, PrefStore* new_recommended_pref_store, AfterRefreshCallback* callback); @@ -234,7 +249,8 @@ class PrefValueStore : public base::RefCountedThreadSafe { // RefreshPolicyPrefsOnFileThread takes ownership of the |callback| object. void RefreshPolicyPrefsOnFileThread( BrowserThread::ID calling_thread_id, - PrefStore* new_managed_pref_store, + PrefStore* new_managed_platform_pref_store, + PrefStore* new_device_management_pref_store, PrefStore* new_recommended_pref_store, AfterRefreshCallback* callback); #endif diff --git a/chrome/browser/prefs/pref_value_store_unittest.cc b/chrome/browser/prefs/pref_value_store_unittest.cc index 9cb933d..cbf7ccc 100644 --- a/chrome/browser/prefs/pref_value_store_unittest.cc +++ b/chrome/browser/prefs/pref_value_store_unittest.cc @@ -36,19 +36,26 @@ const char kDefaultPref[] = "default.pref"; } // Potentially expected values of all preferences used in this test program. -namespace enforced_pref { +namespace managed_platform_pref { const std::string kHomepageValue = "http://www.topeka.com"; } +namespace device_management_pref { +const std::string kSearchProviderNameValue = "Chromium"; +const char kHomepageValue[] = "http://www.wandering-around.org"; +} + namespace extension_pref { const char kCurrentThemeIDValue[] = "set by extension"; const char kHomepageValue[] = "http://www.chromium.org"; +const std::string kSearchProviderNameValue = "AreYouFeelingALittleLucky"; } namespace command_line_pref { const char kApplicationLocaleValue[] = "hi-MOM"; const char kCurrentThemeIDValue[] = "zyxwvut"; const char kHomepageValue[] = "http://www.ferretcentral.org"; +const std::string kSearchProviderNameValue = "AreYouFeelingPrettyLucky"; } // The "user" namespace is defined globally in an ARM system header, so we need @@ -59,6 +66,7 @@ const bool kDeleteCacheValue = true; const char kCurrentThemeIDValue[] = "abcdefg"; const char kHomepageValue[] = "http://www.google.com"; const char kApplicationLocaleValue[] = "is-WRONG"; +const std::string kSearchProviderNameValue = "AreYouFeelingVeryLucky"; } namespace recommended_pref { @@ -69,22 +77,29 @@ const bool kRecommendedPrefValue = true; namespace default_pref { const int kDefaultValue = 7; const char kHomepageValue[] = "default homepage"; +const std::string kSearchProviderNameValue = "AreYouFeelingExtraLucky"; } class PrefValueStoreTest : public testing::Test { protected: virtual void SetUp() { // Create dummy user preferences. - enforced_prefs_= CreateEnforcedPrefs(); + managed_platform_prefs_= CreateManagedPlatformPrefs(); + device_management_prefs_ = CreateDeviceManagementPrefs(); extension_prefs_ = CreateExtensionPrefs(); command_line_prefs_ = CreateCommandLinePrefs(); user_prefs_ = CreateUserPrefs(); recommended_prefs_ = CreateRecommendedPrefs(); default_prefs_ = CreateDefaultPrefs(); + std::sort(expected_differing_paths_.begin(), + expected_differing_paths_.end()); + // Create |DummyPrefStore|s. - enforced_pref_store_ = new DummyPrefStore(); - enforced_pref_store_->set_prefs(enforced_prefs_); + managed_platform_pref_store_ = new DummyPrefStore(); + managed_platform_pref_store_->set_prefs(managed_platform_prefs_); + device_management_pref_store_ = new DummyPrefStore(); + device_management_pref_store_->set_prefs(device_management_prefs_); extension_pref_store_ = new DummyPrefStore(); extension_pref_store_->set_prefs(extension_prefs_); command_line_pref_store_ = new DummyPrefStore(); @@ -99,7 +114,8 @@ class PrefValueStoreTest : public testing::Test { // Create a new pref-value-store. pref_value_store_ = new TestingPrefService::TestingPrefValueStore( - enforced_pref_store_, + managed_platform_pref_store_, + device_management_pref_store_, extension_pref_store_, command_line_pref_store_, user_pref_store_, @@ -111,6 +127,9 @@ class PrefValueStoreTest : public testing::Test { Value::TYPE_STRING); pref_value_store_->RegisterPreferenceType(prefs::kCurrentThemeID, Value::TYPE_STRING); + pref_value_store_->RegisterPreferenceType( + prefs::kDefaultSearchProviderName, + Value::TYPE_STRING); pref_value_store_->RegisterPreferenceType(prefs::kDeleteCache, Value::TYPE_BOOLEAN); pref_value_store_->RegisterPreferenceType(prefs::kHomePage, @@ -143,15 +162,31 @@ class PrefValueStoreTest : public testing::Test { user_pref::kCurrentThemeIDValue); user_prefs->SetString(prefs::kApplicationLocale, user_pref::kApplicationLocaleValue); + user_prefs->SetString(prefs::kDefaultSearchProviderName, + user_pref::kSearchProviderNameValue); user_prefs->SetString(prefs::kHomePage, user_pref::kHomepageValue); return user_prefs; } - DictionaryValue* CreateEnforcedPrefs() { - DictionaryValue* enforced_prefs = new DictionaryValue(); - enforced_prefs->SetString(prefs::kHomePage, enforced_pref::kHomepageValue); + DictionaryValue* CreateManagedPlatformPrefs() { + DictionaryValue* managed_platform_prefs = new DictionaryValue(); + managed_platform_prefs->SetString( + prefs::kHomePage, + managed_platform_pref::kHomepageValue); expected_differing_paths_.push_back(prefs::kHomePage); - return enforced_prefs; + return managed_platform_prefs; + } + + DictionaryValue* CreateDeviceManagementPrefs() { + DictionaryValue* device_management_prefs = new DictionaryValue(); + device_management_prefs->SetString( + prefs::kDefaultSearchProviderName, + device_management_pref::kSearchProviderNameValue); + expected_differing_paths_.push_back("default_search_provider"); + expected_differing_paths_.push_back(prefs::kDefaultSearchProviderName); + device_management_prefs->SetString(prefs::kHomePage, + device_management_pref::kHomepageValue); + return device_management_prefs; } DictionaryValue* CreateExtensionPrefs() { @@ -160,6 +195,8 @@ class PrefValueStoreTest : public testing::Test { extension_pref::kCurrentThemeIDValue); extension_prefs->SetString(prefs::kHomePage, extension_pref::kHomepageValue); + extension_prefs->SetString(prefs::kDefaultSearchProviderName, + extension_pref::kSearchProviderNameValue); return extension_prefs; } @@ -171,6 +208,9 @@ class PrefValueStoreTest : public testing::Test { command_line_pref::kApplicationLocaleValue); command_line_prefs->SetString(prefs::kHomePage, command_line_pref::kHomepageValue); + command_line_prefs->SetString( + prefs::kDefaultSearchProviderName, + command_line_pref::kSearchProviderNameValue); return command_line_prefs; } @@ -225,7 +265,8 @@ class PrefValueStoreTest : public testing::Test { scoped_refptr pref_value_store_; // |PrefStore|s are owned by the |PrefValueStore|. - DummyPrefStore* enforced_pref_store_; + DummyPrefStore* managed_platform_pref_store_; + DummyPrefStore* device_management_pref_store_; DummyPrefStore* extension_pref_store_; DummyPrefStore* command_line_pref_store_; DummyPrefStore* user_pref_store_; @@ -239,7 +280,8 @@ class PrefValueStoreTest : public testing::Test { std::vector expected_differing_paths_; // Preferences are owned by the individual |DummyPrefStores|. - DictionaryValue* enforced_prefs_; + DictionaryValue* managed_platform_prefs_; + DictionaryValue* device_management_prefs_; DictionaryValue* extension_prefs_; DictionaryValue* command_line_prefs_; DictionaryValue* user_prefs_; @@ -252,7 +294,7 @@ class PrefValueStoreTest : public testing::Test { }; TEST_F(PrefValueStoreTest, IsReadOnly) { - enforced_pref_store_->set_read_only(true); + managed_platform_pref_store_->set_read_only(true); extension_pref_store_->set_read_only(true); command_line_pref_store_->set_read_only(true); user_pref_store_->set_read_only(true); @@ -267,13 +309,21 @@ TEST_F(PrefValueStoreTest, IsReadOnly) { TEST_F(PrefValueStoreTest, GetValue) { Value* value; - // Test getting an enforced value overwriting a user-defined and + // Test getting a managed platform value overwriting a user-defined and // extension-defined value. value = NULL; ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &value)); std::string actual_str_value; EXPECT_TRUE(value->GetAsString(&actual_str_value)); - EXPECT_EQ(enforced_pref::kHomepageValue, actual_str_value); + EXPECT_EQ(managed_platform_pref::kHomepageValue, actual_str_value); + + // Test getting a managed platform value overwriting a user-defined value. + value = NULL; + ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultSearchProviderName, + &value)); + EXPECT_TRUE(value->GetAsString(&actual_str_value)); + EXPECT_EQ(device_management_pref::kSearchProviderNameValue, + actual_str_value); // Test getting an extension value overwriting a user-defined and // command-line-defined value. @@ -341,7 +391,8 @@ TEST_F(PrefValueStoreTest, GetValueChangedType) { EXPECT_EQ(recommended_pref::kStabilityLaunchCountValue, actual_int_value); // Check falling back multiple times, to a default string. - enforced_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); + managed_platform_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); + device_management_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); extension_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); command_line_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); user_pref_store_->prefs()->SetInteger(prefs::kHomePage, 1); @@ -359,8 +410,13 @@ TEST_F(PrefValueStoreTest, GetValueChangedType) { } TEST_F(PrefValueStoreTest, HasPrefPath) { - // Enforced preference + // Managed Platform preference EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage)); + // Device management preference + EXPECT_TRUE(pref_value_store_->HasPrefPath( + prefs::kDefaultSearchProviderName)); + // Extension preference + EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID)); // User preference EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kDeleteCache)); // Recommended preference @@ -373,10 +429,11 @@ TEST_F(PrefValueStoreTest, HasPrefPath) { TEST_F(PrefValueStoreTest, PrefHasChanged) { // Setup. - const char managed_pref_path[] = "managed_pref"; - pref_value_store_->RegisterPreferenceType(managed_pref_path, + const char managed_platform_pref_path[] = "managed_platform_pref"; + pref_value_store_->RegisterPreferenceType(managed_platform_pref_path, Value::TYPE_STRING); - enforced_pref_store_->prefs()->SetString(managed_pref_path, "managed value"); + managed_platform_pref_store_->prefs()->SetString(managed_platform_pref_path, + "managed value"); const char user_pref_path[] = "user_pref"; pref_value_store_->RegisterPreferenceType(user_pref_path, Value::TYPE_STRING); user_pref_store_->prefs()->SetString(user_pref_path, "user value"); @@ -386,9 +443,9 @@ TEST_F(PrefValueStoreTest, PrefHasChanged) { default_pref_store_->prefs()->SetString(default_pref_path, "default value"); // Check pref controlled by highest-priority store. - EXPECT_TRUE(pref_value_store_->PrefHasChanged(managed_pref_path, + EXPECT_TRUE(pref_value_store_->PrefHasChanged(managed_platform_pref_path, static_cast(0))); - EXPECT_FALSE(pref_value_store_->PrefHasChanged(managed_pref_path, + EXPECT_FALSE(pref_value_store_->PrefHasChanged(managed_platform_pref_path, PrefNotifier::USER_STORE)); // Check pref controlled by user store. @@ -425,8 +482,9 @@ TEST_F(PrefValueStoreTest, SetUserPrefValue) { Value* new_value = NULL; Value* actual_value = NULL; - // Test that enforced values can not be set. - ASSERT_TRUE(pref_value_store_->PrefValueInManagedStore(prefs::kHomePage)); + // Test that managed platform values can not be set. + ASSERT_TRUE(pref_value_store_->PrefValueInManagedPlatformStore( + prefs::kHomePage)); // The Ownership is tranfered to |PrefValueStore|. new_value = Value::CreateStringValue("http://www.youtube.com"); pref_value_store_->SetUserPrefValue(prefs::kHomePage, new_value); @@ -434,10 +492,10 @@ TEST_F(PrefValueStoreTest, SetUserPrefValue) { ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &actual_value)); std::string value_str; actual_value->GetAsString(&value_str); - ASSERT_EQ(enforced_pref::kHomepageValue, value_str); + ASSERT_EQ(managed_platform_pref::kHomepageValue, value_str); // User preferences values can be set - ASSERT_FALSE(pref_value_store_->PrefValueInManagedStore( + ASSERT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kStabilityLaunchCount)); actual_value = NULL; pref_value_store_->GetValue(prefs::kStabilityLaunchCount, &actual_value); @@ -474,48 +532,64 @@ TEST_F(PrefValueStoreTest, SetUserPrefValue) { ASSERT_TRUE(expected_list_value->Equals(actual_value)); } -TEST_F(PrefValueStoreTest, PrefValueInManagedStore) { - // Test an enforced preference. +TEST_F(PrefValueStoreTest, PrefValueInManagedPlatformStore) { + // Test a managed platform preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage)); - EXPECT_TRUE(pref_value_store_->PrefValueInManagedStore(prefs::kHomePage)); + EXPECT_TRUE(pref_value_store_->PrefValueInManagedPlatformStore( + prefs::kHomePage)); + + // Test a device management preference. + ASSERT_TRUE(pref_value_store_->HasPrefPath( + prefs::kDefaultSearchProviderName)); + EXPECT_TRUE(pref_value_store_->PrefValueInDeviceManagementStore( + prefs::kDefaultSearchProviderName)); // Test an extension preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kCurrentThemeID)); // Test a command-line preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kApplicationLocale)); // Test a user preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kStabilityLaunchCount)); // Test a preference from the recommended pref store. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kRecommendedPref)); // Test a preference from the default pref store. ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( prefs::kDefaultPref)); // Test a preference for which the PrefValueStore does not contain a value. ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref)); - EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore(prefs::kMissingPref)); + EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore( + prefs::kMissingPref)); } TEST_F(PrefValueStoreTest, PrefValueInExtensionStore) { - // Test an enforced preference. + // Test a managed platform preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage)); EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(prefs::kHomePage)); EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore( prefs::kHomePage)); + // Test a device management preference. + ASSERT_TRUE(pref_value_store_->HasPrefPath( + prefs::kDefaultSearchProviderName)); + EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore( + prefs::kDefaultSearchProviderName)); + EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore( + prefs::kDefaultSearchProviderName)); + // Test an extension preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID)); EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore( @@ -567,16 +641,24 @@ TEST_F(PrefValueStoreTest, DetectProxyConfigurationConflict) { // Create conflicting proxy settings in the managed and command-line // preference stores. command_line_prefs_->SetBoolean(prefs::kProxyAutoDetect, false); - enforced_prefs_->SetBoolean(prefs::kProxyAutoDetect, true); + managed_platform_prefs_->SetBoolean(prefs::kProxyAutoDetect, true); ASSERT_TRUE(pref_value_store_->HasPolicyConflictingUserProxySettings()); } TEST_F(PrefValueStoreTest, PrefValueInUserStore) { - // Test an enforced preference. + // Test a managed platform preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage)); EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(prefs::kHomePage)); EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kHomePage)); + // Test a device management preference. + ASSERT_TRUE(pref_value_store_->HasPrefPath( + prefs::kDefaultSearchProviderName)); + EXPECT_TRUE(pref_value_store_->PrefValueInUserStore( + prefs::kDefaultSearchProviderName)); + EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore( + prefs::kDefaultSearchProviderName)); + // Test an extension preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID)); EXPECT_TRUE(pref_value_store_->PrefValueInUserStore( @@ -617,10 +699,16 @@ TEST_F(PrefValueStoreTest, PrefValueInUserStore) { } TEST_F(PrefValueStoreTest, PrefValueFromDefaultStore) { - // Test an enforced preference. + // Test a managed platform preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage)); EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(prefs::kHomePage)); + // Test a device management preference. + ASSERT_TRUE(pref_value_store_->HasPrefPath( + prefs::kDefaultSearchProviderName)); + EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( + prefs::kDefaultSearchProviderName)); + // Test an extension preference. ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID)); EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( @@ -653,10 +741,11 @@ TEST_F(PrefValueStoreTest, PrefValueFromDefaultStore) { } TEST_F(PrefValueStoreTest, TestPolicyRefresh) { - // pref_value_store_ is initialized by PrefValueStoreTest to have values - // in both it's managed and recommended store. By replacing them with - // dummy stores, all of the paths of the prefs originally managed and - // recommended stores should change. + // pref_value_store_ is initialized by PrefValueStoreTest to have values in + // the managed platform, device management and recommended stores. By + // replacing them with dummy stores, all of the paths of the prefs originally + // in the managed platform, device management and recommended stores should + // change. MockPolicyRefreshCallback callback; EXPECT_CALL(callback, DoCallback(_)).Times(0); BrowserThread::PostTask( @@ -672,23 +761,24 @@ TEST_F(PrefValueStoreTest, TestPolicyRefresh) { } TEST_F(PrefValueStoreTest, TestRefreshPolicyPrefsCompletion) { - // Test changed preferences in managed store and removed - // preferences in the recommended store. In addition - // to "homepage", the other prefs that are set by default in - // the test class are removed by the DummyStore - scoped_ptr new_managed_store(new DummyPrefStore()); + // Test changed preferences in the managed platform store and removed + // preferences in the recommended store. In addition to "homepage", the other + // prefs that are set by default in the test class are removed by the + // DummyStore. + scoped_ptr new_managed_platform_store(new DummyPrefStore()); DictionaryValue* dict = new DictionaryValue(); dict->SetString("homepage", "some other changed homepage"); - new_managed_store->set_prefs(dict); + new_managed_platform_store->set_prefs(dict); MockPolicyRefreshCallback callback; EXPECT_CALL(callback, DoCallback(expected_differing_paths_)).Times(1); pref_value_store_->RefreshPolicyPrefsCompletion( - new_managed_store.release(), + new_managed_platform_store.release(), + new DummyPrefStore(), new DummyPrefStore(), NewCallback(&callback, &MockPolicyRefreshCallback::DoCallback)); - // Test properties that have been removed from the managed store. + // Test properties that have been removed from the managed platform store. // Homepage is still set in managed prefs. expected_differing_paths_.clear(); expected_differing_paths_.push_back(std::string("homepage")); @@ -697,9 +787,27 @@ TEST_F(PrefValueStoreTest, TestRefreshPolicyPrefsCompletion) { pref_value_store_->RefreshPolicyPrefsCompletion( new DummyPrefStore(), new DummyPrefStore(), + new DummyPrefStore(), NewCallback(&callback2, &MockPolicyRefreshCallback::DoCallback)); + // Test properties that are added to the device management store. + expected_differing_paths_.clear(); + expected_differing_paths_.push_back(std::string("homepage")); + scoped_ptr new_device_management_store( + new DummyPrefStore()); + dict = new DictionaryValue(); + dict->SetString("homepage", "some other changed homepage"); + new_device_management_store->set_prefs(dict); + MockPolicyRefreshCallback callback3; + EXPECT_CALL(callback3, DoCallback(expected_differing_paths_)).Times(1); + pref_value_store_->RefreshPolicyPrefsCompletion( + new DummyPrefStore(), + new_device_management_store.release(), + new DummyPrefStore(), + NewCallback(&callback3, + &MockPolicyRefreshCallback::DoCallback)); + // Test properties that are added to the recommended store. scoped_ptr new_recommended_store(new DummyPrefStore()); dict = new DictionaryValue(); @@ -707,29 +815,31 @@ TEST_F(PrefValueStoreTest, TestRefreshPolicyPrefsCompletion) { new_recommended_store->set_prefs(dict); expected_differing_paths_.clear(); expected_differing_paths_.push_back(std::string("homepage")); - MockPolicyRefreshCallback callback3; - EXPECT_CALL(callback3, DoCallback(expected_differing_paths_)).Times(1); + MockPolicyRefreshCallback callback4; + EXPECT_CALL(callback4, DoCallback(expected_differing_paths_)).Times(1); pref_value_store_->RefreshPolicyPrefsCompletion( new DummyPrefStore(), + new DummyPrefStore(), new_recommended_store.release(), - NewCallback(&callback3, + NewCallback(&callback4, &MockPolicyRefreshCallback::DoCallback)); // Test adding a multi-key path. - new_managed_store.reset(new DummyPrefStore()); + new_managed_platform_store.reset(new DummyPrefStore()); dict = new DictionaryValue(); dict->SetString("segment1.segment2", "value"); - new_managed_store->set_prefs(dict); + new_managed_platform_store->set_prefs(dict); expected_differing_paths_.clear(); expected_differing_paths_.push_back(std::string("homepage")); expected_differing_paths_.push_back(std::string("segment1")); expected_differing_paths_.push_back(std::string("segment1.segment2")); - MockPolicyRefreshCallback callback4; - EXPECT_CALL(callback4, DoCallback(expected_differing_paths_)).Times(1); + MockPolicyRefreshCallback callback5; + EXPECT_CALL(callback5, DoCallback(expected_differing_paths_)).Times(1); pref_value_store_->RefreshPolicyPrefsCompletion( - new_managed_store.release(), + new_managed_platform_store.release(), new DummyPrefStore(), - NewCallback(&callback4, + new DummyPrefStore(), + NewCallback(&callback5, &MockPolicyRefreshCallback::DoCallback)); } diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc index 38e89b6..f4f2caf 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc @@ -10,7 +10,6 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/dom_ui/dom_ui_util.h" @@ -27,10 +26,11 @@ #include "chrome/browser/service/service_process_control.h" #include "chrome/browser/service/service_process_control_manager.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #if defined(TOOLKIT_VIEWS) #include "chrome/browser/views/browser_dialogs.h" #endif // defined(TOOLKIT_GTK) -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" @@ -202,12 +202,12 @@ void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user, // Start the authenticator. authenticator_.reset( - new GaiaAuthenticator2(this, GaiaConstants::kChromeSource, - profile_->GetRequestContext())); + new GaiaAuthFetcher(this, GaiaConstants::kChromeSource, + profile_->GetRequestContext())); authenticator_->StartClientLogin(user, password, GaiaConstants::kCloudPrintService, "", captcha, - GaiaAuthenticator2::HostedAccountsAllowed); + GaiaAuthFetcher::HostedAccountsAllowed); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h index c6f71ea..a5ccd97 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h @@ -12,11 +12,11 @@ #include "base/time.h" #include "chrome/browser/dom_ui/html_dialog_ui.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "gfx/native_widget_types.h" #include "grit/generated_resources.h" -class GaiaAuthenticator2; +class GaiaAuthFetcher; class CloudPrintServiceProcessHelper; class CloudPrintSetupMessageHandler; class ServiceProcessControl; @@ -114,7 +114,7 @@ class CloudPrintSetupFlow : public HtmlDialogUIDelegate, Profile* profile_; // Fetcher to obtain the Chromoting Directory token. - scoped_ptr authenticator_; + scoped_ptr authenticator_; std::string login_; std::string lsid_; diff --git a/chrome/browser/printing/print_preview_tab_controller.cc b/chrome/browser/printing/print_preview_tab_controller.cc new file mode 100644 index 0000000..0396583 --- /dev/null +++ b/chrome/browser/printing/print_preview_tab_controller.cc @@ -0,0 +1,194 @@ +// 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/printing/print_preview_tab_controller.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/url_constants.h" + +namespace printing { + +// static +PrintPreviewTabController* PrintPreviewTabController::GetInstance() { + if (!g_browser_process) + return NULL; + return g_browser_process->print_preview_tab_controller(); +} + +PrintPreviewTabController::PrintPreviewTabController() + : waiting_for_new_preview_page_(false) { +} + +PrintPreviewTabController::~PrintPreviewTabController() { + preview_tab_map_.clear(); +} + +TabContents* PrintPreviewTabController::GetOrCreatePreviewTab( + TabContents* initiator_tab, int browser_window_id ) { + DCHECK(initiator_tab); + + if (IsPrintPreviewTab(initiator_tab)) + return initiator_tab; + + // Get the print preview tab for |initiator_tab|. + TabContents* preview_tab = GetPrintPreviewForTab(initiator_tab); + if (preview_tab) { + // Show current preview tab. + preview_tab->Activate(); + return preview_tab; + } + return CreatePrintPreviewTab(initiator_tab, browser_window_id); +} + +bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) { + const GURL& url = tab->GetURL(); + return (url.SchemeIs(chrome::kChromeUIScheme) && + url.host() == chrome::kChromeUIPrintHost); +} + +TabContents* PrintPreviewTabController::GetInitiatorTab( + TabContents* preview_tab) { + PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); + if (it != preview_tab_map_.end()) + return preview_tab_map_[preview_tab]; + return NULL; +} + +TabContents* PrintPreviewTabController::GetPrintPreviewForTab( + TabContents* tab) { + PrintPreviewTabMap::iterator it = preview_tab_map_.find(tab); + if (it != preview_tab_map_.end()) + return tab; + + for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) { + if (it->second == tab) + return it->first; + } + return NULL; +} + +void PrintPreviewTabController::AddObservers(TabContents* tab) { + registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, + Source(tab)); + registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, + Source(&tab->controller())); +} + +void PrintPreviewTabController::RemoveObservers(TabContents* tab) { + registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, + Source(tab)); + registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED, + Source(&tab->controller())); +} + +TabContents* PrintPreviewTabController::CreatePrintPreviewTab( + TabContents* initiator_tab, int browser_window_id) { + Browser* current_browser = BrowserList::FindBrowserWithID(browser_window_id); + // Add a new tab next to initiator tab. + browser::NavigateParams params(current_browser, + GURL(chrome::kChromeUIPrintURL), + PageTransition::LINK); + params.disposition = NEW_FOREGROUND_TAB; + params.tabstrip_index = current_browser->tabstrip_model()-> + GetIndexOfTabContents(initiator_tab) + 1; + browser::Navigate(¶ms); + TabContents* preview_tab = params.target_contents; + preview_tab->Activate(); + + // Add an entry to the map. + preview_tab_map_[preview_tab] = initiator_tab; + waiting_for_new_preview_page_ = true; + + AddObservers(initiator_tab); + AddObservers(preview_tab); + + return preview_tab; +} + +void PrintPreviewTabController::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + TabContents* initiator_tab = NULL; + TabContents* preview_tab = NULL; + TabContents* source_tab = NULL; + NavigationController::LoadCommittedDetails* detail_info = NULL; + + switch (type.value) { + case NotificationType::TAB_CONTENTS_DESTROYED: { + source_tab = Source(source).ptr(); + break; + } + case NotificationType::NAV_ENTRY_COMMITTED: { + NavigationController* controller = + Source(source).ptr(); + source_tab = controller->tab_contents(); + detail_info = + Details(details).ptr(); + break; + } + default: { + NOTREACHED(); + return; + } + } + + DCHECK(source_tab); + preview_tab = GetPrintPreviewForTab(source_tab); + + // |source_tab| is preview tab. + if (preview_tab == source_tab) + initiator_tab = GetInitiatorTab(source_tab); + else + initiator_tab = source_tab; + + if (detail_info) { + PageTransition::Type transition_type = + detail_info->entry->transition_type(); + NavigationType::Type nav_type = detail_info->type; + + // Don't update/erase the map entry if the page has not changed. + if (transition_type == PageTransition::RELOAD || + nav_type == NavigationType::SAME_PAGE) { + return; + } + + // New |preview_tab| is created. Don't update/erase map entry. + if (waiting_for_new_preview_page_ && + transition_type == PageTransition::LINK && + nav_type == NavigationType::NEW_PAGE && + source_tab == preview_tab) { + waiting_for_new_preview_page_ = false; + return; + } + + // User navigated to a preview tab using forward/back button. + if (IsPrintPreviewTab(source_tab) && + transition_type == PageTransition::FORWARD_BACK && + nav_type == NavigationType::EXISTING_PAGE) { + return; + } + } + + // If |source_tab| is |initiator_tab|, update the map entry. + if (source_tab == initiator_tab) { + preview_tab_map_[preview_tab] = NULL; + } + + // If |source_tab| is |preview_tab|, erase the map entry. + if (source_tab == preview_tab) { + preview_tab_map_.erase(preview_tab); + RemoveObservers(preview_tab); + } + + if (initiator_tab) + RemoveObservers(initiator_tab); +} + +} // namespace printing diff --git a/chrome/browser/printing/print_preview_tab_controller.h b/chrome/browser/printing/print_preview_tab_controller.h new file mode 100644 index 0000000..6eec3f4 --- /dev/null +++ b/chrome/browser/printing/print_preview_tab_controller.h @@ -0,0 +1,87 @@ +// 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_PRINTING_PRINT_PREVIEW_TAB_CONTROLLER_H_ +#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_TAB_CONTROLLER_H_ +#pragma once + +#include + +#include "base/ref_counted.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" + +class Browser; +class TabContents; + +namespace printing { + +// For print preview, a print preview (PP) tab is linked with the initiator tab +// that initiated the printing operation. If the tab initiates a second +// printing operation while the first print preview tab is still open, that PP +// tab is focused/activated. There may be more than one PP tab open. There is a +// 1:1 relationship between PP tabs and initiating tabs. This class manages PP +// tabs and initiator tabs. +class PrintPreviewTabController + : public base::RefCounted, + public NotificationObserver { + public: + static PrintPreviewTabController* GetInstance(); + + PrintPreviewTabController(); + + virtual ~PrintPreviewTabController(); + + // Get/Create the print preview tab for |initiator_tab|. + // |browser_window_id| is the browser window containing |initiator_tab|. + TabContents* GetOrCreatePreviewTab( + TabContents* initiator_tab, int browser_window_id); + + // Notification observer implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + friend class base::RefCounted; + + // Returns true if |tab| is a print preview tab. + bool IsPrintPreviewTab(TabContents* tab); + + // Returns initiator tab for |preview_tab|. + // Returns NULL if no initiator tab exists for |preview_tab|. + TabContents* GetInitiatorTab(TabContents* preview_tab); + + // Returns preview tab for |tab|. + // Returns |tab| if |tab| is a preview tab. + // Returns NULL if no preview tab exists for |tab|. + TabContents* GetPrintPreviewForTab(TabContents* tab); + + // Creates a new print preview tab. + TabContents* CreatePrintPreviewTab( + TabContents* initiator_tab, int browser_window_id); + + // Adds/Removes observers for notifications from |tab|. + void AddObservers(TabContents* tab); + void RemoveObservers(TabContents* tab); + + // 1:1 relationship between initiator tab and print preview tab. + // Key: Preview tab. + // Value: Initiator tab. + typedef std::map PrintPreviewTabMap; + PrintPreviewTabMap preview_tab_map_; + + // A registrar for listening notifications. + NotificationRegistrar registrar_; + + // True if the controller is waiting for a new preview tab via + // NavigationType::NEW_PAGE. + bool waiting_for_new_preview_page_; + + DISALLOW_COPY_AND_ASSIGN(PrintPreviewTabController); +}; + +} // namespace printing + +#endif // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_TAB_CONTROLLER_H_ diff --git a/chrome/browser/printing/print_preview_tab_controller_unittest.cc b/chrome/browser/printing/print_preview_tab_controller_unittest.cc new file mode 100644 index 0000000..40b630a --- /dev/null +++ b/chrome/browser/printing/print_preview_tab_controller_unittest.cc @@ -0,0 +1,114 @@ +// 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/printing/print_preview_tab_controller.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/test/browser_with_test_window_test.h" +#include "chrome/test/testing_profile.h" + +typedef BrowserWithTestWindowTest PrintPreviewTabControllerTest; + +// Create/Get a preview tab for initiator tab. +TEST_F(PrintPreviewTabControllerTest, GetOrCreatePreviewTab) { + ASSERT_TRUE(browser()); + BrowserList::SetLastActive(browser()); + ASSERT_TRUE(BrowserList::GetLastActive()); + + // Lets start with one window with one tab. + EXPECT_EQ(1u, BrowserList::size()); + EXPECT_EQ(0, browser()->tab_count()); + browser()->NewTab(); + EXPECT_EQ(1, browser()->tab_count()); + + // Create a reference to initiator tab contents. + TabContents* initiator_tab = browser()->GetSelectedTabContents(); + + printing::PrintPreviewTabController* tab_controller = + new printing::PrintPreviewTabController(); + ASSERT_TRUE(tab_controller); + + // Get the preview tab for initiator tab. + TabContents* preview_tab = tab_controller->GetOrCreatePreviewTab( + initiator_tab, initiator_tab->controller().window_id().id()); + + // New print preview tab is created. Current focus is on preview tab. + EXPECT_EQ(2, browser()->tab_count()); + EXPECT_NE(initiator_tab, preview_tab); + + // Activate initiator_tab. + initiator_tab->Activate(); + + // Get the print preview tab for initiator tab. + TabContents* new_preview_tab = tab_controller->GetOrCreatePreviewTab( + initiator_tab, initiator_tab->controller().window_id().id()); + + // Preview tab already exists. Tab count remains the same. + EXPECT_EQ(2, browser()->tab_count()); + + // 1:1 relationship between initiator and preview tab. + EXPECT_EQ(new_preview_tab, preview_tab); +} + +// To show multiple print preview tabs exist in the same browser for +// different initiator tabs. If preview tab already exists for an initiator, it +// gets focused. +TEST_F(PrintPreviewTabControllerTest, MultiplePreviewTabs) { + ASSERT_TRUE(browser()); + BrowserList::SetLastActive(browser()); + ASSERT_TRUE(BrowserList::GetLastActive()); + + // Lets start with one window and two tabs. + EXPECT_EQ(1u, BrowserList::size()); + EXPECT_EQ(0, browser()->tab_count()); + + browser()->NewTab(); + TabContents* tab_contents_1 = browser()->GetSelectedTabContents(); + ASSERT_TRUE(tab_contents_1); + + browser()->NewTab(); + TabContents* tab_contents_2 = browser()->GetSelectedTabContents(); + ASSERT_TRUE(tab_contents_2); + EXPECT_EQ(2, browser()->tab_count()); + + printing::PrintPreviewTabController* tab_controller = + new printing::PrintPreviewTabController(); + ASSERT_TRUE(tab_controller); + + // Create preview tab for |tab_contents_1| + TabContents* preview_tab_1 = tab_controller->GetOrCreatePreviewTab( + tab_contents_1, tab_contents_1->controller().window_id().id()); + + EXPECT_NE(tab_contents_1, preview_tab_1); + EXPECT_EQ(3, browser()->tab_count()); + + // Create preview tab for |tab_contents_2| + TabContents* preview_tab_2 = tab_controller->GetOrCreatePreviewTab( + tab_contents_2, tab_contents_2->controller().window_id().id()); + + EXPECT_NE(tab_contents_2, preview_tab_2); + // 2 initiator tab and 2 preview tabs exist in the same browser. + EXPECT_EQ(4, browser()->tab_count()); + + TabStripModel* model = browser()->tabstrip_model(); + ASSERT_TRUE(model); + + int preview_tab_1_index = model->GetIndexOfTabContents(preview_tab_1); + int preview_tab_2_index = model->GetIndexOfTabContents(preview_tab_2); + + EXPECT_NE(-1, preview_tab_1_index); + EXPECT_NE(-1, preview_tab_2_index); + // Current tab is |preview_tab_2|. + EXPECT_EQ(preview_tab_2_index, browser()->selected_index()); + + // Activate |tab_contents_1| tab. + tab_contents_1->Activate(); + + // When we get the preview tab for |tab_contents_1|, + // |preview_tab_1| is activated and focused. + tab_controller->GetOrCreatePreviewTab( + tab_contents_1, tab_contents_1->controller().window_id().id()); + EXPECT_EQ(preview_tab_1_index, browser()->selected_index()); +} diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc index fe537d2..fa66e17 100644 --- a/chrome/browser/process_singleton_linux.cc +++ b/chrome/browser/process_singleton_linux.cc @@ -74,7 +74,6 @@ #include "base/utf_string_conversions.h" #include "base/time.h" #include "base/timer.h" -#include "chrome/browser/browser_init.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #if defined(TOOLKIT_GTK) @@ -83,6 +82,7 @@ #include "chrome/browser/io_thread.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" +#include "chrome/browser/ui/browser_init.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/process_singleton_linux_uitest.cc b/chrome/browser/process_singleton_linux_uitest.cc index c9f72de..f1ad59c 100644 --- a/chrome/browser/process_singleton_linux_uitest.cc +++ b/chrome/browser/process_singleton_linux_uitest.cc @@ -16,11 +16,11 @@ #include "base/string_util.h" #include "base/thread.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "chrome/test/chrome_process_util.h" #include "chrome/test/ui/ui_test.h" #include "net/base/net_util.h" diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc index 7b56819..875c6c2 100644 --- a/chrome/browser/process_singleton_win.cc +++ b/chrome/browser/process_singleton_win.cc @@ -13,12 +13,12 @@ #include "base/process_util.h" #include "base/scoped_handle.h" #include "base/win_util.h" -#include "chrome/browser/browser_init.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extensions_startup.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" +#include "chrome/browser/ui/browser_init.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index bc5ba44..adf5885 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -17,9 +17,9 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/chrome_blob_storage_context.h" #include "chrome/browser/download/download_manager.h" -#include "chrome/browser/file_system/file_system_host_context.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/file_system/browser_file_system_context.h" #include "chrome/browser/find_bar_state.h" #include "chrome/browser/in_process_webkit/webkit_context.h" #include "chrome/browser/net/chrome_url_request_context.h" @@ -96,6 +96,14 @@ void Profile::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kCurrentThemeDisplayProperties); prefs->RegisterBooleanPref(prefs::kDisableExtensions, false); prefs->RegisterStringPref(prefs::kSelectFileLastDirectory, ""); +#if defined(OS_CHROMEOS) + // TODO(dilmah): For OS_CHROMEOS we maintain kApplicationLocale in both + // local state and user's profile. For other platforms we maintain + // kApplicationLocale only in local state. + // In the future we may want to maintain kApplicationLocale + // in user's profile for other platforms as well. + prefs->RegisterStringPref(prefs::kApplicationLocale, ""); +#endif } // static @@ -204,7 +212,7 @@ class OffTheRecordProfileImpl : public Profile, return GetOriginalProfile()->GetExtensionsService(); } - virtual BackgroundContentsService* GetBackgroundContentsService() { + virtual BackgroundContentsService* GetBackgroundContentsService() const { return background_contents_service_.get(); } @@ -323,12 +331,12 @@ class OffTheRecordProfileImpl : public Profile, return NULL; } - virtual FileSystemHostContext* GetFileSystemHostContext() { - if (!file_system_host_context_) - file_system_host_context_ = new FileSystemHostContext( + virtual BrowserFileSystemContext* GetFileSystemContext() { + if (!browser_file_system_context_) + browser_file_system_context_ = new BrowserFileSystemContext( GetPath(), IsOffTheRecord()); - DCHECK(file_system_host_context_.get()); - return file_system_host_context_.get(); + DCHECK(browser_file_system_context_.get()); + return browser_file_system_context_.get(); } virtual void InitThemes() { @@ -573,6 +581,10 @@ class OffTheRecordProfileImpl : public Profile, return profile_->GetExtensionInfoMap(); } + virtual PromoCounter* GetInstantPromoCounter() { + return NULL; + } + private: NotificationRegistrar registrar_; @@ -632,7 +644,7 @@ class OffTheRecordProfileImpl : public Profile, scoped_refptr blob_storage_context_; // The file_system context for this profile. - scoped_refptr file_system_host_context_; + scoped_refptr browser_file_system_context_; DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl); }; diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index aac3f02..f2accbf 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -54,7 +54,7 @@ class ExtensionProcessManager; class ExtensionsService; class FaviconService; class FilePath; -class FileSystemHostContext; +class BrowserFileSystemContext; class FindBarState; class GeolocationContentSettingsMap; class GeolocationPermissionContext; @@ -68,6 +68,7 @@ class PersonalDataManager; class PinnedTabService; class PrefService; class ExtensionInfoMap; +class PromoCounter; class ProfileSyncService; class ProfileSyncFactory; class SessionService; @@ -287,8 +288,10 @@ class Profile { // Returns the PersonalDataManager associated with this profile. virtual PersonalDataManager* GetPersonalDataManager() = 0; - // Returns the HTML5 FileSystemHostContext assigned to this profile. - virtual FileSystemHostContext* GetFileSystemHostContext() = 0; + // Returns the FileSystemContext associated to this profile. The context + // is lazily created the first time this method is called. This is owned + // by the profile. + virtual BrowserFileSystemContext* GetFileSystemContext() = 0; // Returns the BrowserSignin object assigned to this profile. virtual BrowserSignin* GetBrowserSignin() = 0; @@ -434,7 +437,7 @@ class Profile { virtual DesktopNotificationService* GetDesktopNotificationService() = 0; // Returns the service that manages BackgroundContents for this profile. - virtual BackgroundContentsService* GetBackgroundContentsService() = 0; + virtual BackgroundContentsService* GetBackgroundContentsService() const = 0; // Returns the StatusTray, which provides an API for displaying status icons // in the system status tray. Returns NULL if status icons are not supported @@ -466,6 +469,9 @@ class Profile { // Returns the IO-thread-accessible profile data for this profile. virtual ExtensionInfoMap* GetExtensionInfoMap() = 0; + // Returns the PromoCounter for Instant, or NULL if not applicable. + virtual PromoCounter* GetInstantPromoCounter() = 0; + #if defined(OS_CHROMEOS) // Returns ChromeOS's ProxyConfigServiceImpl, creating if not yet created. virtual chromeos::ProxyConfigServiceImpl* diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index 649ef1c..02f1a2e 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -38,7 +38,7 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/favicon_service.h" -#include "chrome/browser/file_system/file_system_host_context.h" +#include "chrome/browser/file_system/browser_file_system_context.h" #include "chrome/browser/find_bar_state.h" #include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/geolocation/geolocation_permission_context.h" @@ -46,6 +46,7 @@ #include "chrome/browser/history/top_sites.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/host_zoom_map.h" +#include "chrome/browser/instant/instant_controller.h" #include "chrome/browser/in_process_webkit/webkit_context.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/gaia/token_service.h" @@ -92,7 +93,9 @@ #endif #if defined(OS_WIN) +#include "chrome/browser/instant/promo_counter.h" #include "chrome/browser/password_manager/password_store_win.h" +#include "chrome/installer/util/install_util.h" #elif defined(OS_MACOSX) #include "chrome/browser/keychain_mac.h" #include "chrome/browser/password_manager/password_store_mac.h" @@ -255,6 +258,9 @@ ProfileImpl::ProfileImpl(const FilePath& path) start_time_(Time::Now()), spellcheck_host_(NULL), spellcheck_host_ready_(false), +#if defined(OS_WIN) + checked_instant_promo_(false), +#endif shutdown_session_service_(false) { DCHECK(!path.empty()) << "Using an empty path will attempt to write " << "profile files to the root directory!"; @@ -293,15 +299,21 @@ ProfileImpl::ProfileImpl(const FilePath& path) // for a spec on where cache files go. The net effect for most systems is we // use ~/.cache/chromium/ for Chromium and ~/.cache/google-chrome/ for // official builds. + // If we're using a different user-data-dir, though, fall through + // to the "normal" cache directory (a subdirectory of that). + // TODO(evan): all of this logic belongs in path_service; refactor and remove + // this IsOverriden business. + if (!PathService::IsOverridden(chrome::DIR_USER_DATA)) { #if defined(GOOGLE_CHROME_BUILD) - const char kCacheDir[] = "google-chrome"; + const char kCacheDir[] = "google-chrome"; #else - const char kCacheDir[] = "chromium"; + const char kCacheDir[] = "chromium"; #endif - PathService::Get(base::DIR_USER_CACHE, &base_cache_path_); - base_cache_path_ = base_cache_path_.Append(kCacheDir); - if (!file_util::PathExists(base_cache_path_)) - file_util::CreateDirectory(base_cache_path_); + PathService::Get(base::DIR_USER_CACHE, &base_cache_path_); + base_cache_path_ = base_cache_path_.Append(kCacheDir); + if (!file_util::PathExists(base_cache_path_)) + file_util::CreateDirectory(base_cache_path_); + } #endif if (base_cache_path_.empty()) base_cache_path_ = path_; @@ -342,6 +354,8 @@ ProfileImpl::ProfileImpl(const FilePath& path) // Log the profile size after a reasonable startup delay. BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, new ProfileSizeTask(path_), 112000); + + InstantController::RecordMetrics(this); } void ProfileImpl::InitExtensions() { @@ -620,7 +634,7 @@ ExtensionsService* ProfileImpl::GetExtensionsService() { return extensions_service_.get(); } -BackgroundContentsService* ProfileImpl::GetBackgroundContentsService() { +BackgroundContentsService* ProfileImpl::GetBackgroundContentsService() const { return background_contents_service_.get(); } @@ -1010,12 +1024,12 @@ PersonalDataManager* ProfileImpl::GetPersonalDataManager() { return personal_data_manager_.get(); } -FileSystemHostContext* ProfileImpl::GetFileSystemHostContext() { - if (!file_system_host_context_.get()) - file_system_host_context_ = new FileSystemHostContext( +BrowserFileSystemContext* ProfileImpl::GetFileSystemContext() { + if (!browser_file_system_context_.get()) + browser_file_system_context_ = new BrowserFileSystemContext( GetPath(), IsOffTheRecord()); - DCHECK(file_system_host_context_.get()); - return file_system_host_context_.get(); + DCHECK(browser_file_system_context_.get()); + return browser_file_system_context_.get(); } void ProfileImpl::InitThemes() { @@ -1297,6 +1311,28 @@ ExtensionInfoMap* ProfileImpl::GetExtensionInfoMap() { return extension_info_map_.get(); } +PromoCounter* ProfileImpl::GetInstantPromoCounter() { +#if defined(OS_WIN) + // TODO: enable this when we're ready to turn on the promo. + /* + if (!checked_instant_promo_) { + checked_instant_promo_ = true; + PrefService* prefs = GetPrefs(); + if (!prefs->GetBoolean(prefs::kInstantEnabledOnce) && + !InstantController::IsEnabled(this) && + InstallUtil::IsChromeSxSProcess()) { + DCHECK(!instant_promo_counter_.get()); + instant_promo_counter_.reset( + new PromoCounter(this, prefs::kInstantPromo, "Instant.Promo", 3, 3)); + } + } + */ + return instant_promo_counter_.get(); +#else + return NULL; +#endif +} + #if defined(OS_CHROMEOS) chromeos::ProxyConfigServiceImpl* ProfileImpl::GetChromeOSProxyConfigServiceImpl() { diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h index 9834fc1..fdae9e2 100644 --- a/chrome/browser/profile_impl.h +++ b/chrome/browser/profile_impl.h @@ -70,7 +70,7 @@ class ProfileImpl : public Profile, virtual TemplateURLFetcher* GetTemplateURLFetcher(); virtual DownloadManager* GetDownloadManager(); virtual PersonalDataManager* GetPersonalDataManager(); - virtual FileSystemHostContext* GetFileSystemHostContext(); + virtual BrowserFileSystemContext* GetFileSystemContext(); virtual void InitThemes(); virtual void SetTheme(const Extension* extension); virtual void SetNativeTheme(); @@ -105,7 +105,7 @@ class ProfileImpl : public Profile, virtual void ReinitializeSpellCheckHost(bool force); virtual WebKitContext* GetWebKitContext(); virtual DesktopNotificationService* GetDesktopNotificationService(); - virtual BackgroundContentsService* GetBackgroundContentsService(); + virtual BackgroundContentsService* GetBackgroundContentsService() const; virtual StatusTray* GetStatusTray(); virtual void MarkAsCleanShutdown(); virtual void InitExtensions(); @@ -122,6 +122,7 @@ class ProfileImpl : public Profile, void InitCloudPrintProxyService(); virtual ChromeBlobStorageContext* GetBlobStorageContext(); virtual ExtensionInfoMap* GetExtensionInfoMap(); + virtual PromoCounter* GetInstantPromoCounter(); virtual BrowserSignin* GetBrowserSignin(); #if defined(OS_CHROMEOS) @@ -221,7 +222,7 @@ class ProfileImpl : public Profile, scoped_ptr status_tray_; scoped_refptr personal_data_manager_; scoped_ptr pinned_tab_service_; - scoped_refptr file_system_host_context_; + scoped_refptr browser_file_system_context_; scoped_ptr browser_signin_; bool history_service_created_; bool favicon_service_created_; @@ -247,6 +248,11 @@ class ProfileImpl : public Profile, // finished. bool spellcheck_host_ready_; +#if defined(OS_WIN) + bool checked_instant_promo_; + scoped_ptr instant_promo_counter_; +#endif + // Set to true when ShutdownSessionService is invoked. If true // GetSessionService won't recreate the SessionService. bool shutdown_session_service_; diff --git a/chrome/browser/profile_manager.cc b/chrome/browser/profile_manager.cc index e6dbb7d..2b5048a 100644 --- a/chrome/browser/profile_manager.cc +++ b/chrome/browser/profile_manager.cc @@ -10,12 +10,12 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/string_util.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/remoting/remoting_setup_flow.cc b/chrome/browser/remoting/remoting_setup_flow.cc index fc50e8d..a7975bc 100644 --- a/chrome/browser/remoting/remoting_setup_flow.cc +++ b/chrome/browser/remoting/remoting_setup_flow.cc @@ -10,8 +10,6 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/dom_ui/dom_ui_util.h" #include "chrome/browser/platform_util.h" @@ -23,7 +21,9 @@ #include "chrome/browser/service/service_process_control.h" #include "chrome/browser/service/service_process_control_manager.h" #include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" @@ -248,12 +248,12 @@ void RemotingSetupFlow::OnUserSubmittedAuth(const std::string& user, // Start the authenticator. authenticator_.reset( - new GaiaAuthenticator2(this, GaiaConstants::kChromeSource, - profile_->GetRequestContext())); + new GaiaAuthFetcher(this, GaiaConstants::kChromeSource, + profile_->GetRequestContext())); authenticator_->StartClientLogin(user, password, GaiaConstants::kRemotingService, "", captcha, - GaiaAuthenticator2::HostedAccountsAllowed); + GaiaAuthFetcher::HostedAccountsAllowed); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/remoting/remoting_setup_flow.h b/chrome/browser/remoting/remoting_setup_flow.h index c2e88f8..fb92715 100644 --- a/chrome/browser/remoting/remoting_setup_flow.h +++ b/chrome/browser/remoting/remoting_setup_flow.h @@ -12,11 +12,11 @@ #include "base/time.h" #include "chrome/browser/dom_ui/html_dialog_ui.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" -#include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "gfx/native_widget_types.h" #include "grit/generated_resources.h" -class GaiaAuthenticator2; +class GaiaAuthFetcher; class RemotingServiceProcessHelper; class RemotingSetupMessageHandler; class ServiceProcessControl; @@ -112,7 +112,7 @@ class RemotingSetupFlow : public HtmlDialogUIDelegate, Profile* profile_; // Fetcher to obtain the Chromoting Directory token. - scoped_ptr authenticator_; + scoped_ptr authenticator_; std::string login_; std::string remoting_token_; std::string sync_token_; diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc index 4c83384..5bfc77e 100644 --- a/chrome/browser/renderer_host/audio_renderer_host.cc +++ b/chrome/browser/renderer_host/audio_renderer_host.cc @@ -55,7 +55,7 @@ static size_t GetMaxAudioStreamsAllowed() { return kMaxStreams; } -static uint32 SelectHardwarePacketSize(AudioParameters params) { +static uint32 SelectSamplesPerPacket(AudioParameters params) { // Select the number of samples that can provide at least // |kMillisecondsPerHardwarePacket| worth of audio data. int samples = kMinSamplesPerHardwarePacket; @@ -64,7 +64,7 @@ static uint32 SelectHardwarePacketSize(AudioParameters params) { params.sample_rate * kMillisecondsPerHardwarePacket) { samples *= 2; } - return params.channels * samples * params.bits_per_sample / 8; + return samples; } AudioRendererHost::AudioEntry::AudioEntry() @@ -347,15 +347,17 @@ void AudioRendererHost::OnCreateStream( return; } - // Select the hardwaer packet size if not specified. - uint32 hardware_packet_size = params.packet_size; - if (!hardware_packet_size) { - hardware_packet_size = SelectHardwarePacketSize(params.params); + AudioParameters audio_params(params.params); + + // Select the hardware packet size if not specified. + if (!audio_params.samples_per_packet) { + audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); } + uint32 packet_size = audio_params.GetPacketSize(); scoped_ptr entry(new AudioEntry()); // Create the shared memory and share with the renderer process. - if (!entry->shared_memory.CreateAndMapAnonymous(hardware_packet_size)) { + if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { // If creation of shared memory failed then send an error message. SendErrorMessage(msg.routing_id(), stream_id); return; @@ -376,16 +378,13 @@ void AudioRendererHost::OnCreateStream( // entry and construct an AudioOutputController. entry->reader.reset(reader.release()); entry->controller = - media::AudioOutputController::CreateLowLatency( - this, params.params, - hardware_packet_size, - entry->reader.get()); + media::AudioOutputController::CreateLowLatency(this, audio_params, + entry->reader.get()); } else { // The choice of buffer capacity is based on experiment. entry->controller = - media::AudioOutputController::Create(this, params.params, - hardware_packet_size, - 3 * hardware_packet_size); + media::AudioOutputController::Create(this, audio_params, + 3 * packet_size); } if (!entry->controller) { diff --git a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc index 64ce7dd..7c3b500 100644 --- a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc +++ b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc @@ -218,7 +218,7 @@ class AudioRendererHostTest : public testing::Test { params.params.channels = 2; params.params.sample_rate = AudioParameters::kAudioCDSampleRate; params.params.bits_per_sample = 16; - params.packet_size = 0; + params.params.samples_per_packet = 0; // Send a create stream message to the audio output stream and wait until // we receive the created message. @@ -244,7 +244,7 @@ class AudioRendererHostTest : public testing::Test { params.params.channels = 2; params.params.sample_rate = AudioParameters::kAudioCDSampleRate; params.params.bits_per_sample = 16; - params.packet_size = 0; + params.params.samples_per_packet = 0; // Send a create stream message to the audio output stream and wait until // we receive the created message. diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index af37c6b..2900957 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -25,6 +25,7 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/thread.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_child_process_host.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/child_process_security_policy.h" @@ -36,6 +37,7 @@ #include "chrome/browser/gpu_process_host.h" #include "chrome/browser/history/history.h" #include "chrome/browser/io_thread.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/audio_renderer_host.h" @@ -619,11 +621,13 @@ void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer( switches::kBlockNonSandboxedPlugins, switches::kDisableOutdatedPlugins, switches::kEnableRemoting, - switches::kDisableClickToPlay, + switches::kEnableClickToPlay, switches::kEnableResourceContentSettings, switches::kPrelaunchGpuProcess, switches::kEnableAcceleratedDecoding, - switches::kDisableFileSystem + switches::kDisableFileSystem, + switches::kPpapiOutOfProcess, + switches::kEnablePrintPreview, }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); @@ -679,6 +683,26 @@ void BrowserRenderProcessHost::InitExtensions() { Send(new ViewMsg_Extension_SetFunctionNames(function_names)); } +void BrowserRenderProcessHost::InitSpeechInput() { + bool enabled = true; + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch(switches::kDisableSpeechInput)) { + enabled = false; +#if defined(GOOGLE_CHROME_BUILD) + } else if (!command_line.HasSwitch(switches::kEnableSpeechInput)) { + // We need to evaluate whether IO is OK here. http://crbug.com/63335. + base::ThreadRestrictions::ScopedAllowIO allow_io; + // Official Chrome builds don't have speech input enabled by default in the + // beta and stable channels. + std::string channel = platform_util::GetVersionStringModifier(); + enabled = (!channel.empty() && channel != "beta"); +#endif + } + + Send(new ViewMsg_SpeechInput_SetFeatureEnabled(enabled)); +} + void BrowserRenderProcessHost::SendUserScriptsUpdate( base::SharedMemory *shared_memory) { // Process is being started asynchronously. We'll end up calling @@ -856,6 +880,12 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { if (deleting_soon_) return; +#if defined(OS_CHROMEOS) + // To troubleshoot crosbug.com/7327. + CHECK(this); + CHECK(&msg); +#endif + mark_child_process_activity_time(); if (msg.routing_id() == MSG_ROUTING_CONTROL) { // Dispatch control messages. @@ -1044,6 +1074,7 @@ void BrowserRenderProcessHost::OnProcessLaunched() { Send(new ViewMsg_SetIsIncognitoProcess(profile()->IsOffTheRecord())); + InitSpeechInput(); InitVisitedLinks(); InitUserScripts(); InitExtensions(); diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h index 841b6ae..2ca02e7 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.h +++ b/chrome/browser/renderer_host/browser_render_process_host.h @@ -127,6 +127,10 @@ class BrowserRenderProcessHost : public RenderProcessHost, // functions to thre renderer process. void InitExtensions(); + // Initialize support for speech input API. Informs the renderer if the API + // is enabled or not. + void InitSpeechInput(); + // Sends the renderer process a new set of user scripts. void SendUserScriptsUpdate(base::SharedMemory* shared_memory); diff --git a/chrome/browser/renderer_host/file_utilities_dispatcher_host.cc b/chrome/browser/renderer_host/file_utilities_dispatcher_host.cc index ffbbc19..ad6fe97 100644 --- a/chrome/browser/renderer_host/file_utilities_dispatcher_host.cc +++ b/chrome/browser/renderer_host/file_utilities_dispatcher_host.cc @@ -52,18 +52,16 @@ void FileUtilitiesDispatcherHost::Shutdown() { } bool FileUtilitiesDispatcherHost::OnMessageReceived( - const IPC::Message& message, bool* message_was_ok) { + const IPC::Message& message) { DCHECK(!shutdown_); - *message_was_ok = true; bool handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(FileUtilitiesDispatcherHost, - message, *message_was_ok) + IPC_BEGIN_MESSAGE_MAP(FileUtilitiesDispatcherHost, message) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetFileSize, OnGetFileSize) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetFileModificationTime, OnGetFileModificationTime) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenFile, OnOpenFile) - IPC_MESSAGE_UNHANDLED((handled = false, msg_is_ok__ = true)) - IPC_END_MESSAGE_MAP_EX() + IPC_MESSAGE_UNHANDLED((handled = false)) + IPC_END_MESSAGE_MAP() return handled; } diff --git a/chrome/browser/renderer_host/file_utilities_dispatcher_host.h b/chrome/browser/renderer_host/file_utilities_dispatcher_host.h index 4e8972a..b62aff5 100644 --- a/chrome/browser/renderer_host/file_utilities_dispatcher_host.h +++ b/chrome/browser/renderer_host/file_utilities_dispatcher_host.h @@ -25,7 +25,7 @@ class FileUtilitiesDispatcherHost FileUtilitiesDispatcherHost(IPC::Message::Sender* sender, int process_id); void Init(base::ProcessHandle process_handle); void Shutdown(); - bool OnMessageReceived(const IPC::Message& message, bool* msg_is_ok); + bool OnMessageReceived(const IPC::Message& message); void Send(IPC::Message* message); diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.cc b/chrome/browser/renderer_host/render_sandbox_host_linux.cc index 0253f9e..92105b4 100644 --- a/chrome/browser/renderer_host/render_sandbox_host_linux.cc +++ b/chrome/browser/renderer_host/render_sandbox_host_linux.cc @@ -637,15 +637,15 @@ class SandboxIPCProcess { // Runs on the main thread at startup. RenderSandboxHostLinux::RenderSandboxHostLinux() - : init_(false), + : initialized_(false), renderer_socket_(0), childs_lifeline_fd_(0), pid_(0) { } void RenderSandboxHostLinux::Init(const std::string& sandbox_path) { - DCHECK(!init_); - init_ = true; + DCHECK(!initialized_); + initialized_ = true; int fds[2]; // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the renderer from @@ -673,7 +673,7 @@ void RenderSandboxHostLinux::Init(const std::string& sandbox_path) { } RenderSandboxHostLinux::~RenderSandboxHostLinux() { - if (init_) { + if (initialized_) { if (HANDLE_EINTR(close(renderer_socket_)) < 0) PLOG(ERROR) << "close"; if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.h b/chrome/browser/renderer_host/render_sandbox_host_linux.h index f8e1551..b0122e8 100644 --- a/chrome/browser/renderer_host/render_sandbox_host_linux.h +++ b/chrome/browser/renderer_host/render_sandbox_host_linux.h @@ -20,11 +20,11 @@ class RenderSandboxHostLinux { // Get the file descriptor which renderers should be given in order to signal // crashes to the browser. int GetRendererSocket() const { - DCHECK(init_); + DCHECK(initialized_); return renderer_socket_; } pid_t pid() const { - DCHECK(init_); + DCHECK(initialized_); return pid_; } void Init(const std::string& sandbox_path); @@ -35,7 +35,9 @@ class RenderSandboxHostLinux { RenderSandboxHostLinux(); ~RenderSandboxHostLinux(); - bool init_; + // Whether Init() has been called yet. + bool initialized_; + int renderer_socket_; int childs_lifeline_fd_; pid_t pid_; diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 134274e..4dd8a10 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -15,7 +15,6 @@ #include "base/string_util.h" #include "base/time.h" #include "base/values.h" -#include "chrome/browser/blocked_plugin_manager.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/child_process_security_policy.h" #include "chrome/browser/cross_site_request_manager.h" @@ -25,6 +24,7 @@ #include "chrome/browser/in_process_webkit/session_storage_namespace.h" #include "chrome/browser/net/predictor_api.h" #include "chrome/browser/notifications/desktop_notification_service.h" +#include "chrome/browser/printing/print_preview_tab_controller.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" @@ -45,12 +45,12 @@ #include "chrome/common/thumbnail_score.h" #include "chrome/common/translate_errors.h" #include "chrome/common/url_constants.h" +#include "chrome/common/web_apps.h" #include "gfx/native_widget_types.h" #include "net/base/net_util.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h" #include "webkit/glue/context_menu.h" -#include "webkit/glue/dom_operations.h" #include "webkit/glue/form_data.h" #include "webkit/glue/form_field.h" #include "webkit/glue/password_form_dom_manager.h" @@ -62,7 +62,6 @@ using webkit_glue::FormData; using webkit_glue::PasswordForm; using webkit_glue::PasswordFormDomManager; using webkit_glue::PasswordFormFillData; -using webkit_glue::WebApplicationInfo; using WebKit::WebConsoleMessage; using WebKit::WebDragOperation; using WebKit::WebDragOperationNone; @@ -134,6 +133,7 @@ RenderViewHost::RenderViewHost(SiteInstance* instance, sudden_termination_allowed_(false), session_storage_namespace_(session_storage), is_extension_process_(false), + autofill_query_id_(0), save_accessibility_tree_for_testing_(false) { if (!session_storage_namespace_) { session_storage_namespace_ = @@ -843,10 +843,6 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_DevToolsRuntimePropertyChanged, OnDevToolsRuntimePropertyChanged); IPC_MESSAGE_HANDLER(ViewHostMsg_MissingPluginStatus, OnMissingPluginStatus); - IPC_MESSAGE_HANDLER(ViewHostMsg_NonSandboxedPluginBlocked, - OnNonSandboxedPluginBlocked); - IPC_MESSAGE_HANDLER(ViewHostMsg_BlockedPluginLoaded, - OnBlockedPluginLoaded); IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin); IPC_MESSAGE_HANDLER(ViewHostMsg_DisabledOutdatedPlugin, OnDisabledOutdatedPlugin); @@ -1620,23 +1616,6 @@ void RenderViewHost::OnMissingPluginStatus(int status) { integration_delegate->OnMissingPluginStatus(status); } -void RenderViewHost::OnNonSandboxedPluginBlocked(const std::string& plugin, - const string16& name) { - RenderViewHostDelegate::BlockedPlugin* blocked_plugin_delegate = - delegate_->GetBlockedPluginDelegate(); - if (blocked_plugin_delegate) { - blocked_plugin_delegate->OnNonSandboxedPluginBlocked(plugin, name); - } -} - -void RenderViewHost::OnBlockedPluginLoaded() { - RenderViewHostDelegate::BlockedPlugin* blocked_plugin_delegate = - delegate_->GetBlockedPluginDelegate(); - if (blocked_plugin_delegate) { - blocked_plugin_delegate->OnBlockedPluginLoaded(); - } -} - void RenderViewHost::OnCrashedPlugin(const FilePath& plugin_path) { RenderViewHostDelegate::BrowserIntegration* integration_delegate = delegate_->GetBrowserIntegrationDelegate(); @@ -1712,33 +1691,27 @@ void RenderViewHost::OnMsgShouldCloseACK(bool proceed) { } void RenderViewHost::OnQueryFormFieldAutoFill( - int query_id, bool form_autofilled, const webkit_glue::FormField& field) { + int query_id, bool field_autofilled, const webkit_glue::FormField& field) { + ResetAutoFillState(query_id); + + // We first query the autofill delegate for suggestions. We keep track of the + // results it gives us, which we will later combine with the autocomplete + // suggestions. RenderViewHostDelegate::AutoFill* autofill_delegate = delegate_->GetAutoFillDelegate(); - // We first save the AutoFill delegate's suggestions. Then we fetch the - // Autocomplete delegate's suggestions and send the combined results back to - // the render view. - if (autofill_delegate && - autofill_delegate->GetAutoFillSuggestions(query_id, - form_autofilled, - field)) { - } else { - // No suggestions provided, so supply an empty vector as the results. - AutoFillSuggestionsReturned(query_id, - std::vector(), - std::vector(), - std::vector(), - std::vector()); + if (autofill_delegate) { + autofill_delegate->GetAutoFillSuggestions(field_autofilled, field); } + // Now query the Autocomplete delegate for suggestions. These will be combined + // with the saved autofill suggestions in |AutocompleteSuggestionsReturned()|. RenderViewHostDelegate::Autocomplete* autocomplete_delegate = delegate_->GetAutocompleteDelegate(); - if (autocomplete_delegate && - autocomplete_delegate->GetAutocompleteSuggestions( - query_id, field.name(), field.value())) { + if (autocomplete_delegate) { + autocomplete_delegate->GetAutocompleteSuggestions(field.name(), + field.value()); } else { - // No suggestions provided, so send an empty vector as the results. - AutocompleteSuggestionsReturned(query_id, std::vector()); + AutocompleteSuggestionsReturned(std::vector()); } } @@ -1792,24 +1765,33 @@ void RenderViewHost::OnDidFillAutoFillFormData() { NotificationService::NoDetails()); } +void RenderViewHost::ResetAutoFillState(int query_id) { + autofill_query_id_ = query_id; + + autofill_values_.clear(); + autofill_labels_.clear(); + autofill_icons_.clear(); + autofill_unique_ids_.clear(); +} + void RenderViewHost::AutoFillSuggestionsReturned( - int query_id, - const std::vector& names, + const std::vector& values, const std::vector& labels, const std::vector& icons, const std::vector& unique_ids) { - autofill_values_.assign(names.begin(), names.end()); + autofill_values_.assign(values.begin(), values.end()); autofill_labels_.assign(labels.begin(), labels.end()); autofill_icons_.assign(icons.begin(), icons.end()); autofill_unique_ids_.assign(unique_ids.begin(), unique_ids.end()); } void RenderViewHost::AutocompleteSuggestionsReturned( - int query_id, const std::vector& suggestions) { + const std::vector& suggestions) { // Combine AutoFill and Autocomplete values into values and labels. for (size_t i = 0; i < suggestions.size(); ++i) { bool unique = true; for (size_t j = 0; j < autofill_values_.size(); ++j) { + // TODO(isherman): Why just when the label is empty? // If the AutoFill label is empty, we need to make sure we don't add a // duplicate value. if (autofill_labels_[j].empty() && @@ -1828,7 +1810,7 @@ void RenderViewHost::AutocompleteSuggestionsReturned( } Send(new ViewMsg_AutoFillSuggestionsReturned(routing_id(), - query_id, + autofill_query_id_, autofill_values_, autofill_labels_, autofill_icons_, @@ -1883,10 +1865,6 @@ void RenderViewHost::OnMsgBlur() { view->Deactivate(); } -gfx::Rect RenderViewHost::GetRootWindowResizerRect() const { - return delegate_->GetRootWindowResizerRect(); -} - void RenderViewHost::ForwardMouseEvent( const WebKit::WebMouseEvent& mouse_event) { @@ -2235,9 +2213,26 @@ void RenderViewHost::OnMsgShowPopup( } #endif +TabContents* RenderViewHost::GetOrCreatePrintPreviewTab() { + TabContents* initiator_tab = delegate_ ? delegate_->GetAsTabContents() : NULL; + if (initiator_tab) { + // Get/Create preview tab for initiator tab. + printing::PrintPreviewTabController* tab_controller = + printing::PrintPreviewTabController::GetInstance(); + if (tab_controller) + return tab_controller->GetOrCreatePreviewTab( + initiator_tab, delegate_->GetBrowserWindowID()); + } + return NULL; +} + #if defined(OS_MACOSX) || defined(OS_WIN) void RenderViewHost::OnPageReadyForPreview( const ViewHostMsg_DidPrintPage_Params& params) { + // Get/Create print preview tab. + TabContents* print_preview_tab = GetOrCreatePrintPreviewTab(); + DCHECK(print_preview_tab); + // TODO(kmadhusu): Function definition needs to be changed. // 'params' contains the metafile handle for preview. @@ -2246,6 +2241,10 @@ void RenderViewHost::OnPageReadyForPreview( } #else void RenderViewHost::OnPagesReadyForPreview(int fd_in_browser) { + // Get/Create print preview tab. + TabContents* print_preview_tab = GetOrCreatePrintPreviewTab(); + DCHECK(print_preview_tab); + // TODO(kmadhusu): Function definition needs to be changed. // fd_in_browser should be the file descriptor of the metafile. diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index efcf56c..eb2233d 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -43,7 +43,9 @@ struct ViewHostMsg_DomMessage_Params; struct ViewHostMsg_PageHasOSDD_Type; struct ViewHostMsg_RunFileChooser_Params; struct ViewHostMsg_ShowNotification_Params; +struct ViewHostMsg_ShowPopup_Params; struct ViewMsg_Navigate_Params; +struct WebApplicationInfo; struct WebDropData; struct WebPreferences; struct UserMetricsAction; @@ -58,7 +60,6 @@ class FormField; struct PasswordForm; struct PasswordFormFillData; struct WebAccessibility; -struct WebApplicationInfo; } // namespace webkit_glue namespace WebKit { @@ -411,18 +412,18 @@ class RenderViewHost : public RenderWidgetHost { // set to false when creating a renderer-initiated window via window.open. void AllowScriptToClose(bool visible); + // Resets the stored AutoFill state. + void ResetAutoFillState(int query_id); + // Called by the AutoFillManager when the list of suggestions is ready. - void AutoFillSuggestionsReturned( - int query_id, - const std::vector& values, - const std::vector& labels, - const std::vector& icons, - const std::vector& unique_ids); + void AutoFillSuggestionsReturned(const std::vector& values, + const std::vector& labels, + const std::vector& icons, + const std::vector& unique_ids); // Called by the AutocompleteHistoryManager when the list of suggestions is // ready. void AutocompleteSuggestionsReturned( - int query_id, const std::vector& suggestions); // Called by the AutoFillManager when the FormData has been filled out. @@ -445,7 +446,6 @@ class RenderViewHost : public RenderWidgetHost { const std::string& value); virtual void ForwardEditCommandsForNextKeyEvent( const EditCommands& edit_commands); - virtual gfx::Rect GetRootWindowResizerRect() const; // Creates a new RenderView with the given route id. void CreateNewWindow(int route_id, @@ -656,9 +656,6 @@ class RenderViewHost : public RenderWidgetHost { void OnDevToolsRuntimePropertyChanged(const std::string& name, const std::string& value); void OnMissingPluginStatus(int status); - void OnNonSandboxedPluginBlocked(const std::string& plugin, - const string16& name); - void OnBlockedPluginLoaded(); void OnCrashedPlugin(const FilePath& plugin_path); void OnDisabledOutdatedPlugin(const string16& name, const GURL& update_url); @@ -671,8 +668,7 @@ class RenderViewHost : public RenderWidgetHost { const std::string& data, int32 status); - void OnDidGetApplicationInfo(int32 page_id, - const webkit_glue::WebApplicationInfo& info); + void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info); void OnMsgShouldCloseACK(bool proceed); void OnQueryFormFieldAutoFill(int request_id, bool form_autofilled, @@ -737,6 +733,9 @@ class RenderViewHost : public RenderWidgetHost { private: friend class TestRenderViewHost; + // Get/Create print preview tab. + TabContents* GetOrCreatePrintPreviewTab(); + // The SiteInstance associated with this RenderViewHost. All pages drawn // in this RenderViewHost are part of this SiteInstance. Should not change // over time. @@ -805,12 +804,14 @@ class RenderViewHost : public RenderWidgetHost { // what process type we use. bool is_extension_process_; + // TODO(isherman): Consider splitting these off into a helper class. // AutoFill and Autocomplete suggestions. We accumulate these separately and // send them back to the renderer together. std::vector autofill_values_; std::vector autofill_labels_; std::vector autofill_icons_; std::vector autofill_unique_ids_; + int autofill_query_id_; // Whether the accessibility tree should be saved, for unit testing. bool save_accessibility_tree_for_testing_; diff --git a/chrome/browser/renderer_host/render_view_host_delegate.cc b/chrome/browser/renderer_host/render_view_host_delegate.cc index 523fd8f..738a1ec 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.cc +++ b/chrome/browser/renderer_host/render_view_host_delegate.cc @@ -69,11 +69,6 @@ RenderViewHostDelegate::GetBookmarkDragDelegate() { return NULL; } -RenderViewHostDelegate::BlockedPlugin* -RenderViewHostDelegate::GetBlockedPluginDelegate() { - return NULL; -} - RenderViewHostDelegate::SSL* RenderViewHostDelegate::GetSSLDelegate() { return NULL; @@ -97,6 +92,10 @@ TabContents* RenderViewHostDelegate::GetAsTabContents() { return NULL; } +BackgroundContents* RenderViewHostDelegate::GetAsBackgroundContents() { + return NULL; +} + GURL RenderViewHostDelegate::GetAlternateErrorPageURL() const { return GURL(); } @@ -105,10 +104,6 @@ WebPreferences RenderViewHostDelegate::GetWebkitPrefs() { return WebPreferences(); } -gfx::Rect RenderViewHostDelegate::GetRootWindowResizerRect() const { - return gfx::Rect(); -} - bool RenderViewHostDelegate::IsExternalTabContainer() const { return false; } diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index a4e88a3..2a6f745 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -24,6 +24,7 @@ class AutomationResourceRoutingDelegate; +class BackgroundContents; struct BookmarkDragData; class BookmarkNode; struct ContextMenuParams; @@ -49,6 +50,7 @@ struct ViewHostMsg_DomMessage_Params; struct ViewHostMsg_FrameNavigate_Params; struct ViewHostMsg_PageHasOSDD_Type; struct ViewHostMsg_RunFileChooser_Params; +struct WebApplicationInfo; struct WebDropData; struct WebMenuItem; class WebKeyboardEvent; @@ -72,7 +74,6 @@ namespace webkit_glue { struct FormData; class FormField; struct PasswordForm; -struct WebApplicationInfo; } // @@ -279,10 +280,11 @@ class RenderViewHostDelegate { virtual void OnDisabledOutdatedPlugin(const string16& name, const GURL& update_url) = 0; - // Notification that a request for install info has completed. + // Notification that a user's request to install an application has + // completed. virtual void OnDidGetApplicationInfo( int32 page_id, - const webkit_glue::WebApplicationInfo& app_info) = 0; + const WebApplicationInfo& app_info) = 0; // Notification that the contents of the page has been loaded. virtual void OnPageContents(const GURL& url, @@ -520,10 +522,7 @@ class RenderViewHostDelegate { // query. When the database thread is finished, the AutocompleteHistory // manager retrieves the calling RenderViewHost and then passes the vector // of suggestions to RenderViewHost::AutocompleteSuggestionsReturned. - // Returns true to indicate that FormFieldHistorySuggestionsReturned will be - // called. - virtual bool GetAutocompleteSuggestions(int query_id, - const string16& field_name, + virtual void GetAutocompleteSuggestions(const string16& field_name, const string16& user_text) = 0; // Called when the user has indicated that she wants to remove the specified @@ -548,13 +547,13 @@ class RenderViewHostDelegate { virtual void FormsSeen(const std::vector& forms) = 0; // Called to retrieve a list of AutoFill suggestions from the web database - // given the name of the field and what the user has already typed in the - // field. |form_autofilled| is true if the form containing |field| has any - // auto-filled fields. Returns true to indicate that - // RenderViewHost::AutoFillSuggestionsReturned has been called. + // given the name of the field, whether it is auto-filled, and what the user + // has already typed in it. If there is a warning to be returned to the + // user, it is stored into |values|, with corresponding unique id -1. + // Returns true to indicate that RenderViewHost::AutoFillSuggestionsReturned + // has been called. virtual bool GetAutoFillSuggestions( - int query_id, - bool form_autofilled, + bool field_autofilled, const webkit_glue::FormField& field) = 0; // Called to fill the FormData object with AutoFill profile information that @@ -586,13 +585,6 @@ class RenderViewHostDelegate { virtual ~BookmarkDrag() {} }; - class BlockedPlugin { - public: - virtual void OnNonSandboxedPluginBlocked(const std::string& plugin, - const string16& name) = 0; - virtual void OnBlockedPluginLoaded() = 0; - }; - // SSL ----------------------------------------------------------------------- // Interface for UI and other RenderViewHost-specific interactions with SSL. @@ -663,7 +655,6 @@ class RenderViewHostDelegate { virtual Autocomplete* GetAutocompleteDelegate(); virtual AutoFill* GetAutoFillDelegate(); virtual BookmarkDrag* GetBookmarkDragDelegate(); - virtual BlockedPlugin* GetBlockedPluginDelegate(); virtual SSL* GetSSLDelegate(); virtual FileSelect* GetFileSelectDelegate(); @@ -679,6 +670,10 @@ class RenderViewHostDelegate { // not a TabContents, returns NULL. virtual TabContents* GetAsTabContents(); + // Return this object cast to a BackgroundContents, if it is one. If the + // object is not a BackgroundContents, returns NULL. + virtual BackgroundContents* GetAsBackgroundContents(); + // Return id number of browser window which this object is attached to. If no // browser window is attached to, just return -1. virtual int GetBrowserWindowID() const = 0; @@ -828,10 +823,6 @@ class RenderViewHostDelegate { // Notification from the renderer that JS runs out of memory. virtual void OnJSOutOfMemory() {} - // Return the rect where to display the resize corner, if any, otherwise - // an empty rect. - virtual gfx::Rect GetRootWindowResizerRect() const; - // Notification that the renderer has become unresponsive. The // delegate can use this notification to show a warning to the user. virtual void RendererUnresponsive(RenderViewHost* render_view_host, diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 6f586ee..46fd376 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -255,26 +255,37 @@ void RenderWidgetHost::WasResized() { return; } - gfx::Rect view_bounds = view_->GetViewBounds(); - gfx::Size new_size(view_bounds.width(), view_bounds.height()); + gfx::Size new_size = view_->GetViewBounds().size(); + gfx::Rect reserved_rect = view_->reserved_contents_rect(); // Avoid asking the RenderWidget to resize to its current size, since it - // won't send us a PaintRect message in that case. - if (new_size == current_size_) + // won't send us a PaintRect message in that case, unless reserved area is + // changed, but even in this case PaintRect message won't be sent. + if (new_size == current_size_ && reserved_rect == current_reserved_rect_) return; - if (in_flight_size_ != gfx::Size() && new_size == in_flight_size_) + if (in_flight_size_ != gfx::Size() && new_size == in_flight_size_ && + in_flight_reserved_rect_ == reserved_rect) { return; + } - // We don't expect to receive an ACK when the requested size is empty. - if (!new_size.IsEmpty()) - resize_ack_pending_ = true; + // We don't expect to receive an ACK when the requested size is empty or + // only reserved area is changed. + resize_ack_pending_ = !new_size.IsEmpty() && new_size != current_size_; - if (!Send(new ViewMsg_Resize(routing_id_, new_size, - GetRootWindowResizerRect()))) + if (!Send(new ViewMsg_Resize(routing_id_, new_size, reserved_rect))) { resize_ack_pending_ = false; - else - in_flight_size_ = new_size; + } else { + if (resize_ack_pending_) { + in_flight_size_ = new_size; + in_flight_reserved_rect_ = reserved_rect; + } else { + // Message was sent successfully, but we do not expect to receive an ACK, + // so update current values right away. + current_size_ = new_size; + current_reserved_rect_ = reserved_rect; + } + } } void RenderWidgetHost::GotFocus() { @@ -617,8 +628,11 @@ void RenderWidgetHost::RendererExited() { repaint_ack_pending_ = false; in_flight_size_.SetSize(0, 0); + in_flight_reserved_rect_.SetRect(0, 0, 0, 0); current_size_.SetSize(0, 0); + current_reserved_rect_.SetRect(0, 0, 0, 0); is_hidden_ = false; + is_gpu_rendering_active_ = false; if (view_) { view_->RenderViewGone(); @@ -675,10 +689,6 @@ void RenderWidgetHost::ImeCancelComposition() { std::vector(), 0, 0)); } -gfx::Rect RenderWidgetHost::GetRootWindowResizerRect() const { - return gfx::Rect(); -} - void RenderWidgetHost::SetActive(bool active) { Send(new ViewMsg_SetActive(routing_id(), active)); } @@ -765,6 +775,7 @@ void RenderWidgetHost::OnMsgUpdateRect( // Update our knowledge of the RenderWidget's size. current_size_ = params.view_size; + current_reserved_rect_ = params.resizer_rect; bool is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags); @@ -775,6 +786,7 @@ void RenderWidgetHost::OnMsgUpdateRect( DCHECK(resize_ack_pending_); resize_ack_pending_ = false; in_flight_size_.SetSize(0, 0); + in_flight_reserved_rect_.SetRect(0, 0, 0, 0); } bool is_repaint_ack = @@ -848,11 +860,9 @@ void RenderWidgetHost::OnMsgUpdateRect( // If we got a resize ack, then perhaps we have another resize to send? if (is_resize_ack && view_) { - gfx::Rect view_bounds = view_->GetViewBounds(); - if (current_size_.width() != view_bounds.width() || - current_size_.height() != view_bounds.height()) { - WasResized(); - } + // WasResized checks the current size and sends the resize update only + // when something was actually changed. + WasResized(); } if (painting_observer_) diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 42bdbde..8514ce0 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -19,6 +19,7 @@ #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/property_bag.h" #include "gfx/native_widget_types.h" +#include "gfx/rect.h" #include "gfx/size.h" #include "ipc/ipc_channel.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" @@ -43,7 +44,6 @@ class RenderWidgetHostView; class RenderWidgetHostPaintingObserver; class TransportDIB; class WebCursor; -struct ViewHostMsg_ShowPopup_Params; struct ViewHostMsg_UpdateRect_Params; // This class manages the browser side of a browser<->renderer HWND connection. @@ -363,10 +363,6 @@ class RenderWidgetHost : public IPC::Channel::Listener, // Cancels an ongoing composition. void ImeCancelComposition(); - // This is for derived classes to give us access to the resizer rect. - // And to also expose it to the RenderWidgetHostView. - virtual gfx::Rect GetRootWindowResizerRect() const; - // Makes an IPC call to toggle the spelling panel. void ToggleSpellPanel(bool is_currently_visible); @@ -575,6 +571,10 @@ class RenderWidgetHost : public IPC::Channel::Listener, // The current size of the RenderWidget. gfx::Size current_size_; + // The current reserved area of the RenderWidget where contents should not be + // rendered to draw the resize corner, sidebar mini tabs etc. + gfx::Rect current_reserved_rect_; + // The size we last sent as requested size to the renderer. |current_size_| // is only updated once the resize message has been ack'd. This on the other // hand is updated when the resize message is sent. This is very similar to @@ -582,6 +582,11 @@ class RenderWidgetHost : public IPC::Channel::Listener, // or height zero, which is why we need this too. gfx::Size in_flight_size_; + // The reserved area we last sent to the renderer. |current_reserved_rect_| + // is only updated once the resize message has been ack'd. This on the other + // hand is updated when the resize message is sent. + gfx::Rect in_flight_reserved_rect_; + // True if a mouse move event was sent to the render view and we are waiting // for a corresponding ViewHostMsg_HandleInputEvent_ACK message. bool mouse_move_pending_; diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc index 1c5bb17..72495d3 100644 --- a/chrome/browser/renderer_host/render_widget_host_unittest.cc +++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc @@ -352,28 +352,33 @@ TEST_F(RenderWidgetHostTest, Resize) { host_->WasResized(); EXPECT_FALSE(host_->resize_ack_pending_); EXPECT_EQ(gfx::Size(), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(), host_->current_size_); EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); // Send a rect that has no area but has either width or height set. + // since we do not expect ACK, current_size_ should be updated right away. process_->sink().ClearMessages(); view_->set_bounds(gfx::Rect(0, 0, 0, 30)); host_->WasResized(); EXPECT_FALSE(host_->resize_ack_pending_); - EXPECT_EQ(gfx::Size(0, 30), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(0, 30), host_->current_size_); EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); // Set the same size again. It should not be sent again. process_->sink().ClearMessages(); host_->WasResized(); EXPECT_FALSE(host_->resize_ack_pending_); - EXPECT_EQ(gfx::Size(0, 30), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(0, 30), host_->current_size_); EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID)); // A different size should be sent again, however. view_->set_bounds(gfx::Rect(0, 0, 0, 31)); host_->WasResized(); EXPECT_FALSE(host_->resize_ack_pending_); - EXPECT_EQ(gfx::Size(0, 31), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(), host_->in_flight_size_); + EXPECT_EQ(gfx::Size(0, 31), host_->current_size_); EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); } diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index d7fa9c3..1c8bb13 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -15,6 +15,7 @@ #include "app/surface/transport_dib.h" #include "gfx/native_widget_types.h" +#include "gfx/rect.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h" #include "third_party/WebKit/WebKit/chromium/public/WebTextInputType.h" @@ -260,6 +261,13 @@ class RenderWidgetHostView { const std::vector& params) { } + gfx::Rect reserved_contents_rect() const { + return reserved_rect_; + } + void set_reserved_contents_rect(const gfx::Rect& reserved_rect) { + reserved_rect_ = reserved_rect; + } + protected: // Interface class only, do not construct. RenderWidgetHostView() : popup_type_(WebKit::WebPopupTypeNone) {} @@ -272,6 +280,10 @@ class RenderWidgetHostView { // horizontally. Can be null, in which case we fall back to painting white. SkBitmap background_; + // The current reserved area in view coordinates where contents should not be + // rendered to draw the resize corner, sidebar mini tabs etc. + gfx::Rect reserved_rect_; + private: DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostView); }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index d8cd696..40761ae 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -1781,7 +1781,12 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { - (id)accessibilityAttributeValue:(NSString *)attribute { BrowserAccessibilityManager* manager = renderWidgetHostView_->browser_accessibility_manager_.get(); - if ([attribute isEqualToString:NSAccessibilityChildrenAttribute] && + + // Contents specifies document view of RenderWidgetHostViewCocoa provided by + // BrowserAccessibilityManager. Children includes all subviews in addition to + // contents. Currently we do not have subviews besides the document view. + if (([attribute isEqualToString:NSAccessibilityChildrenAttribute] || + [attribute isEqualToString:NSAccessibilityContentsAttribute]) && manager) { return [NSArray arrayWithObjects:manager-> GetRoot()->toBrowserAccessibilityCocoa(), nil]; @@ -1792,6 +1797,13 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { return ret; } +- (NSArray*)accessibilityAttributeNames { + NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; + [ret addObject:NSAccessibilityContentsAttribute]; + [ret addObjectsFromArray:[super accessibilityAttributeNames]]; + return ret; +} + - (id)accessibilityHitTest:(NSPoint)point { if (!renderWidgetHostView_->browser_accessibility_manager_.get()) return self; diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 38bbee2..6945b2e 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -578,8 +578,6 @@ void RenderWidgetHostViewWin::UpdateCursor(const WebCursor& cursor) { } void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() { - static HCURSOR kCursorResizeRight = LoadCursor(NULL, IDC_SIZENWSE); - static HCURSOR kCursorResizeLeft = LoadCursor(NULL, IDC_SIZENESW); static HCURSOR kCursorArrow = LoadCursor(NULL, IDC_ARROW); static HCURSOR kCursorAppStarting = LoadCursor(NULL, IDC_APPSTARTING); static HINSTANCE module_handle = @@ -591,26 +589,19 @@ void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() { if (WindowFromPoint(pt) == m_hWnd) { BOOL result = ::ScreenToClient(m_hWnd, &pt); DCHECK(result); - if (render_widget_host_->GetRootWindowResizerRect().Contains(pt.x, pt.y)) { - if (base::i18n::IsRTL()) - SetCursor(kCursorResizeLeft); - else - SetCursor(kCursorResizeRight); - } else { - // We cannot pass in NULL as the module handle as this would only work for - // standard win32 cursors. We can also receive cursor types which are - // defined as webkit resources. We need to specify the module handle of - // chrome.dll while loading these cursors. - HCURSOR display_cursor = current_cursor_.GetCursor(module_handle); - - // If a page is in the loading state, we want to show the Arrow+Hourglass - // cursor only when the current cursor is the ARROW cursor. In all other - // cases we should continue to display the current cursor. - if (is_loading_ && display_cursor == kCursorArrow) - display_cursor = kCursorAppStarting; - - SetCursor(display_cursor); - } + // We cannot pass in NULL as the module handle as this would only work for + // standard win32 cursors. We can also receive cursor types which are + // defined as webkit resources. We need to specify the module handle of + // chrome.dll while loading these cursors. + HCURSOR display_cursor = current_cursor_.GetCursor(module_handle); + + // If a page is in the loading state, we want to show the Arrow+Hourglass + // cursor only when the current cursor is the ARROW cursor. In all other + // cases we should continue to display the current cursor. + if (is_loading_ && display_cursor == kCursorArrow) + display_cursor = kCursorAppStarting; + + SetCursor(display_cursor); } } @@ -684,31 +675,6 @@ void RenderWidgetHostViewWin::Redraw() { EnumChildWindows(m_hWnd, EnumChildProc, lparam); } -void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect, - HDC dc) { - gfx::Rect resize_corner_rect = - render_widget_host_->GetRootWindowResizerRect(); - if (!paint_rect.Intersect(resize_corner_rect).IsEmpty()) { - SkBitmap* bitmap = ResourceBundle::GetSharedInstance(). - GetBitmapNamed(IDR_TEXTAREA_RESIZER); - gfx::CanvasSkia canvas(bitmap->width(), bitmap->height(), false); - canvas.getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0); - int x = resize_corner_rect.x() + resize_corner_rect.width() - - bitmap->width(); - canvas.save(); - if (base::i18n::IsRTL()) { - canvas.TranslateInt(bitmap->width(), 0); - canvas.ScaleInt(-1, 1); - x = 0; - } - canvas.DrawBitmapInt(*bitmap, 0, 0); - canvas.getTopPlatformDevice().drawToHDC(dc, x, - resize_corner_rect.y() + resize_corner_rect.height() - - bitmap->height(), NULL); - canvas.restore(); - } -} - void RenderWidgetHostViewWin::DidUpdateBackingStore( const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, const std::vector& copy_rects) { @@ -925,7 +891,6 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) { for (DWORD i = 0; i < region_data->rdh.nCount; ++i) { gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i])); if (!paint_rect.IsEmpty()) { - DrawResizeCorner(paint_rect, backing_store->hdc()); if (visually_deemphasized_) { DrawDeemphasized(paint_rect, backing_store->hdc(), paint_dc.m_hDC); } else { @@ -1253,21 +1218,6 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, // call). So the TabContents window would have to be specified to the // RenderViewHostHWND as there is no way to retrieve it from the HWND. if (!close_on_deactivate_) { // Don't forward if the container is a popup. - if (message == WM_LBUTTONDOWN) { - // If we get clicked on, where the resize corner is drawn, we delegate the - // message to the root window, with the proper HTBOTTOMXXX wparam so that - // Windows can take care of the resizing for us. - if (render_widget_host_ && - render_widget_host_->GetRootWindowResizerRect(). - Contains(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) { - WPARAM wparam = HTBOTTOMRIGHT; - if (base::i18n::IsRTL()) - wparam = HTBOTTOMLEFT; - HWND root_hwnd = ::GetAncestor(m_hWnd, GA_ROOT); - if (SendMessage(root_hwnd, WM_NCLBUTTONDOWN, wparam, lparam) == 0) - return 0; - } - } switch (message) { case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index 5d8c680..d02193f 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -248,10 +248,6 @@ class RenderWidgetHostViewWin // asynchronously. void Redraw(); - // Draw the resize corner bitmap on top of the given HDC, if it intersects the - // given paint rect. - void DrawResizeCorner(const gfx::Rect& paint_rect, HDC dc); - // Draw our background over the given HDC in the given |rect|. The background // will be tiled such that it lines up with existing tiles starting from the // origin of |dc|. diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 6fd669e..c88e558 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -1141,8 +1141,7 @@ bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { } else { // We should not have any SSL state. DCHECK(!request->ssl_info().cert_status && - (request->ssl_info().security_bits == -1 || - request->ssl_info().security_bits == 0) && + request->ssl_info().security_bits == -1 && !request->ssl_info().connection_status); } diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc index 67cbe92..48390f6 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc @@ -77,7 +77,7 @@ TEST_F(ResourceDispatcherTest, ContentDispositionInline) { } // Test for bug #1091358. -// Flakey due to NavigateToURL bug: see http://crbug.com/55380 +// Flaky: http://crbug.com/62595 TEST_F(ResourceDispatcherTest, FLAKY_SyncXMLHttpRequest) { net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(FILE_PATH_LITERAL("chrome/test/data"))); @@ -99,7 +99,8 @@ TEST_F(ResourceDispatcherTest, FLAKY_SyncXMLHttpRequest) { EXPECT_TRUE(success); } -TEST_F(ResourceDispatcherTest, SyncXMLHttpRequest_Disallowed) { +// http://code.google.com/p/chromium/issues/detail?id=62776 +TEST_F(ResourceDispatcherTest, FLAKY_SyncXMLHttpRequest_Disallowed) { net::TestServer test_server(net::TestServer::TYPE_HTTP, FilePath(FILE_PATH_LITERAL("chrome/test/data"))); ASSERT_TRUE(test_server.Start()); diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index fc8cc12..6b83d5c 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -24,7 +24,6 @@ #include "chrome/browser/download/download_types.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/file_system/file_system_dispatcher_host.h" -#include "chrome/browser/file_system/file_system_host_context.h" #include "chrome/browser/geolocation/geolocation_dispatcher_host_old.h" #include "chrome/browser/geolocation/geolocation_permission_context.h" #include "chrome/browser/gpu_process_host.h" @@ -32,16 +31,18 @@ #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" #include "chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h" #include "chrome/browser/metrics/histogram_synchronizer.h" +#include "chrome/browser/mime_registry_dispatcher.h" #include "chrome/browser/nacl_host/nacl_process_host.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/predictor_api.h" #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/notifications/notifications_prefs_cache.h" #include "chrome/browser/platform_util.h" -#include "chrome/browser/plugin_service.h" #include "chrome/browser/plugin_process_host.h" -#include "chrome/browser/printing/printer_query.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/browser/ppapi_plugin_process_host.h" #include "chrome/browser/printing/print_job_manager.h" +#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/audio_renderer_host.h" #include "chrome/browser/renderer_host/blob_dispatcher_host.h" @@ -290,7 +291,9 @@ ResourceMessageFilter::ResourceMessageFilter( new BlobDispatcherHost( this->id(), profile->GetBlobStorageContext()))), ALLOW_THIS_IN_INITIALIZER_LIST(file_utilities_dispatcher_host_( - new FileUtilitiesDispatcherHost(this, this->id()))) { + new FileUtilitiesDispatcherHost(this, this->id()))), + ALLOW_THIS_IN_INITIALIZER_LIST(mime_registry_dispatcher_( + new MimeRegistryDispatcher(this))) { request_context_ = profile_->GetRequestContext(); DCHECK(request_context_); DCHECK(media_request_context_); @@ -329,6 +332,9 @@ ResourceMessageFilter::~ResourceMessageFilter() { // Shut down the async file_utilities dispatcher host. file_utilities_dispatcher_host_->Shutdown(); + // Shut down the mime registry dispatcher host. + mime_registry_dispatcher_->Shutdown(); + // Let interested observers know we are being deleted. NotificationService::current()->Notify( NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, @@ -407,7 +413,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { device_orientation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || file_system_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || blob_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || - file_utilities_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok); + file_utilities_dispatcher_host_->OnMessageReceived(msg) || + mime_registry_dispatcher_->OnMessageReceived(msg); if (!handled) { DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK. @@ -450,6 +457,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { OnReceiveContextMenuMsg(msg)) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, + OnOpenChannelToPepperPlugin) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LaunchNaCl, OnLaunchNaCl) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker) @@ -498,13 +507,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { OnClipboardReadFilenames) IPC_MESSAGE_HANDLER(ViewHostMsg_CheckNotificationPermission, OnCheckNotificationPermission) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension, - OnGetMimeTypeFromExtension) IPC_MESSAGE_HANDLER(ViewHostMsg_RevealFolderInOS, OnRevealFolderInOS) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile, - OnGetMimeTypeFromFile) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetPreferredExtensionForMimeType, - OnGetPreferredExtensionForMimeType) IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext, OnGetCPBrowsingContext) #if defined(OS_WIN) @@ -877,6 +880,14 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, new OpenChannelToPluginCallback(this, reply_msg)); } +void ResourceMessageFilter::OnOpenChannelToPepperPlugin( + const FilePath& path, + IPC::Message* reply_msg) { + PpapiPluginProcessHost* host = new PpapiPluginProcessHost(this); + host->Init(path, reply_msg); + ppapi_plugin_hosts_.push_back(linked_ptr(host)); +} + void ResourceMessageFilter::OnLaunchNaCl( const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg) { NaClProcessHost* host = new NaClProcessHost(resource_dispatcher_host_, url); @@ -1075,21 +1086,6 @@ void ResourceMessageFilter::OnCheckNotificationPermission( *result = notification_prefs_->HasPermission(source_url.GetOrigin()); } -void ResourceMessageFilter::OnGetMimeTypeFromExtension( - const FilePath::StringType& ext, std::string* mime_type) { - net::GetMimeTypeFromExtension(ext, mime_type); -} - -void ResourceMessageFilter::OnGetMimeTypeFromFile( - const FilePath& file_path, std::string* mime_type) { - net::GetMimeTypeFromFile(file_path, mime_type); -} - -void ResourceMessageFilter::OnGetPreferredExtensionForMimeType( - const std::string& mime_type, FilePath::StringType* ext) { - net::GetPreferredExtensionForMimeType(mime_type, ext); -} - void ResourceMessageFilter::OnGetCPBrowsingContext(uint32* context) { // Always allocate a new context when a plugin requests one, since it needs to // be unique for that plugin instance. diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 850306e..9266277 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -17,6 +17,7 @@ #include "app/surface/transport_dib.h" #include "base/callback.h" #include "base/file_path.h" +#include "base/linked_ptr.h" #include "base/process.h" #include "base/ref_counted.h" #include "base/string16.h" @@ -42,7 +43,9 @@ struct FontDescriptor; class GeolocationDispatcherHostOld; class HostZoomMap; class IndexedDBDispatcherHost; +class MimeRegistryDispatcher; class NotificationsPrefsCache; +class PpapiPluginProcessHost; class Profile; class RenderWidgetHelper; class SearchProviderInstallStateDispatcherHost; @@ -195,6 +198,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnOpenChannelToPlugin(const GURL& url, const std::string& mime_type, IPC::Message* reply_msg); + void OnOpenChannelToPepperPlugin(const FilePath& path, + IPC::Message* reply_msg); void OnLaunchNaCl(const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg); @@ -254,12 +259,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, #endif void OnRevealFolderInOS(const FilePath& path); - void OnGetMimeTypeFromExtension(const FilePath::StringType& ext, - std::string* mime_type); - void OnGetMimeTypeFromFile(const FilePath& file_path, - std::string* mime_type); - void OnGetPreferredExtensionForMimeType(const std::string& mime_type, - FilePath::StringType* ext); void OnGetCPBrowsingContext(uint32* context); #if defined(OS_WIN) @@ -474,6 +473,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, base::TimeTicks last_plugin_refresh_time_; // Initialized to 0. + // A list of all Ppapi plugin processes for this renderer. + std::vector > ppapi_plugin_hosts_; + // A callback to create a routing id for the associated renderer process. scoped_ptr::Type> next_route_id_callback_; @@ -501,6 +503,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, // Handles file utilities messages. scoped_refptr file_utilities_dispatcher_host_; + // Handles mime registry requests. + scoped_refptr mime_registry_dispatcher_; + DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter); }; diff --git a/chrome/browser/renderer_host/test/render_process_host_browsertest.cc b/chrome/browser/renderer_host/test/render_process_host_browsertest.cc index 537b03a..f1b8bec 100644 --- a/chrome/browser/renderer_host/test/render_process_host_browsertest.cc +++ b/chrome/browser/renderer_host/test/render_process_host_browsertest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" @@ -58,7 +58,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DISABLED_ProcessOverflow) { // Create a new TYPE_NORMAL tab. It should be in its own process. GURL page1("data:text/html,hello world1"); - browser()->ShowSingletonTab(page1); + browser()->ShowSingletonTab(page1, false); if (browser()->tab_count() == tab_count) ui_test_utils::WaitForNewTab(browser()); tab_count++; @@ -72,7 +72,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DISABLED_ProcessOverflow) { // Create another TYPE_NORMAL tab. It should share the previous process. GURL page2("data:text/html,hello world2"); - browser()->ShowSingletonTab(page2); + browser()->ShowSingletonTab(page2, false); if (browser()->tab_count() == tab_count) ui_test_utils::WaitForNewTab(browser()); tab_count++; @@ -87,7 +87,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DISABLED_ProcessOverflow) { // bug 43448 where extension and DOMUI tabs could get combined into normal // renderers. GURL history(chrome::kChromeUIHistoryURL); - browser()->ShowSingletonTab(history); + browser()->ShowSingletonTab(history, false); if (browser()->tab_count() == tab_count) ui_test_utils::WaitForNewTab(browser()); tab_count++; @@ -100,7 +100,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, DISABLED_ProcessOverflow) { // Create a TYPE_EXTENSION tab. It should be in its own process. // (the bookmark manager is implemented as an extension) GURL bookmarks(chrome::kChromeUIBookmarksURL); - browser()->ShowSingletonTab(bookmarks); + browser()->ShowSingletonTab(bookmarks, false); if (browser()->tab_count() == tab_count) ui_test_utils::WaitForNewTab(browser()); tab_count++; diff --git a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc index b75c09b..c93a3a5 100644 --- a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc +++ b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc @@ -4,9 +4,9 @@ #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/browser.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "net/test/test_server.h" diff --git a/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc index 2e7c56b..bf347a6 100644 --- a/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc +++ b/chrome/browser/renderer_host/test/render_view_host_manager_browsertest.cc @@ -5,13 +5,12 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/ref_counted.h" -#include "base/stringprintf.h" -#include "chrome/browser/browser.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_details.h" @@ -30,23 +29,18 @@ class RenderViewHostManagerTest : public InProcessBrowserTest { EnableDOMAutomation(); } - std::string GetFileWithHostAndPortReplacement( - const std::string& original_path, - const net::HostPortPair& host_port_pair) const { - return StringPrintf("%s?replace_orig=%s&replace_new=%s", - original_path.c_str(), - kReplaceText_, - host_port_pair.ToString().c_str()); + static bool GetFilePathWithHostAndPortReplacement( + const std::string& original_file_path, + const net::HostPortPair& host_port_pair, + std::string* replacement_path) { + std::vector replacement_text; + replacement_text.push_back( + make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); + return net::TestServer::GetFilePathWithReplacements( + original_file_path, replacement_text, replacement_path); } - - private: - static const char* const kReplaceText_; }; -// static -const char* const RenderViewHostManagerTest::kReplaceText_ = - "REPLACE_WITH_HOST_AND_PORT"; - // Test for crbug.com/24447. Following a cross-site link with rel=noreferrer // and target=_blank should create a new SiteInstance. IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, @@ -59,9 +53,11 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ASSERT_TRUE(https_server_.Start()); // Load a page with links that open in a new window. - std::string replacement_path = GetFileWithHostAndPortReplacement( + std::string replacement_path; + ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( "files/click-noreferrer-links.html", - https_server_.host_port_pair()); + https_server_.host_port_pair(), + &replacement_path)); ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(replacement_path)); @@ -105,9 +101,11 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ASSERT_TRUE(https_server_.Start()); // Load a page with links that open in a new window. - std::string replacement_path = GetFileWithHostAndPortReplacement( + std::string replacement_path; + ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( "files/click-noreferrer-links.html", - https_server_.host_port_pair()); + https_server_.host_port_pair(), + &replacement_path)); ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(replacement_path)); @@ -151,9 +149,11 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ASSERT_TRUE(https_server_.Start()); // Load a page with links that open in a new window. - std::string replacement_path = GetFileWithHostAndPortReplacement( + std::string replacement_path; + ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( "files/click-noreferrer-links.html", - https_server_.host_port_pair()); + https_server_.host_port_pair(), + &replacement_path)); ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(replacement_path)); diff --git a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc index ff93b3d..dafd77b 100644 --- a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc +++ b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc @@ -6,12 +6,12 @@ #include #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/render_messages.h" #include "chrome/common/notification_type.h" #include "chrome/test/in_process_browser_test.h" diff --git a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc index 0779b00..06ce085 100644 --- a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc +++ b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc @@ -6,10 +6,10 @@ #include "base/message_loop.h" #include "base/process_util.h" -#include "chrome/browser/browser.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/web_cache_manager.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc index cc4a75c..a1a94bd 100644 --- a/chrome/browser/renderer_preferences_util.cc +++ b/chrome/browser/renderer_preferences_util.cc @@ -33,6 +33,7 @@ void UpdateFromSystemSettings(RendererPreferences* prefs, Profile* profile) { #endif // !defined(TOOLKIT_VIEWS) #if defined(OS_CHROMEOS) + prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0); prefs->active_selection_bg_color = SkColorSetRGB(0xDC, 0xE4, 0xFA); prefs->active_selection_fg_color = SK_ColorBLACK; prefs->inactive_selection_bg_color = SkColorSetRGB(0xF7, 0xF7, 0xF7); diff --git a/chrome/browser/resources/filebrowse.html b/chrome/browser/resources/filebrowse.html index 5c33205..5f465c5 100644 --- a/chrome/browser/resources/filebrowse.html +++ b/chrome/browser/resources/filebrowse.html @@ -1778,7 +1778,7 @@ function createNewList(title, results, main, path) { if (inFullMode) { divTitle.style['text-align'] = 'center'; } - divTitle.innerHTML = title; + divTitle.innerText = title; if (inFullMode && (path.length != 0)) { var popOutButton = document.createElement('div'); popOutButton.innerHTML = '∏'; diff --git a/chrome/browser/resources/guest_session_tab.html b/chrome/browser/resources/guest_session_tab.html new file mode 100644 index 0000000..06a99be --- /dev/null +++ b/chrome/browser/resources/guest_session_tab.html @@ -0,0 +1,25 @@ + + + + + + + + +
+ + +
+ + + diff --git a/chrome/browser/resources/incognito_tab.css b/chrome/browser/resources/incognito_tab.css new file mode 100644 index 0000000..154f727 --- /dev/null +++ b/chrome/browser/resources/incognito_tab.css @@ -0,0 +1,35 @@ +body { + margin: 10px 8px; +} +html[dir="ltr"] .icon { + float: right; + margin: 0 6px 0 3px; + -webkit-transform: scale(-1, 1); +} +html[dir="rtl"] .icon { + float: left; + margin: 0 3px 0 6px; +} +.content { + border-radius: 5px 5px; + background-color: #eee; + color: black; + padding: 10px; + max-width: 600px; + margin-left: auto; + margin-right: auto; + margin-top: 66px; +} +.extensionsmessage { + color: black; + padding: 10px; + max-width: 600px; + margin-left: auto; + margin-right: auto; + margin-top: 5px; +} +.extensionicon { + float: left; + margin: 10px 5px 0 0px; + width: 30px; +} diff --git a/chrome/browser/resources/incognito_tab.html b/chrome/browser/resources/incognito_tab.html index 67846e5..03dad1d 100644 --- a/chrome/browser/resources/incognito_tab.html +++ b/chrome/browser/resources/incognito_tab.html @@ -2,43 +2,7 @@ - + @@ -109,24 +115,26 @@ iframe { -